Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the type (class) of a property of a Grails domain object?

I'm trying to dynamically create domain objects in Grails and encountered the problem that for any property referencing another domain object the metaproperty tells me its type is "java.lang.Object" and not the expected type.

For example:

class PhysicalSiteAssessment {
    // site info
    Site site
    Date sampleDate
    Boolean rainLastWeek
    String additionalNotes
    ...

is the beginning of a domain class, which references another domain class "Site".

If I try to dynamically find the property types for this class by using this code (in a service):

String entityName = "PhysicalSiteAssessment"
Class entityClass
try {
    entityClass = grailsApplication.getClassForName(entityName)
} catch (Exception e) {
    throw new RuntimeException("Failed to load class with name '${entityName}'", e)
}
entityClass.metaClass.getProperties().each() {
    println "Property '${it.name}' is of type '${it.type}'"
}

then the result is that it recognizes the Java classes, but not the Grails domain class. The output contains the following lines:

Property 'site' is of type 'class java.lang.Object'
Property 'siteId' is of type 'class java.lang.Object'
Property 'sampleDate' is of type 'class java.util.Date'
Property 'rainLastWeek' is of type 'class java.lang.Boolean'
Property 'additionalNotes' is of type 'class java.lang.String' 

The problem is that I would like to use the dynamic lookup to find matching objects, e.g. do a

def targetObjects = propertyClass."findBy${idName}"(idValue)

where the propertyClass is retrieved via introspection, idName is the name of the property to look up (not necessarily the database ID) and idValue is the value to find.

It all ends in:

org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: static java.lang.Object.findByCode() is applicable for argument types: (java.lang.String) values: [T04]

Is there a way to find the actual domain class for the property? Or maybe some other solution to the problem of finding an instance of a domain class whose type is not given (only a property name that has the type)?

It works if I use the convention that the type name is the property name capitalized ("site"->"Site") to look up the class via the grailsApplication instance, but I would like to avoid that.

like image 824
Peter Becker Avatar asked Jun 10 '09 06:06

Peter Becker


People also ask

What is Grails domain class?

In Grails a domain is a class that lives in the grails-app/domain directory. A domain class can be created with the create-domain-class command: grails create-domain-class org.bookstore.Book. or with your favourite IDE or text editor.

What is gorm in Grails?

GORM is the data access toolkit used by Grails and provides a rich set of APIs for accessing relational and non-relational data including implementations for Hibernate (SQL), MongoDB, Neo4j, Cassandra, an in-memory ConcurrentHashMap for testing and an automatic GraphQL schema generator.

What is domain class in Java?

A domain class represents a table column and it allows you to handle the column value as a Java object. In the Doma framework, a domain means all the values which a data type may contain. In short, a domain class is a user defined class that can be map to a column.


2 Answers

Grails allows you to access some meta-information of your domain model via the GrailsApplication instance. You can look it up that way:

import org.codehaus.groovy.grails.commons.ApplicationHolder
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler

def grailsApplication = ApplicationHolder.application
def domainDescriptor = grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, "PhysicalSiteAssessment")

def property = domainDescriptor.getPropertyByName("site")
def type = property.getType()
assert type instanceof Class

API:

  • GrailsApplication
  • GrailsDomainClass
  • GrailsDomainClassProperty
like image 79
Siegfried Puchbauer Avatar answered Sep 18 '22 16:09

Siegfried Puchbauer


You can use GrailsClassUtils.getPropertyType(clazz, propertyName)

like image 28
geeksays Avatar answered Sep 20 '22 16:09

geeksays