I'm trying to render command validation errors as json but I'm getting an exception. The command object is using joda time DateTime objects instead of java.util Date objects. The code to do the json rendering looks like:
def results = eventSaleDataCommand.errors.fieldErrors.toList()
def errors = []
for (error in results) {
errors.add([
'type' : 'invalid_entry',
'field' : error.field,
'rejected_value': error.rejectedValue,
'message' : error.defaultMessage
])
}
render errors as JSON
The exception I'm getting is:
Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.joda.time.tz.DateTimeZoneBuilder$PrecalculatedZone with modifiers "public".
Anyone know how to get around this?
Implementing a Joda converter did the trick. Thanks.
Related
I'm trying to save nested person, which is json array and complains about requiring a Set.
Another problem I encountered, is that another field date cannot be null, but contains value already.
What I need to do before for adding params into my object or I have to change my json is built? I'm trying to save json post like this:
// relationship of Test
//static hasMany = [people: Person, samples: Sample]
def jsonParams= JSON.parse(request.JSON.toString())
def testInstance= new Test(jsonParams)
//Error requiring a Set
[Failed to convert property value of type 'org.codehaus.groovy.grails.web.json.JSONArray' to required type 'java.util.Set' for property 'people'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.Person] for property 'people[0]': no matching editors or conversion strategy found]]
//error saying its null
Field error in object 'com.Test' on field 'samples[2].dateTime': rejected value [null]; codes [com.Sample]
//...
"samples[0].dateTime_hour":"0",
"samples[0].dateTime_minute":"0",
"samples[0].dateTime_day":"1",
"samples[0].dateTime_month":"0",
"samples[0].dateTime_year":"-1899",
"samples[0]":{
"dateTime_minute":"0",
"dateTime_day":"1",
"dateTime_year":"-1899",
"dateTime_hour":"0",
"dateTime_month":"0"
},
"people":[
"1137",
"1141"
], //...
First off, ths line is unnecessary:
def jsonParams= JSON.parse(request.JSON.toString())
The request.JSON can be directly passed to the Test constructor:
def testInstance = new Test(request.JSON)
I'm not sure what your Person class looks like, but I'm assuming those numbers (1137, 1141) are ids. If that is the case, then your json should work - there's a chance that passing the request.JSON directly could help. I tested your JSON locally and it has no problem associating the hasMany collection. I also used:
// JSON numbers rather than strings
"people": [1137, 1141]
// using Person map with the id
"people: [{
"id": 1137
}, {
"id": 1141
}]
Both of these worked as well and are worth trying.
Concerning the null dateTime, I would rework your JSON. I would send the dateTime in a single field, instead of splitting the value into hour/minute/day/etc. The default formats are yyyy-MM-dd HH:mm:ss.S and yyyy-MM-dd'T'hh:mm:ss'Z', but these can be defined by the grails.databinding.dateFormats config setting (config.groovy). There are other ways to do the binding as well (#BindingFormat annotation) but it's going to be easiest to just send the date in a way that grails can handle without additional configuration.
If you are dead set on splitting the dateTime into pieces, then you could use the #BindUsing annotation:
class Sample{
#BindUsing({obj, source ->
def hour = source['dateTime_hour']
def minute = source['dateTime_minute']
...
// set obj.dateTime based on these pieces
})
Date dateTime
}
An additional comment on your JSON, you seem to have samples[0] defined twice and are using 2 syntaxes for your internal collections (JSON arrays and indexed keys). I personally would stick with a single syntax to clean it up:
"samples": [
{"dateTime": "1988-01-01..."}
{"dateTime": "2015-10-21..."}
],"people": [
{"id": "1137"},
{"id": "1141"}
],
code is an integer, so it's declared as an Int in my subclass.swift file. The subclass is in the same format as the JSON, to enable saving the JSON directly to Realm.
I get this JSON:
...
"code": 301
...
And this is how I'm saving it:
realm.create(Student.self, value: jsonStudent, update: true)
But Realm throws this:
failed: caught "RLMException", "Invalid value '301' for property 'code'"
At first I thought the '301' might be getting parsed as a string, but that was not the case, calling 'dynamicType' on it in the debugger returns NSCFNumber, which is expected.
What's wrong?
NSJSONSerialization will convert {"code": 301} to an NSNumber of type q, which is integer. So the fact that you're getting an invalid property implies that the code property on your Realm model is of a different type (maybe Float or Double)?
Could you share your model definition here?
If your code property is actually Int or a variation thereof (Int32, Int64, etc.), this would imply there's a bug in Realm and I'd recommend that you open an issue at https://github.com/realm/realm-cocoa/issues.
In my grails domain I am having a field Date i.e. java.util.Date.
In my controller I am loading this date from params using SimpleDateFormate.
To be precise assume that params.date is something like '20/02/2013 02:30 am'. In the controller I load this as follows:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm a");
domainInstance.date = simpleDateFormat.parse(params.date)
While this statement executes no error is detected. However when the domain Instance is being saved error is generated that
[typeMismatch.Domain.date,typeMismatch.date,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes
[Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'date'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "20/02/2013 02:30 am"]
Can you anyone tell me where things are going wrong.
I am pretty sure that SimpleDateFormat parses String to Date. Why is it accepting as String.
Thanks for the response, but I have found the solution to the problem. The problem was something like this.
I was instantiating my domainInstance as domainInstance = new Domain(params)
This was the first statement in the controller action.
When this statement is executed params holds the date in the format "dd/MM/yyyy HH:mm a". Hence this statement adds an error in the domainInstance object.
Later after using SimpleDateFormat the variable is updated but the error still remains in the object because of which the error crops up.
The solution to this error is immediately after the statement 'domainInstance = new Domain(params)' call the statement domainInstance.clearErrors().
This clears up all the errors in the object. Later when the domainInstance is being saved validate is called. In case validate fails due to some other error then the respective error is added at that time.
Rammohan
Grails 2.3.1 is actual problem
def domain = new FooBar(params)
domain.clearErrors()
domain.save(flush:true) // <--- validation will be there
if (doamin.hasErrors()) {
... do something
}
You can try:
domainInstance.date = new Date().parse("dd/MM/yyyy HH:mm a", params.date)
I am trying to pull all the PostOrder's out where a child instance is present
My domain is as follows:
class PostOrder {
String pOrder
Date dateCreated
Picture picture
Post posts
Video video
static hasMany = [children : Child]
}
and the method i am trying to use to get the objects is:
def getAllInOrder(Child child){
def json = PostOrder.findAllByChildren(child, sort: 'dateCreated', order: 'desc') as JSON
return json
}
I am just getting sql exceptions from this.
Any Ideas?
also these are my exceptions:
util.JDBCExceptionReporter No value specified for parameter 1
errors.GrailsExceptionResolver SQLException occurred when processing request: [GET] /FYP/profile/appPosts - parameters:
child: 1
No value specified for parameter 1. Stacktrace follows:
java.sql.SQLException: No value specified for parameter 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.PreparedStatement.checkAllParametersSet(PreparedStatement.java:2595)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2571)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2497)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2251)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.grails.datastore.gorm.GormStaticApi$_methodMissing_closure2.doCall(GormStaticApi.groovy:105)
at com.fyp.timeline.ProfileController$$ENmIB8q0.getAllInOrder(ProfileController.groovy:636)
at com.fyp.timeline.ProfileController$$ENmIB8q0.appPosts(ProfileController.groovy:624)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Try
PostOrder.findAllByChildren(child, [sort: 'dateCreated', order: 'desc'])
Although I don't think this will fix your problem entirely because in this instance, child is expected to be a list. Try this:
PostOrder.all.findAll{it.children.contains(child)}
It seems like there should be a better way to do that, maybe someone else can ring in.
I am trying to do a safe insert using GORM for Mongo's low-level API.
I have reproduced the problem in a clean Grails project like follows:
Create a new Grails project
Uninstall the Hibernate plugin
Install the GORM for Mongo plugin
Create a controller with the following action
import com.mongodb.*
class TestController {
def mongo
def index = {
def database = mongo.getDB("ExampleDatabase")
def collection = database.getCollection("ExampleCollection")
def document = new BasicDBObject();
document.put("key", "value")
collection.insert(document, WriteConcern.SAFE)
render ""
}
}
When firing the action, the following exception is thrown:
2011-07-27 12:53:03,161 [http-8080-1] ERROR errors.GrailsExceptionResolver - Exception occurred when processing request: [GET] /WriteConcern.SAFE-test/test/index
Stacktrace follows:
groovy.lang.MissingPropertyException: No such property: value for class: com.mongodb.WriteConcern
at com.gmongo.internal.Patcher$__converAllCharSeqToString_closure2.doCall(Patcher.groovy:81)
at com.gmongo.internal.Patcher._converAllCharSeqToString(Patcher.groovy:80)
at com.gmongo.internal.Patcher$_converAllCharSeqToString.callStatic(Unknown Source)
at com.gmongo.internal.Patcher$_converAllCharSeqToString.callStatic(Unknown Source)
at com.gmongo.internal.Patcher._convert(Patcher.groovy:69)
at com.gmongo.internal.Patcher$_convert.callStatic(Unknown Source)
at com.gmongo.internal.Patcher$__patchInternal_closure1.doCall(Patcher.groovy:31)
at writeconcern.safe.test.TestController$_closure1.doCall(TestController.groovy:17)
at writeconcern.safe.test.TestController$_closure1.doCall(TestController.groovy)
at java.lang.Thread.run(Thread.java:680)
If I change the action to use the Mongo Java API as follows:
def index = {
def database = new Mongo().getDB("ExampleDatabase")
def collection = database.getCollection("ExampleCollection")
def document = new BasicDBObject();
document.put("key", "value")
collection.insert(document, WriteConcern.SAFE)
render ""
}
Now it works and the document is persisted to the Mongo database as expected.
My question is this: Is this a bug with the GMongo wrapper, or then how should safe writes be done using the low level API?
This appears due to the GMongo library and how it patches the DBCollection object to handle passing of Map objects to the insert method and converts them. It assumes that all of the arguments of the insert method are Map objects and will then try to get the value property from the Map.Entry.
Looking at the source of Patcher.groovy from GMongo library you'll see the function _convert() that attempts to do this. It looks like a fork of the Github project with type check on the argument (either to see if it's a WriteConcern or to check if it's actually a Map before passing to the _converAllCharSeqToString) is necessary.
EDIT:
I created a pull request on Github for the appropriate code change, but as with all things Groovy, patching the class can also help. You can "patch" the WriteConcern class in your BootStrap.groovy to have a getValue method and that will allow you to pass the parameter in:
def init = { servletContext ->
com.mongodb.WriteConcern.metaClass.getValue = { null }
}