To add a username "lastUpdatedBy" property (along with some other std properties) to several domain classes I created a trait. Everything works fine to the database, but EhCache disk storage gives a NotSerializableException on springSecurityService. I have
def springSecurityService
in order to get the principal.username.
Is there a way to designate the service as transient (static transients=[] doesn't seem to help), or am I at a dead end? Referencing a service from within a domain class is a bit dodgy anyway, but what is a better, workable way to get the username just before saving?
Ok, I figured this out. One of the domain classes had a composite key and was therefore tagged to implement Serializable. Once this was converted to maintain the usual id field and "implements Serializable" was removed, the problem went away.
Just declare your the field as a transient field.
class MyDomain {
// other stuff omitted
transient SpringSecurityService springSecurityService
}
This will do the job when it come to serialization.
Related
I have some booleans that are used throughout my grails project (services & controllers, etc) so they are declared in my domain class but I do not want them appearing in the table in the database. Instead of declearing them Boolean I tried Def but this isn't working. Is there a way to do this?
If you want to have a property of a domain class that does not get stored in the database then use transients.
Here is a simple example:
class Thing {
String name
boolean flag
boolean anotherFlag
static transients = ['flag', 'anotherFlag']
}
Something I picked up from one of the grails videos by Burt Beckwith was in grails domain classes if you define a getter or a setter without declaring the object itself that itself becomes a transient object by default. So as per above rather than all of the declarations if you had
//This will return the same value
boolean getFlag() {
return someField && someOtherField
}
//so you call `object.flag` or `object.getFlag()`
This saves from then having to declare a transient value as well giving you the chance to apply some logic on the fly.
In all honesty it appears you are using both the domain class for validation and input. Usually I separate and create a validation class in src to do this part and get domain class to do raw work - keeps it cleaner per say
This is almost identical to this old question: Dynamic define the inList constraint using database query which was essentially unaddressed, perhaps there have been advances in the years since that was asked.
I'd like to populate the inList parameter of a domain attribute with values from another domain. Due to auto-generated views (scaffolding, filterpane), this needs to come from inList rather than a custom validator.
class MyDomain {
String someValue
static constraints = {
someValue(nullable: true, maxSize: 50, inList: SomeOtherDomain.list()*.name)
}
}
This gives the following error on startup:
Caused by: java.lang.IllegalStateException: Either class [thepackage.SomeOtherDomain] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
I know, the "correct" way to handle this is to make someValue an instance of SomeOtherDomain instead of just storing the name, but that doesn't quite fit. We want to be able to delete an instance of SomeOtherDomain without breaking the saved value of the owning domain... the domain with the deleted value will be invalid going forward, and would have to be updated before saving, but archived/locked records will still exist and can be displayed.
You can specify value lists for filterpane like this:
<filterpane:filterPane domain="MyObject" filterPropertyValues="${['someValue':[values: SomeOtherDomain.list().collect{it.name}]]}" />
And then just use a custom validator to actually validate. I'm not sure what scaffolding might use the inList but easy enough to get around that if you're OK with replacing a few scaffolded pages with static ones.
I'm trying to serialize a Grails domain class instance into Memcached just after updating the domain instance by normal data binding.
When I'm doing this, I'm getting NotSerializableException saying Caused by NotSerializableException: org.codehaus.groovy.grails.web.json.JSONObject which looks like one of the field inside the domain instance is not serializable which is not implementing Serializable interface which is of type JSONObject of Groovy.
But, my domain class does not having such a field. This clearly states that some thing is being set by Grails databinding, since this serialization is working fine if I freshly get a instance.
So, is there any way of knowing that which field is actually failed to serialize?
Just a few high-level, hopefully very quick questions:
1) If I have a class A with a single field x, is constructing it
def A = new A(x:someVal, y:someVal)
totally fine?
2) Related, is the following a good way to copy relevant parts of a command object into a domain object?
def domainObject = new DomainObject(commandObject.properties).
Where command object has extra properties. Or should it be done instead:
def domainObject = new DomainObject()
domainObject.properties['prop1', 'prop2', ...] = commandObject.properties
or ?
Thanks
For the first question, it's important to distinguish between a vanilla groovy object, and a grails domain object. Groovy objects with throw a MissingPropertyException. Grails domain objects will silently ignore extra properties.
Regarding the second question, initializing grails domain objects with a command object is a common pattern, and generally ok. Params can be a little bit more dangerous. A malicious user can put anything into params so it's best to explicitly spell out what properties you want to assign. Otherwise, things like timestamps and users, or even non-mapped columns like injected spring beans could be affected.
In my Grails app, I'm using the Searchable plugin for searching/indexing. I want to write a Compass/Lucene query that involves multiple domain classes. Within that query when I want to refer to the id of a class, I can't simply use 'id' because all classes have an 'id' property. Currently, I work around this problem by adding the following property to a class Foo
public Long getFooId() {
return id
}
static transients = ['fooId']
Then when I want to refer to the id of Foo within a query I use 'fooId'. Is there a way I can provide an alias for a property in the searchable mapping rather than adding a property to the class?
You can give a more specific name to your id property. See this page for how to do this.
I finally discovered that this is the way to do it:
static searchable = {
id: name 'fooId'
}
Thanks! This would work really well, that is, if I could get past the OOM errors the app server seems to throw each time Searchable plugin is installed. These are bubbling up via :
org.compass.gps.CompassGpsException: Failed to index, execution exception; nested exception is java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java heap space
Has anyone configured their Searchable.groovy in grails-app/conf to perform a strict file:/// or mmap:// only configuration using no heap, and indexing say once or twice per day? Search is beyond a nice to have - but the cost of using the database mirroring in Grails (with Oracle 10g) seems memory intensive.
Really small amount of domains to search (4) small database, maybe 1-2gb for this application.