Is it possible to mark a property as dirty in Grails domain? - grails

We have embedded domain in Grails 2.5.1. When any value inside this embedded domain is changed the owner domain mark property representing embedded domain as dirty. But there is no information which property inside of embedded domain is dirty.
So I would like to somehow mark such property manually - by implementing our own mechanism for marking and detecting such properties and I thought that I could use e.g. markDirty() method of owner domain for it. But this method does not work when it is called from outside.
Is it possible to somehow influence dirtyPropertyNames and in additional any other related properties and method so it will contain embedded domain values?
Than we could use dirtyPropertyNames as usual and it could return something like:
['embededDomainProperty.changedPropertyName']

Related

Check for annotation present on superclass field

I have problems to check if a persistent property in grails has an specific annotation for fields that belong to superclass ... ane then get it's name and value.
I am getting the persistence properties as:
GrailsDomainClassProperty[] persistentProperties = new DefaultGrailsDomainClass(entityClass).getPersistentProperties();
That works great ... but later i found that getDeclaredFields only retrieves the actual class fields (not superclass) and things starts to look not very Groovy.
Is there a prefered Groovy way to do this?
No, you should use this code for all super classes. The same will be for children classes.

Where should I place a transient domain class in a grails app?

Where should I place a transient domain class in a grails app?
Ie I have an Action class that will be passed about, and used, but never saved. Should this be in the grails-app/domain folder, or somewhere else?
grails-app/domain is for persistent domain classes, but not all of your application's domain-related classes need to be there, e.g. in this case where you want to use it as a value object. You can put these in src/groovy along with other classes that aren't considered Grails artifacts.
If you want the classes to support validation, you can annotate them with #Validateable - see section "7.5 Validation Non Domain and Command Object Classes" in the ref docs: http://grails.org/doc/latest/
I think a CommandObject may fit the bill. These typically go in the same directory as your controllers, have the same validation features available to domain objects, but are never persisted. Great for things like search forms.

Is there a list of forbidden method names for Grails domain objects?

Often as I add a helper method to a domain object I get an error when compiling which resolves to "x property is not found". This seems to happen for methods name getX, setX, and also recently isX. Is there a list of name forms that I should avoid? Is there a way to annotate or otherwise label these methods so Grails doesn't confuse them with auto properties?
Grails autodetects properties and assumes that they're persistent. Public fields in Groovy create a getter and setter under the hood so getters are assumed to be associated with persistent fields.
But if you want a helper method that starts with 'get' or 'is' but isn't a getter for a persistent field, you have two options. One is to use the transients list - see http://grails.org/doc/latest/ref/Domain%20Classes/transients.html
The other option is to declare the return value as def. Since it's not typed (def is an alias for Object) Hibernate can't persist it since it doesn't know what data type to use, so it's ignored.
My preference is the transients list because I would rather have self-documenting methods where it's obvious what they do, what parameter types they accept, and what they return.
I have no idea of common list - it's too diverse. Convention methods are added by different parts of Groovy and Grails:
Groovy convention about property getters/setters is very basic thing. It's impossible have a getX() method and not have read access to x property.
Grails domain class dynamic methods and Domain class convention properties are specific to Grails domain classes;
Same for controllers, and so on;
Groovy convention about property getters/setters, including methodMissing, propertyMissing, $staticMethodMissing, getProperty, properties and so on;
Groovy adds a number of as<Type>() methods, like asInteger();
different plugins could inject more convention methods.
To access declared field, not getter/setter, use java field access operator.
As far as I understand your problem, you can use transient !
static transients = ['feildName']

Distinguishing between Grails domain-class fields and getBlah() methods via GrailsDomainClassProperty

I'm writing a Groovy script (as part of a Grails plugin) and I want to get a list of properties for a GrailsDomainClass that a user of my plugin might define. I can do this using domainClass.properties (where domainClass is a GrailsDomainClass).
However, suppose a user has the grails domain class:
class Example {
String name
static constraints = {
}
def getSomeNonExistingProperty(){
return "Not-a-real-property"
}
}
In this case, domainClass.properties returns a list with both name and someNoneExistingProperty
I understand that this is because of Grails is generating a read-only property on-the-fly for use where someone has a getBlah() method. That's great, but in my script I want to perform some actions with the "real" properties only (or at least non read-only properties).
That is, I would like some way of distinguishing or identifying someNonExistingProperty as a read-only property, or, alternatively, as a property generated by Grails and not entered explicitly as a field in the domainClass by the user of my plugin.
I've looked at the GrailsDomainClassProperty Class and it has a range of methods providing information about the property. However, none of them appear to tell me whether a property is read-only or not, or to allow me to distinguish between a field defined in the domainClass and a field created on-the-fly by Grails as a result of a "getSomeNonExistingProperty()" method.
Am I missing something obvious here? Is there a way of getting a list of just the explicitly user-defined fields (eg name, in the above example)?
I believe transient properties are what you are trying to exclude
I've run into this problem a few times, and instead of trying to work around it I typically just end up renaming my getX() method. It's probably the easiest option.
Edit:
Alternatively, I wonder if you could use reflection to see which methods are defined on the class, and while iterating over your properties see if the property has an explicit getter defined, and omit it. I'm not very familiar with reflection when it comes to Groovy and Grails, especially with the dynamic methods, but it's a possible route of investigation.

Grails internals : Auto mapping and Domain object creation

I am trying to make a taglib to represent an object (to read and display at the UI). When creating an object (save method in the controller), I see the domain class and association are created by the auto assignment of parameter
def Book = new Book(params)
It also maps complex types (for eg: joda time). I wonder about the naming convention necessary to facilitate this mapping. Out of curiosity, can someone also point where in the grails source code I could see how grails handles this mapping. I'm still learning Spring and probably this would be a good exercise.
Thanks,
Babu.
AFAIK the naming conventions are rather straightforward. If there's a field params.foo and the object you are binding to has a field foo, it will bind the value, assuming the type conversion works properly. If there's a params.bar.id set with an Long value and your object has a complex property of type Bar, it will lookup this instance and inject it.
If you need more control over the binding process, you might want to use bindData.
If you are interested into the details of the binding process, have a look at Java's PropertyEditor as this is what is being used in the background. I wrote a blog post on how to create and register PropertyEditors a while ago, maybe it helps you getting started with that stuff.

Resources