Grails 2.0 CreateCriteria private attribute cannot be queried - grails

I'm trying to upgrade my app to Grails 2.0 and I face following problem. I have a private domain attribute with public getter. I'd like to query this attribute in createCriteria and it returns me: "Could not resolve property ..." exception even if the getter is public. I've seen a Jira bug http://jira.grails.org/browse/GRAILS-8498?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
but it's still not workin. Grails 1.3.7 worked fine.
My code is like:
Domain class
class MyClass {
protected boolean reserved = false
protected void setReserved(boolean reserved) {
this.reserved = reserved
}
public boolean getReserved() {
return this.reserved
}
}
Query
def c = MyClass.createCriteria()
def results = c.list {
eq('reserved', true)
}
May be the problem is that 'reserved' attribute name became a reserved keyword in grails because it seems that for other attributes of different names it works...

The problem here is that to enable domain class properties being automatically persistent without having to configure them, fields must be properties, i.e. they have to have a public getter/setter pair of the same type.
Groovy does this for you when you add a public field - it makes the field private and creates a public getter and setter. But if you have a getter or setter already it doesn't do that, and if they're not both public then they're not considered a property (in the JavaBean sense) so the field isn't persistent. So it's more than that the field isn't queryable - it's not even being stored or updated in the database.

After a few minutes of examination, I've realized that the problem is in the protected setter. If I set the setter to public, it works. It seems to be a Grails bug, and therefore I've risen grails bug, see:http://jira.grails.org/browse/GRAILS-8637

Related

Spring Data Rest Binding

I am trying to work with Spring-Data-Rest, but I am hanging that Spring is not binding my body object given via Post.
My domain class looks like:
#Entity
#EqualsAndHashCode
#ToString
public class Rendite{
#Id #GeneratedValue Long id;
double jahresNettoMiete;
public Rendite(){}
}
#RepositoryRestResource(collectionResourceRel = "renditen", path = "renditen")
public interface RenditeRepositoryextends CrudRepository<Rendite, Long> {}
Calling the via Get works fine:
Calling the POST to save an entity calls the Application, too, but it doesnt bind the value to the property:
You appear to be missing getters (and optionally) setters on your entity.
Adding a public getter for the relevant field(s) should allow for both serlialization and deserialization.
See further on this here:
http://www.baeldung.com/jackson-field-serializable-deserializable-or-not
Unintuitively, the getter also makes the private field deserializable
as well – because once it has a getter, the field is considered a
property.
You can control serialization/deserialization in various ways as outlined in the article.
Another approach rather than adding getters would be to use:
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
as outlined in example 4.5 at the below:
http://www.baeldung.com/jackson-annotations

Why do scope modifiers on fields in domain classes prevent validation?

I'm just starting with Grails (coming from Rails) and I noticed that Grails really doesn't seem to like scope modifiers on fields in domain classes.
I had understood that all unscoped fields in a domain class were by default public, but if you actually declare it public, Grails won't validate it.
class Person {
public String firstName
public String middleName
public String lastName
}
If you add a constraint, Grails will throw a NotReadablePropertyException exception when you call validate()
class Person {
public String firstName
public String middleName
public String lastName
static constraints = {
middleName nullable: true
}
}
However if you take out the public declaration, everything works normally.
Can someone explain what's going on behind the scenes with the scoping in domain classes? Hard to understand why explicitly declaring something public which is already public would break the framework. I'm guessing you wouldn't want to declare anything 'private' either, although it would be nice if there was away that a fields which shouldn't be manipulated directly could be hidden from consumers of the domain class.
When you add a field to a Groovy class without a scope modifier, it's more that it's inferred to be public than being actually public. The compiler converts the field to a private field and generates a public getter and a setter for it, although it won't overwrite a getter or setter that you wrote. This is convenient because you can later write getters and/or setters to implement business logic and not affect the callers.
But a public field (declared as 'public') is just that - a public field. There's no generated getter or setter. I recommend using a decompiler to see this in action - create a simple POGO in src/groovy, e.g.
class Thing {
String realProperty
public String fieldButNotProperty
}
and open up the .class file with http://jd.benow.ca/ or another decompiler.
GORM automatically assumes that typed properties are persistent unless you exclude some with the transients list. The type is required so it knows how to persist the data, and properties like def name will be ignored. Properties in this sense are similar to JavaBean properties - a matched getter/setter pair.
Hibernate has no support for Groovy and doesn't know what's going on under the hood - it just calls your getters and setters to set and access field data during persistence. So the Groovy compiler adding those in makes it easy for POGOs in Grails to be persisted by Hibernate. And you could do this yourself - add in a getter and setter with correct names and data type (e.g. String getName() and void setName(String name) and it will be treated as a persistent property, even if you do nothing with the values.
The reason for the NotReadablePropertyException is that there's no getter to call for your 'property'. Even though your fields are perfectly accessible, you've effectively hidden them from GORM and Hibernate.
If you add a constraint, Grails will throw a NotReadablePropertyException exception when you call validate()
Never noticed this before, sounds like a bug
it would be nice if there was away that a fields which shouldn't be manipulated directly could be hidden from consumers of the domain class.
If you want to prevent direct access to a property, simply add a getter and setter. In the (contrived) example below, I ensure that name is always read/written as an upper case string.
class Person {
public String firstName
public String middleName
public String lastName
public void setFirstName(String name) {
this.firstName = name.toUpperCase()
}
public String getFirstName() {
return this.firstName.toUpperCase()
}
}

spring MVC model attributes in jsp page

When I access simple model data like the username using : ${username} everything seems to be fine. But when I try to use ${userdata.uname} I get an error like :
Could not find property uname in class com.mydom.datahandling.userdata
userdata is java class I add to the ModelAndView
ModelAndView mav = new ModelAndView("page37");
mav.addObject("sessionID",ID);
mav.addObject("userdata",p37userdata);
What do I need to do differently ? This seems to be happening whenever I try to use something other than a primitive type or String. I obviously need a bit more education. Do I need to serialize p37userdata?
userdata is
public class userdata{
public String uname;
public String otherstuff;
}
The objects you reference from your EL in your JSP should be java beans (or a map). According to wikipedia (the source of all truth) A bean has the following properties:
They are serializable, have a 0-argument constructor, and allow access
to properties using getter and setter methods.
So you should probably add getters and setters to your userdata class.

Why is get-Property in domain class only usable with Set and findAll?

In Domain class FooReward I added a method
int getQuantity() {
FooRewardAssignment.countByReward(this)
}
Usage in GSP should be fooRewardInstance.quantity, but that errors on startup (in bootstrap) with message that it has no setter method found.
If I change it to
Set<FooRewardAssignment> getListOfFoos() {
FooRewardAssignment.findAllByReward(this)
}
and change the usage in GSP to be badeRewardInstance.listOfFoos.size(), it works and shows me how often a special FooReward is assigned.
Any idea what is wrong in version 1?
Two workarounds for this problem:
Changing the return value to def:
def getQuantity() {
FooRewardAssignment.countByReward(this)
}
Or by adding transients list:
static transients = ['quantity']
int getQuantity() {
FooRewardAssignment.countByReward(this)
}
Sometimes GORM create column in tabel on the basis of setters and getters method inside domain class. And in this situation GORM want add column like 'quantity' but the error occur because GORM see only getter, and don't see setter. So we can say that we don't want create this column in database (static transients) or we can set return value as def - but don't ask me why 'def getters' are not taken into account by GORM ;)

How do I get the type (class) of a property of a Grails domain object?

I'm trying to dynamically create domain objects in Grails and encountered the problem that for any property referencing another domain object the metaproperty tells me its type is "java.lang.Object" and not the expected type.
For example:
class PhysicalSiteAssessment {
// site info
Site site
Date sampleDate
Boolean rainLastWeek
String additionalNotes
...
is the beginning of a domain class, which references another domain class "Site".
If I try to dynamically find the property types for this class by using this code (in a service):
String entityName = "PhysicalSiteAssessment"
Class entityClass
try {
entityClass = grailsApplication.getClassForName(entityName)
} catch (Exception e) {
throw new RuntimeException("Failed to load class with name '${entityName}'", e)
}
entityClass.metaClass.getProperties().each() {
println "Property '${it.name}' is of type '${it.type}'"
}
then the result is that it recognizes the Java classes, but not the Grails domain class. The output contains the following lines:
Property 'site' is of type 'class java.lang.Object'
Property 'siteId' is of type 'class java.lang.Object'
Property 'sampleDate' is of type 'class java.util.Date'
Property 'rainLastWeek' is of type 'class java.lang.Boolean'
Property 'additionalNotes' is of type 'class java.lang.String'
The problem is that I would like to use the dynamic lookup to find matching objects, e.g. do a
def targetObjects = propertyClass."findBy${idName}"(idValue)
where the propertyClass is retrieved via introspection, idName is the name of the property to look up (not necessarily the database ID) and idValue is the value to find.
It all ends in:
org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: static java.lang.Object.findByCode() is applicable for argument types: (java.lang.String) values: [T04]
Is there a way to find the actual domain class for the property? Or maybe some other solution to the problem of finding an instance of a domain class whose type is not given (only a property name that has the type)?
It works if I use the convention that the type name is the property name capitalized ("site"->"Site") to look up the class via the grailsApplication instance, but I would like to avoid that.
Grails allows you to access some meta-information of your domain model via the GrailsApplication instance. You can look it up that way:
import org.codehaus.groovy.grails.commons.ApplicationHolder
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler
def grailsApplication = ApplicationHolder.application
def domainDescriptor = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, "PhysicalSiteAssessment")
def property = domainDescriptor.getPropertyByName("site")
def type = property.getType()
assert type instanceof Class
API:
GrailsApplication
GrailsDomainClass
GrailsDomainClassProperty
You can use GrailsClassUtils.getPropertyType(clazz, propertyName)
The answer above provided by Siegfried became obsolete somewhere around Grails 2.4. ApplicationHolder is obsolete.
Now, you can get real type names from the domainClass property that every domain class has.
entityClass.domainClass.getProperties().each() {
println "Property '${it.name}' is of type '${it.type}'"
}
Note: this answer is not directly to the question but relates enough IMO.
I was banging my head to the wall, ground and surrounding trees when trying to resolve the "generic type" of a collection association:
class A {
static hasMany = {
bees: B
}
List bees
}
Turned out the easiest and yet sound way was mere (and which I did not try but after 3 hours):
A.getHasMany()['bees']

Resources