ArrayList and Map problem in grails - exception

I have a service that contains a map:
static Map cargosMap = ['1':'item1','2':'item 2','3':'item 3']
that is returned via a method in the service:
static Map getCargos() {
[cargosMap]
}
A controller calls it like this:
def mform = {
Map cargos = empService.getCargos()
[cargos:cargos]
}
In the gsp, I have the select:
<g:select name="cg1" from="${cargos}" />
But I'm getting the exception:
Error 500: Executing action ....caused exception:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object
...
with class 'java.util.ArrayList' to class
'java.util.Map'
Any clues ? Thanks

Looks to me like you're wrapping the map in an ArrayList in getCargos(). Why not just: static getCargos() { cargosMap }. Or, better yet, just rename cargosMap to cargos and Groovy will create the getter for you.

Related

Parse json and unable to access javascript object

I am passing a json object to the client side from java object with a time and value as attributes with gson
this.template.convertAndSend("/topic/123", gson.toJson(object, type));
and on the client side i have the following code where the json object data is stored in the body of the payload but I am unable to access the properties with obj.time or obj.value, it tells me undefined after it is parsed, I tried showing the entire 'obj' itself and the format seems fine however:
var subscription_callback1 = function(payload) {
var obj = JSON.parse(payload.body);
alert(obj);
};
output with alert(obj)
{"time":"3:00:34","value":"7989797"}
Nevermind solved. Since I am transfering STOMP protocol messages with the Spring 4 framework. I opted to use the Jackson2 message converter instead of directly using gson and it seems to work
#Configuration
#EnableWebSocketMessageBroker
public class MessageBrokerConfigurer extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
messageConverters.add(new MappingJackson2MessageConverter());
return true;
}
then i directly put my java object into the send function instead of using gson to convert it as above
this.template.convertAndSend("/topic/123", event)

JSON, JAXB,JSON Rest

I created a Rest Service which has is working fine in XML request ( Rest Service input JAXB generated class ). When I am trying to send a Json Request, It's throwing an exception.
SEVERE: The exception contained within MappableContainerException could not be mapped to a response, re-throwing to the HTTP container
org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class Transaction] from JSON String; no single-String constructor/factory method (through reference chain:
class Transaction which is inner class .
My Request class is generated from schema using JAXB, My getter method is like below but no setter method.
public List<Transaction> getORIG() {
if (origtrans == null) {
origtrans = new ArrayList<Transaction>();
}
return this.origtrans;
}
My Json Request below
{
"LOB_CD": "42424"
"ORIGINALTRANSACTION" : [
"LOGON_ID" : "TEST"
]
}
When I am addiong original Transaction it's throwing an error otherwise it's working fine.
Can you please help me out with this.
Thanks in advance.
First of all make sure you are using a valid JSON, like:
{
"LOB_CD": "42424",
"ORIGINALTRANSACTION": {
"LOGON_ID": "TEST"
}
}
Also, it would be nice if you could show us the Transaction class.
It works.
I did following steps
1) Added an empty constructor
2) Added this annotation for the list
#JsonDeserialize(as=ArrayList.class, contentAs=Transaction.class)
3) change a Json Object to
{ "LOB_CD": "42424" "ORIGINALTRANSACTION" : [ { "LOGON_ID" : "TEST" } ] }
Thanks a lot,
Patel

Grails: setting transient fields in the map constructor

I'm trying to persist Maps of properties as single JSON-encoded columns, as shown in this question.
The problem I'm having is that apparently transient properties cannot be set in the default map constructor. Given any transient field:
class Test {
//...
String foo
static transients = ['foo']
}
It seems that the map constructor (which Grails overrides in various ways) simply discards transient fields:
groovy:000> t = new Test(foo:'bar')
===> Test : (unsaved)
groovy:000> t.foo
===> null
While direct assignment (through the setter method) works as expected:
groovy:000> c.foo = 'bar'
===> bar
groovy:000> c.foo
===> bar
Is there a way to make the map constructor accept transient fields?
Or rather: is there a better way to persist a Map as a single JSON-encoded DB field, rather than the method shown in the linked question?
Here's the complete example:
import grails.converters.JSON
class JsonMap {
Map data
String dataAsJSON
static transients = ['data']
def afterLoad() { data = JSON.parse(dataAsJSON) }
def beforeValidate() { dataAsJSON = data as JSON }
}
I can set data using the setter (which will then be converted into dataAsJSON) but not using the map constructor.
The map constructor in GORM uses the data binding mechanism, and transient properties are not data-bindable by default. But you can override this using the bindable constraint
class Test {
//...
String foo
static transients = ['foo']
static constraints = {
foo bindable:true
}
}
I've also replied to your original question, that you don't need json conversion to achieve what you need. However, If you need json conversion badly, why don't you implement it in your getters/setters?
class Test {
String propsAsJson
static transients = ['props']
public Map getProps() {
return JSON.parse(propsAsJson)
}
public void setProps(Map props) {
propsAsJson = props as JSON
}
}
//So you can do
Test t = new Test(props : ["foo" : "bar"])
t.save()
In this way you encapsulate the conversion stuff, and in DB you have your properties as Json.
You can simplify your case by adding the JSON-conversion methods to your domain class, they should have nothing to do with GORMing:
class Test {
String title
void titleFromJSON( json ){
title = json.toStringOfSomeKind()
}
def titleAsJSON(){
new JSON( title )
}
}

How do I render plain object as JSON, XML in Grails?

I have a controller (RestfulController) code similar to the following:
def doSomethingAwesome() {
Domain domainObject = prepareDomainObject()
//do something on the domain object
Model model = new Model(name: domainObject.name, description: domainObject.description)
respond model
}
As can be seen, I'm trying to respond with data wrapped inside a Model object. However, Model class is not a domain class; it's just a plain Groovy class. When I try to test this code in isolation, I get it to pass, but when I test it with all the other tests, I get GroovyCastException saying the object cannot be cast to JSON.
Some of the articles that came up of my searches suggest I put the model object inside a map then have that map get rendered. Something like:
render ['model': model] as JSON
However, this isn't how I'd like the response message to be. In addition, the XML message would look very different.
The Grails 2.4.3 demo project at https://github.com/jeffbrown/pogorespond demonstrates passing a POGO (not a domain class) to the respond method. https://github.com/jeffbrown/pogorespond/blob/1646c64fe2b37856fc87b64ae1cf5a6c4fd44cb1/grails-app/controllers/demo/DemoController.groovy contains the following:
package demo
class DemoController {
static responseFormats = ['json']
def index() {
def m = new Model(name: 'Some Name', description: 'Some Description')
respond m
}
}
class Model {
String name
String description
}

error doing nested resource in grails

i am try to do nested resource call using angular and grails.
in my account domain i map domain this way:
example:
class Account {
static hasMany=[contacts:Contacts,users:User_BE];
}
and in contact domain
example:
class Contacts {
static belongsTo=[accounts:Account];
}
my json structure is like this:
{"accountType":"Single","traderwinkel":true,"lynxAgro":true,"contacts":[{"class":"com.crm.contacts","name":"abc"}]}
i am getting this error:
null id in com.crm.Contacts entry
and i am also try to send json without using array like this:
{"accountType":"Single","traderwinkel":true,"lynxAgro":true,"contacts":{"class":"com.crm.contacts","name":"abc"}}
but got same error like above.
and also i have used restfullcontroller:
class AccountController extends RestfulController {
static responseFormats = ['json', 'xml']
}
please suggest me how should i need to structure and send json data