In GORM, it is possible for someone to specify the default id generator in config.groovy by doing:
grails.gorm.default.mapping = {
id generator : 'uuid2', type: 'pg-uuid'
}
However, I have a class in a plugin which is expecting the id to be a long, so it falls over. I could change the plugin, but just wondering if I have any other options here?
Thanks
You could try implementing an AST Transformation on the domain classes of your project which would convert any Long fields to String fields.
Grails scans the package org.codehaus.groovy.grails.compiler for any classes which implement grails.compiler.ast.GrailsArtefactClassInjector. Create a class in this package which scans domain classes and removes any id properties which have a class of Long and replaces them with a property of class String (or whatever class type you need).
Related
I'm trying to annotate fields over my domain classes but I'm not able to get them at runtime by reflection as usual Java fields.
My annotated domain class looks like:
class MyDomainClass {
#MyAnnotation
String myField
}
The Java way to access myField by reflection doesn't work:
MyDomainClass.class.getField("myField") //throws java.lang.NoSuchFieldException
The Grails way to inspect domain classes doesn't expose field annotations:
new DefaultGrailsDomainClass(MyDomainClass).getPersistentProperty("myField").??? //there is nothing similar to getAnnotations()
How can I retrieve the annotations associated with a domain field?
That's not a field, it's a property. When you declare a class-scope variable like that with no scope modifier (public, protected, etc.) in a Groovy class, the Groovy compiler converts it to a private field with the same type and name, and a getter and setter method, essentially
class MyDomainClass {
#MyAnnotation
private String myField
public String getMyField() {
return myField
}
public void setMyField(String s) {
myField = s
}
}
It won't overwrite an existing getter or setter though.
When you access the property you end up calling the getter or setter, which you can see if you add those methods and include println statements. This way Java classes can access the property via those methods, and Groovy pretends that you're directly reading or writing a field but under the hood you end up calling the same methods that you would from Java.
One benefit of this is that if you decide later that you want to add some logic when setting or getting the value, you can define the corresponding method(s) and add what you want without needing to change the code that accesses the property since in Groovy you can still treat it like a field and your custom methods will be called, and Java classes will have been calling the setter and getter all along.
getFields() returns only public fields, but getDeclaredFields() returns all of them, so since the actual field is private that's why getDeclaredFields() (or the property access form declaredFields) is necessary.
Grails doesn't use annotations because Graeme (and others) feel that they're ugly and bulky, not because they're not accessible.
I would like to split a Grails app in smaller plugins. Some domain classes have attributes which are of type Enum. Some values from these Enums would logically be part of the plugins, so I'm looking for a way for each plugin to register its own values into the 'core' Enums.
Obviously this cannot be done with Enums as they cannot be modified at runtime.
One option I see is replacing every Enum with a class with static attributes and add a static method to register new values from plugins. This has the following consequences:
GORM will not know what to store for the fake Enum values so it will throw an Exception
Therefore, I would have to change the type of these attributes to String, this way it will still work with the present values in storage, but I lose the advantage of seeing where that attribute can take its values.
Is there a better way to do this? Am I taking an approach which is not the "Grails way"?
In the end I am looking for a way to do an extension point in the core app for the plugins, like I would do with a ServiceProvider in Java.
I have a feeling that you are over complicating this problem, I would define the enums in different files depending on their type as probably they are now, then use them across your applications. I personally prefer to group the enums by their type not by their application, but it depends on your design.
Regarding the extension point, if you define them in core plugin, by the nature of Grails plugin you will have extendability. Meaning your applications can override or extend those values.
Hope this helps
I've faced the same problem in the development process. There is one solution I've found.
Transfer your enums to domains and init values with your plugins. Make static methods to get values, so domains will look like enums. For example:
class Person {
String name
static mapping = {
cache usage: 'read-only'
table 'Person '
id column: 'Person ID', generator: 'identity'
name column: 'Name'
}
static Person getJOHN() {
getByName('John')
}
static Person getByName(String name) {
Person.findByName(name)
}
}
I'm starting out with Grails and I'm following the InfoQ ebook found here.
The book teaches about Authentication in Chapter 9 and how to encrypt the password. Below shows how it is done, but I don't understand how it works.
First, we need to create a class in grails-app/utils/SHACodec.groovy:
import java.security.MessageDigest
class SHACodec{
static encode = { target->
MessageDigest md = MessageDigest.getInstance('SHA')
md.update(target.getBytes('UTF-8'))
return new String(md.digest()).encodeAsBase64()
}
}
Then in my User domain, I need to add a closure to beforeInsert:
class User{
...
String password
def beforeInsert = {
password = password.encodeAsSHA()
password
}
...
}
The code is working fine, but I don't see the connection on how adding a class in grails-app/utils/SHACodec.groovy enable the use of the function encodeAsSHA() for password in the User domain.
Since the SHACodec class only assign a closure to encode, and never mention encodeAsSHA(). How is password(a String) able to use it out of no where?
I'm surely missing something here!
A Grails codec class is one that may contain an encode closure, a decode closure or both. When a Grails application starts up the Grails framework dynamically loads codecs from the grails-app/utils/ directory.
The framework looks under grails-app/utils/ for class names that end with the convention Codec. For example one of the standard codecs that ships with Grails is HTMLCodec.
If a codec contains an encode closure Grails will create a dynamic encode method and add that method to the Object class with a name representing the codec that defined the encode closure. For example, the HTMLCodec class defines an encode closure, so Grails attaches it with the name encodeAsHTML.
I have a loop in my controller that does something like this:
for(d in grailsApplication.domainClasses) {
def c = d.getClazz().count()
// construct table containing object instance counts
}
My intent is to use this loop to count the instances of non-leaf domain classes in my database. Is there a way to query the domain class itself to find out if it is abstract or not? I wasn't sure if there were some member functions automatically added by the framework since I am still new to Groovy/Grails. I couldn't find anything that addressed it in the Grails documentation.
Figured it out after a few minutes of poking around the Groovy documentation. The function isAbstract() can be invoked on the domain class to determine whether or not the domain class is a leaf node in the class hierarchy
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.