¿Cómo obtengo el tipo(clase) de una propiedad de un objeto de dominio Grails?
dynamic groovy (4)
Intento crear dinámicamente objetos de dominio en Grails y encontré el problema de que para cualquier propiedad que haga referencia a otro objeto de dominio, la metapropiedad me dice que su tipo es "java.lang.Object" y no el tipo esperado.
Por ejemplo:
class PhysicalSiteAssessment {
// site info
Site site
Date sampleDate
Boolean rainLastWeek
String additionalNotes
...
es el comienzo de una clase de dominio, que hace referencia a otra clase de dominio "Sitio".
Si trato de encontrar dinámicamente los tipos de propiedad para esta clase usando este código (en un servicio):
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}''"
}
entonces el resultado es que reconoce las clases de Java, pero no la clase de dominio de Grails. El resultado contiene las siguientes líneas:
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''
El problema es que me gustaría utilizar la búsqueda dinámica para buscar objetos coincidentes, por ejemplo, hacer un
def targetObjects = propertyClass."findBy${idName}"(idValue)
donde el propertyClass se recupera mediante introspección, idName es el nombre de la propiedad que se busca (no necesariamente el ID de la base de datos) y idValue es el valor que se debe buscar.
Todo termina en:
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]
¿Hay alguna manera de encontrar la clase de dominio real para la propiedad? ¿O tal vez alguna otra solución al problema de encontrar una instancia de una clase de dominio cuyo tipo no se da (solo un nombre de propiedad que tiene el tipo)?
Funciona si utilizo la convención de que el nombre de tipo es el nombre de la propiedad en mayúscula ("sitio" -> "Sitio") para buscar la clase a través de la instancia de grailsApplication, pero me gustaría evitar eso.
Grails le permite acceder a cierta metainformación de su modelo de dominio a través de la instancia GrailsApplication. Puedes buscarlo de esa manera:
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:
La respuesta anterior proporcionada por Siegfried se volvió obsoleta en algún lugar alrededor de Grails 2.4. ApplicationHolder está obsoleto.
Ahora puede obtener nombres de tipos reales de la propiedad domainClass que tiene cada clase de dominio.
entityClass.domainClass.getProperties().each() {
println "Property ''${it.name}'' is of type ''${it.type}''"
}
Nota: esta respuesta no es directamente a la pregunta, pero relata suficiente IMO.
Estaba golpeando mi cabeza contra la pared, el suelo y los árboles circundantes cuando trataba de resolver el "tipo genérico" de una asociación de colecciones:
class A {
static hasMany = {
bees: B
}
List bees
}
Resultó que la manera más fácil y sin embargo sólida era simple (y que no probé sino después de 3 horas):
A.getHasMany()[''bees'']