I tried to serialize grails domains classes to Maps or similar in order to be able to store it in memcached.
I want to be able to read the objects only, I don't need gorm crud. Only to read them without breaking the kind of interfaces they have.
For instance: I could convert domains to maps, becouse it wouldn't break the interface for access like .<property> or .findall or similar
First I tried to do a manual serialization but it was very error prone. So I needed something more general.
Then I tried to serialize as a map with a grails codec.
Here is the testing repo.
Here is the snippet.
But I get StackOverFlowException.
I also tried to mark all the domains as Serializable but I need to reattach every domain when I bring them back from memcached to avoid hibernate errors like org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Do you know a way to achieve this?
Is very frustrating to google search for something like this "storing domain classes in memcached" and find out is not a common problem.
I haven't see an out-of-the-box solution for doing this, but if you wanted to keep it generic you could do it manually (and consistently) like this:
def yourDomainInst = DefaultGrailsDomainClass(YourDomainClazz)
List listOfOnlyPersistantProperties = yourDomainInst.persistantProperties
def yourNewMap
yourObjects.each { obj ->
listOfOnlyPersistantProperties.each { prop ->
def propName = prop.name
yourNewMap.put(propName, obj."$propName")
}
}
Something like that should work. Note there's probably a hundred errors because I can't try it out right now, but that is the general idea.
Have a look at: Retrieving a list of GORM persistent properties for a domain
Related
I came across a problem mapping multiple beans with Super CSV. I got a csv file, containing information for multiple beans (per line). But as I can see from examples on the website it is only possible to map each line into one bean (not into two or more beans).
Is there a way of doing this? The only way I can think of is creating a new bean, containing the all beans I need and do a deep mapping, i.e.:
class MultiBeanWrapper {
Address addreass;
BankAccount bankAccount;
}
...
String[] FIELD_MAPPING = new String[]
{address.street, bankAccount.bankNumber};
...
beanReader.read(MultiBeanWrapper.class, processors));
I didn't try this, because I want to be sure that there is no other / better way.
Thanks for your help
Daniel
No, you can't read a line into multiple beans - sorry! (I'm not sure what this would even look like - would you get a List<Object> back?)
You have a few options:
Add a relationship between the objects
Then can use a mapping like parent.fieldA, parent.child.fieldB. In your scenario Address and BankAccount aren't related semantically, so I'd recommend creating a common parent (see next option)
Add a common parent object
Then you can use a mapping like parent.child1.fieldA, parent.child2.fieldB. This is what you've suggested, but I'd recommend giving it a better name than Wrapper - it looks like a customer to me!
Oh, and I'd recommend trying stuff out before posting a question - often you'll answer your own question, or be able to give more details which will get you better answers!
I would like to iterate over all the available dataSources for the current environment, trying to see if any of them contain a particular domain instance. Each environment has different dataSources.
The best I've hacked up so far is grailsApplication.config.findAll { it.key.contains('dataSource_') }. Is there a better or more legitimate way to do this?
You can also query against the bean names in the application context.
Something like
ctx.beanDefinitionNames.findAll{ it.contains( 'dataSource' ) }
At least that is what the DatasourcesUtils in the Datasources plugin does -
http://plugins.grails.org/grails-datasources/trunk/src/groovy/com/burtbeckwith/grails/plugin/datasources/DatasourcesUtils.groovy
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.
Is it a bad practice to use domain objects in Sets or as keys in Maps?
In the past I've done things like this a lot
Set<Book> someBooks = [] as Set
someBooks.addAll (Book.findAllByAuthorLike('%hofstadter%'))
someBooks.add (Book.findByTitleLike ('%eternal%'))
However I have noticed that I often encounter problems when findAllByAuthorLike might return a list of Hibernate Proxy objects com.me.Book_$$_javassist_128 but findByTitleLike will return a proper com.me.Book object. This causes duplicates in the set because the real object and the proxy are considered not equal.
I find I need to be extremely careful when using Sets of domain objects like this, and I get the feeling it might be something I should not be doing in the first place.
The alternative is of course to use a set/map of id's, but it makes my code verbose and prone to misunderstanding
Set<Integer> someBooks = [] as Set // a set of id's for books
#Burt: I thought Grails domain classes already did this, at least so that equals/compare was done on class/id's rather than the object instance. Do you mean a special comparator for hibernate proxies?
return (this.class == obj.class && this.id == obj.id) ||
(obj.class == someHibernateProxy && this.id == obj.id)
It's not bad practice at all, but just like in a non-Grails application you should override equals and hashCode if you'll be putting them in hash-based collections (HashSet, HashMap, etc.) and also implement Comparable (which implies a compareTo method) if you're going to use TreeSet/TreeMap/etc.
Proper implementation of equals() and hashcode() in a Hibernate-backed situation is far from trivial. Java Collections require that hashcodes of objects and behaviour of equals() don't change, but the id of an object can change when it's a newly created object, and other fields can change for a wide variety of reasons. Sometimes you have a good unchangeable business id that you can use, but quite often that's not the case. And obviously default Java behaviour is also not suitable in a Hibernate situation.
The best solution I've seen is described here: http://onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=2
The solution it describes is: initialize the id as soon as the object is created. Don't wait for Hibernate to assign an id. Configure Hibernate to use version to determine whether it's a new object. This way, id in unchangeable, and can be safely used for hashcode() and equals().
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.