I'm currently developing a grails application (Version 3.1.2) and I got a frustrating error that I currently cannot solve.
Lets have an example case:
// Domain classes
class RootBean {
NestedBean nestedBean
}
class NestedBean {
int nestedInteger
}
not much to say about it, its just an 1 to 1 relation with no back reference
Now lets specify my problem: I've got a create and an edit view which both render a editTemplate with all the possible inputs. With a new Object (create) everythings works fine but with a existing Object I want to update I get this GSP Error Message:
URI
/VMPMessung/edit/2
Class
groovy.lang.MissingPropertyException
Message
Request processing failed; nested exception is org.grails.gsp.GroovyPagesException: Error processing GroovyPageView: [views/rootBean/edit.gsp:13] Error executing tag <g:render>: [views/rootBean/_editTemplate.gsp:1] Error executing tag <g:form>: [views/rootBean/_editTemplate.gsp:150] Error executing tag <f:widget>: No such property: nestedInteger for class: RootBean
Caused by
No such property: nestedInteger for class: RootBean
The GSP Code:
<f:widget class="form-control"
property="nestedBean.nestedInteger"
bean="RootBean"/>
I also debugged through the Taglibary and discoverd that it's going wrong cause of the Type Integer, I got other String fields in the real object and they are working fine. The Error is thrown in the FormFieldsTagLib class at line 569
private CharSequence renderNumericInput(BeanPropertyAccessor propertyAccessor,Map model, Map attrs) {
if (!attrs.type && model.constraints?.inList) {
attrs.from = model.constraints.inList
if (!model.required) attrs.noSelection = ["": ""]
return g.select(attrs)
} else if (model.constraints?.range) {
attrs.type = attrs.type ?: "range"
attrs.min = model.constraints.range.from
attrs.max = model.constraints.range.to
} else {
attrs.type = attrs.type ?: getDefaultNumberType(model )
if (model.constraints?.scale != null) attrs.step = "0.${'0' * (model.constraints.scale - 1)}1"
if (model.constraints?.min != null) attrs.min = model.constraints.min
if (model.constraints?.max != null) attrs.max = model.constraints.max
}
if(propertyAccessor != null && attrs.value) {
attrs.value = g.fieldValue(bean: propertyAccessor.rootBean, field: propertyAccessor.propertyName)
// This call causes the Error
// Debugging Values: propertyAccessor.rootBean: RootBean,
// propertyAccessor.propertyName: nestedInteger
}
return g.field(attrs)
}
I guess they are trying to find the fieldName on the RootBean instead of the NestedBean but am I doing something wrong or is it a Bug on Grails side?
Hopefully some of you knows an answer to this, its really much a blocker for me :(
I am having the same issue, the weird thing is that in I am not having problem, I have it only in
I could fix it with a workaround, implementing in RootBean class a getter for nestedInteger:
def int getNumber() {
return nestedBean?.nestedInteger
}
That worked for me.
Could you solve it properly?
Related
I have a controller like this:
class DemoController {
def index() {
DemoCommand cmd = new DemoCommand(demoAmount: 'foo')
render cmd.validate() ? "Validation successful" : "Validation failed, ${cmd.errors}"
}
}
class DemoCommand implements Validateable {
String demoAmount
static constraints = {
demoAmount nullable: false
}
Long getDemoAmountAsLong() {
demoAmount?.isNumber() ? new Long(demoAmount) : null
}
}
Hitting the index action shows validation failed, stating demoAmountAsLong cannot be null. There were a couple bugs reported in 3.1.2 (https://github.com/grails/grails-core/issues/9754) on this issue but looked like they were resolved. I've tested this in both 3.1.11 and 3.2.11 with the same results. I must be missing something? I've tried making the getter method transient, or adding static transients = ['demoAmountAsLong'] without luck.
I'm using grails 2.1.1 and I getting the message "No signature of method: ClassA.save() is applicable for argument types: () values: []" when trying to save an object in production environment.
This is the code:
def method(campId, userId){
ClassA cbl = new ClassA()
cbl.userId = userId
cbl.campId = campId
cbl.save(flush:true)
}
This code works fine in development but when I execute the code in production I have this problem.
A couple of things to look out for
You say it works in dev but not in production so the first starting point of any investigation is what is the difference between both. Meaning do a show create table class_a on both product/development environments.
It maybe something has changed and it has some required value that is no longer provided
Step 2:
It is obviously not saving so you need to see if any errors are thrown
def method(campId, userId){
if (campId && userId) {
try {
ClassA cbl = new ClassA()
cbl.userId = userId
cbl.campId = campId
if (!cbl.save(flush:true)) {
//println cbl.errors
//log.info "${cbl.errors}"
}
}catch (Exception e) {
//println "E really happended $e"
}
}else {
println "oh my ... a certain value has not been provided"
}
}
You see in above code an if statement to ensure both values provided since you are setting without checking, the try catch was last alternative to try but the if it saves println error is the next thing to try
Finally there are many ways to save a class just in case as Anton suggest you have some other inbuild functions in ClassA when it comes to saving and new ClassA() may cause an issue maybe since you are missing
ClassA() {
super()
}
or something then I would lastly try this as a test
ClassA cbl = new ClassA(userId:userId,campId:campId)?.save(flush:true)
Same logic applied differently
I have a property with custom data binding like this:
class User {
// Custom data binding for the image
#BindUsing({ obj, source ->
def imageFile = source['image']
if (imageFile && imageFile.size > 0) {
Document image = obj.image ?: new Document()
image.setFile(imageFile)
if(!image.save()) {
throw new Exception('Non localizable message')
}
return image
}
})
Document image
...
}
If an exception is thrown (like in my example) it is converted to a ValidationException with always the same generic error codes for typeMismatch:
[com.example.security.User.image.typeMismatch.error,com.example.security.User.image.typeMismatch,user.image.typeMismatch.error,user.image.typeMismatch,typeMismatch.com.example.security.User.image,typeMismatch.image,typeMismatch.com.example.common.Document,typeMismatch]
The defaultMessage of the ValidationException is the message of the exception that was thrown in #BindUsing. So to get localized messages one would have to inject messageSource somehow into #BindUsing and localize the message of the exception that is thrown.
What is the correct way to return an error or an error code from #BindUsing?
I have the following command object
class SaleDetailCommand implements Serializable {
Item item
Presentation presentation
String measure
Integer quantity
BigDecimal total
static constraints = {
importFrom SaleDetail
}
def beforeValidate() {
total = item.sellingPrice * quantity
}
}
in the above command object I am trying to calc total just before command object is validated, but beforeValidate is not call it when i try this code from controller
if (command.hasErrors()) {
command.errors.allErrors.each { error ->
log.error "[$error.field: $error.defaultMessage]"
}
return error()
}
I get this message in console
Error 2014-09-23 08:06:26,585 [http-bio-8080-exec-8] ERROR builder.ActionDelegate - [total: Property [{0}] of class [{1}] cannot be null]
I also tried !command.validate
Which is solution to perform this task?
thanks for your time!
I want to upload an image using a groovy on grails.
My gsp page is as follows (I am showing a simplified version of the original)
<g:form controller="post" action="save" enctype="multipart/form-data">
My picture <input type="file" name="myPicture" />
<g:submitButton name="submit" value="Save"/>
</g:form>
My domain class is as follows:
class Post {
byte[] myPicture
static mapping = {
myPicture type: "blob"
}
I need this mapping otherwise MySql will create a smallblob which is to small to fit the images
static constraints = {
myPicture(nullable:false)
}
}
At the controller I have an action called save which is as follows:
def save = {
def post = loadPost(params.id)
post.properties = params
if(post.save()) {
print "hallo world"
redirect(action:'list', params:params)
} else {
render(view:'edit', model:[post:post])
}
}
The exception is thrown when I try to save the image at the DB.
2009-04-27 18:16:07,319 [20806951#qtp0-0] ERROR errors.GrailsExceptionResolver - java.lang.ClassCastException: [B cannot be cast to java.sql.Blob
org.codehaus.groovy.runtime.InvokerInvocationException: java.lang.ClassCastException: [B cannot be cast to java.sql.Blob
Any hint why is this?
BTW, I've seen in a tutorial that images were handled as strings but it didn't work
as well.
I found a similar question on Nabble:
http://www.nabble.com/MySQL-and-Blobs-td16116885.html
Two possible solutions are suggested:
Change the constraints of the blob property to a large max-size, to stop it from using "TinyBlob".
Use the Hibernate Blob implementation instead of byte[] for the property's type declaration. This will require you stream data into the Blob, instead of direct assignment, but the post above gives code to do so.
Can you try using Spring's MultipartFile within your loadPost() method?
Here's an example from the docs:
def upload = {
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File('/some/local/dir/myfile.txt') )
response.sendError(200,'Done');
}
else {
flash.message = 'file cannot be empty'
render(view:'uploadForm')
}
}
I believe you can access f.bytes directly.
try this way:
def save = {
def post = loadPost(params.id)
def f = request.getFile('myPicture')
post.myPicture = f.getBytes()
post.pictureType = f.getContentType()
if(post.save()) {