A recent discussion on the Grails Dev mailing list about creating a dynamic form builder involved needing to compile new domain classes at runtime. The consensus seemed to be that it’s not possible and/or not advisable, but I’ve thought a lot about this topic and had done similar work when creating the Dynamic Controller plugin, so I started playing with it.
The solution I came up with isn’t pretty but seems to work. There were a few issues to tackle. One is that Grails does quite a bit of work to convert your relatively simple domain classes into full GORM classes, registered with Hibernate and wired up with validation, convenience MetaClass methods, etc. There’s also the issue of automatically compiling in an
version field, a default
toString() method, and collections corresponding to
hasMany declarations. In addition there are four Spring beans created for each domain class. There’s a lot being done under the hood that we tend to take for granted.
But the big hurdle is registering the new entity with Hibernate. It’s expected that this is done at startup and never changed, so the data fields in
SessionFactoryImpl are mostly private and in two cases final. So the solution is rather hackish and involves brute force reflection. It just so happens that when using reflection, final fields are only mostly final. So I create a whole new
SessionFactoryImpl (it’d be convenient to create a small one with just the new domain class, but then you couldn’t reference other domain classes) and replace the real
SessionFactoryImpl‘s data with the data from the new one. I can’t replace the
SessionFactoryImpl since other classes will have a reference to the previous one.