Couchbase gives badarg error - couchbase

I Created simple couchbase spatial view to get list of report, but it gives {error: "error", reason: "badarg"} error.
Here is my view:-
function (doc, meta) {
if (doc.type == "report" && doc.location && doc.location.type && doc.location.coordinates) {
if(doc.location.type=='Point'){
emit(doc.location, {
summary:doc.summary
});
}
}
}
why this badarg error is coming, same view work on different doc.type

I used your View on an empty bucket and used the example query on the View UI page to test it:
_design/dev_test/_spatial/test?stale=false&connection_timeout=60000&limit=10&skip=0
On an empty bucket I got a successful but empty result, which was expected. As soon as I added the example document above, then I get your same error:
{error: "error", reason: "badarg"}
After some reducing of the View and of the document I found that with this particular document it fails because there are double quotes around the latitude and longitude coordinates in your location field (doc.location.coordinates). They need to be unquoted numbers if you want to pass your location field in as the geometry for the key. More on spatial views can be found here: http://docs.couchbase.com/admin/admin/Views/views-geospatial.html
Ideally, you would fix your issue by fixing the documents in your bucket. Whatever is creating your location field is putting the coordinates in as strings when they need to be floats. If that is not possible then you can try something similar to the following to doing the conversion in your View, at the very least this should prove that the string coordinates are the root cause of your problem:
function (doc, meta) {
if (doc.type == "report" && doc.location && doc.location.type && doc.location.coordinates) {
if(doc.location.type=='Point'){
for(var i=0; i<doc.location.coordinates.length; i++){
doc.location.coordinates[i] = parseFloat(doc.location.coordinates[i]);
}
emit(doc.location, {summary:doc.summary});
}
}
}

Related

Error: Converting circular structure to JSON

I have a problem with my application. Anyone can help me?
Error:
Converting circular structure to JSON
My Service to create items and save on localstorage:
addItem(item: Item): void {
this.itens.unshift(item);
let itens;
if (localStorage.getItem('itens') == null){
itens = [];
itens.unshift(itens);
localStorage.setItem('itens', JSON.stringify(itens));
} else {
JSON.parse(localStorage.getItem('itens'));
itens.unshift(itens);
localStorage.setItem('itens', JSON.stringify(itens));
}
}
And my component.ts:
addItem(): void {
this.itemAdicionado.emit({
nome: this.nome,
unidade: this.unidade,
quantidade: this.quantidade,
preco: this.preco,
perecivel: true,
validade: this.validade,
fabricacao: this.fabricacao,
});
this.nome = '';
this.unidade ;
this.quantidade ;
this.preco;
this.validade;
this.fabricacao;
console.log(this.nome, this.unidade, this.quantidade, this.preco, this.validade, this.fabricacao);
}
This isn't an Angular error. It's a JavaScript runtime error thrown by the JSON.stringify function. The error tells you that itens contains a circular object reference. This is OK while you run the application, but when stringifying it causes a problem: the JSON generated would become infinitely long.
As Kevin Koelzer indicated in his answer. The problem is that you wrote itens.unshift(itens);. Basically this adds the array of items to the array of items, thus creating a circular reference. Therefore, writing itens.unshift(item); instead solves your problem and is probably what you intended to do anyway.
itens.unshift(itens);
could this be:
itens.unshift(iten);

Ignore Undefined objects in array of arrays variable

In Google Apps Script, I'm pulling data from an API. In the code below, the "output" variable contains an array of arrays. There is always at least one ["Response"] object, but sometimes there are 2.
My problem is, the code below isn't returning the second object (["Response"][1]) when it is present. I tried removing the "if" statement, but I get an error saying "TypeError: Cannot read property "Product" from undefined".
Does anyone know how to get the second object when it's present and ignore it when it's not?
var data = reportAPI();
var applications = data["applications"];
var output = []
applications.forEach(function(elem,i) {
output.push(["ID",elem["Id"]]);
output.push([elem["Response"][0]["Product"],elem["Response"][0]["Status"]]);
if (["Response"][1] != null) {
output.push([elem["Response"][1]["Product"],elem["Response"][1]["Status"]]);
}
}
P.S. I would even be happy with replacing the undefined object with "", but I'm not sure how to do it.
How about this modification? Please think of this as one of several answers. I used forEach to elem["Response"]. By this, values can be pushed by the number of elem["Response"].
From :
applications.forEach(function(elem,i) {
output.push(["ID",elem["Id"]]);
output.push([elem["Response"][0]["Product"],elem["Response"][0]["Status"]]);
if (["Response"][1] != null) {
output.push([elem["Response"][1]["Product"],elem["Response"][1]["Status"]]);
}
}
To :
applications.forEach(function(elem) {
output.push(["ID",elem["Id"]]);
elem["Response"].forEach(function(elem2) {
output.push([elem2["Product"],elem2["Status"]]);
});
});
If this didn't work, please tell me. I would like to modify.
The example below helps to account for the cases where the Response[0] or Reponse[1] are not "undefined" or "null". Putting !() will turn the Boolean values for "undefined" or "null" to true.
applications.forEach(function(elem,i) {
output.push(["ID",elem.Id]);
if(!(elem.Reponse[0]))
output.push([elem.Response[0].Product,elem.Response[0].Status]);
if (!(elem.Response[1])) {
output.push([elem.Response[1].Product,elem.Response[1]Status]);
}
}

Response custom error when key not satisfies the exact value in couchbase view

I have a document like -
{
"fullUserName": "xxyz",
"userFirstName": "xx",
"userLastName": "xx",
"primaryRole": "xy",
"actualRole": "rrr",
"userId": "abcd1234",
"password":"c28f5c7cb675d41c7763ab0c42d",
"type":"login",
"channels":"*"
}
and view -
function (doc, meta) {
if(doc.userId,doc.password,doc.type){
emit([doc.userId,doc.password,doc.type],doc);
}
}
When the key matches with the docment's property it return the document otherwise it return empty JSON like -
{"total_rows":2,"rows":[
]
}
Now I want to response the error message in JSON format when the key does not match for example-
{
"Error-Code":"400",
"Error-Msg":"user id and password does not match"
}
Is there any way to do so,Please correct if I am moving in the wrong direction.
Thanks in advance.
You shouldn't directly expose the view query result to your users but interpret it instead.
So make a view request, look at the response and do the business logic of checking there. For example:
"if result is empty it can only be because the user is unknown or the password hash didn't match the user, so return a business-specific error message, otherwise carry on with login"
There's no way you can change the behavior and response format of the server, and that doesn't make much sense to do so anyway. This is the API and contract of how you interact with the server. You should add your own business logic in a layer in between.

How can I update an existing JSON object's parameters in Grails?

I'm making a todo list. When first entering the item and adding it to the list, the server works great. It takes the parameters that the user selects and passes them into a list on the server that can be viewed by rendering Item.list(), that looks like so:
[{"class":"server.Item","id":1,"assignedTo":"User 1","comments":null,"completed":false,"creator":"User 1","name":"Task 1","priority":"1","type":"Personal"},
{"class":"server.Item","id":2,"assignedTo":"User 2","comments":null,"completed":false,"creator":"User 2","name":"Er","priority":"3","type":"Work"},
{"class":"server.Item","id":3,"assignedTo":"User 1","comments":null,"completed":false,"creator":"User 2","name":"Ga","priority":"1","type":"Work"}]
Now, the user then has the option to edit the task later. On the client side this works fine, but then I need the user to be able to save the new, updated task.
This is my current update function:
def updateList() {
def newItem = Item.findById(request.JSON.id)
newItem.assignedTo = request.JSON.assignedTo
newItem.comments = request.JSON.comments
newItem.completed = request.JSON.completed
newItem.creator = request.JSON.creator
newItem.name = request.JSON.name
newItem.priority = request.JSON.priority
newItem.type = request.JSON.type
newItem.save(flush: true)
render newItem as JSON
}
This doesn't work, however. I get a null pointer exception that says "Cannot set property "assignedTo" on null object. I'm assuming that the findById request is not getting anything for the JSON object, and thus there is no object to assign values to, however I don't know what the problem is considering the items are in fact being put into the Item.list().
This is called with the following JS function on the client side:
$scope.updateList = function() {
angular.forEach($scope.items, function (item) {
// serverList.save({command: 'updateList'}, item);
$http.post('http://localhost:8080/server/todoList/updateList', item)
.success(function(response) {})
.error(function(response) {alert("Failed to update");});
});
};
This might depend on your Grails version, but you should be able to do this:
def update(Item item) {
if (!item) {
// return a 404
} else {
// you should really use a service and not save
// in the controller
itemService.update(item)
respond item
}
}
Grails is smart enough look that item up since there is an ID in the JSON params, and populate the object correctly.
Sort of a work around for anyone else that may need to do this in a basic manner, what I've done that works is clear the list when "Update List" is clicked, then read back in the values that are currently in the client side list.
Grails:
def clearList() {
Item.executeUpdate('delete from Item')
render Item.list()
}
def updateList() {
def newItem = new Item(request.JSON)
newItem.save(flush:true)
render newItem as JSON
}
Javascript:
$scope.updateList = function() { // Update list on the server
serverList.get({command: 'clearList'});
angular.forEach($scope.items, function (item) {
serverList.save({command: 'updateList'}, item);
});
};

Alfresco exception message format

I want to show only my message for alfresco workflow exception. But in alfresco exception message format is that
1. exception.class.name
2. ErrorLogNumber
3. Message
For example,
org.alfresco.service.cmr.workflow.WorkflowException: 05130007 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I only want to show 3.Message not 1.exception.class.name and 2.ErrorLogNumber. I can remove ErrorLogNumber from message by adding a custom exception class. But I can't remove 1.exception.class.name from error message.
Let me know how to implement that.
The solution is quite simple. Just throw AlfrescoRuntimeException with your message.
throw new AlfrescoRuntimeException("your.message");
In that case you get a message, but loose exception subtyping.
It is really hard to explain in words how I was suprised when saw exception handling in alfresco javaScript code:
onFormSubmitFailure: function FormManager_onFormSubmitFailure(response)
{
var failureMsg = null;
if (response.json && response.json.message && response.json.message.indexOf("Failed to persist field 'prop_cm_name'") !== -1)
{
failureMsg = this.msg("message.details.failure.name");
}
else if (response.json && response.json.message && response.json.message.indexOf("PropertyValueSizeIsMoreMaxLengthException") !== -1)
{
failureMsg = this.msg("message.details.failure.more.max.length");
}
else if (response.json && response.json.message && response.json.message.indexOf("org.alfresco.error.AlfrescoRuntimeException") == 0)
{
var split = response.json.message.split(/(?:org.alfresco.error.AlfrescoRuntimeException:\s*\d*\s*)/ig);
if (split && split[1])
{
failureMsg = split[1];
}
}
Alfresco.util.PopupManager.displayPrompt(
{
title: this.msg(this.options.failureMessageKey),
text: failureMsg ? failureMsg : (response.json && response.json.message ? response.json.message : this.msg("message.details.failure"))
});
},
As you can see they "catch" class name from java and replace it with message. I hope they provide more extensible way to handle custome exceptions.
P.S. Of course another way is to extend alfresco.js file and add one more if else condition for you exception.
Have you tried to override toString in your exception class? Or maybe to change logger implementation, if output is printed this way.
I had similar problem as you and failed to trace where this message is created even using debugger, quite tricky. Also anyone on Alfresco forums couldn't help me.
I developed a workaround instead of throwing an exception directly in java workflow task, I used a JS validation in form (the way I told you in another post), there I called a java webscript using ajax, which in case of error displayed JS alert box.