2009-06-10 7 views
14

J'essaie de créer dynamiquement des objets de domaine dans Grails et j'ai rencontré le problème que pour toute propriété référençant un autre objet de domaine, la métaproperty m'indique que son type est "java.lang.Object" et non le type attendu.Comment obtenir le type (classe) d'une propriété d'un objet de domaine Grails?

Par exemple:

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

est le début d'une classe de domaine, qui fait référence à une autre classe de domaine "du site".

Si j'essaie de trouver dynamiquement les types de propriétés de cette classe en utilisant ce code (dans un 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}'" 
} 

alors le résultat est qu'il reconnaît les classes Java, mais pas la classe de domaine Grails . La sortie contient les lignes suivantes:

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' 

Le problème est que je voudrais utiliser la recherche dynamique pour trouver des objets correspondant, par exemple faire un

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

où le propertyClass est récupéré par l'introspection, idName est le nom de la propriété pour rechercher (pas nécessairement l'ID de base de données) et idValue est la valeur à trouver.

tout se termine dans:

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] 

est-il un moyen de trouver la classe de domaine réel pour la propriété? Ou peut-être une autre solution au problème de trouver une instance d'une classe de domaine dont le type n'est pas donné (seulement un nom de propriété qui a le type)?

Cela fonctionne si j'utilise la convention que le nom de type est le nom de la propriété en majuscule ("site" -> "Site") pour rechercher la classe via l'instance grailsApplication, mais je voudrais éviter cela.

Répondre

15

Grails vous permet d'accéder à certaines méta-informations de votre modèle de domaine via l'instance GrailsApplication. Vous pouvez le regarder de cette façon:

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:

+0

Merci, cela fonctionne. Y a-t-il un aperçu de cette API quelque part? J'avais cherché quelque chose comme ça mais je ne l'ai pas trouvé. –

+0

Il n'y a pas de bonnes références que j'ai jamais vu en dehors des javadocs (http://grails.org/doc/1.1/api/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.html). Je trouve aussi très utile de regarder le code source de Grails. J'utilise aussi ce genre de choses dans le plugin build-test-data pour inspecter les contraintes d'objets de domaine et générer automatiquement des objets de test qui passent les contraintes si vous cherchez des exemples (http://bitbucket.org/tednaleid/grails- test-data/wiki/Accueil). –

+1

J'appelle 'getDomainClass' à la place. 'grailsApplication.getDomainClass (PhysicalSiteAssessment) .getPropertyByName ('site'). Type' –

0

Note: cette réponse n'est pas directement à la question mais rapporte assez IMO.

je frappais ma tête sur le mur, le sol et les arbres environnants en essayant de résoudre le « type générique » d'une association de collection:

class A { 
    static hasMany = { 
     bees: B 
    } 

    List bees 
} 

se sont avérés la meilleure façon et pourtant son était simple (et que je ne l'ai pas essayé, mais au bout de 3 heures):

A.getHasMany()['bees'] 
2

La réponse ci-dessus fourni par Siegfried est devenu obsolète quelque part Grails environ 2,4. ApplicationHolder est obsolète.

Maintenant, vous pouvez obtenir des noms de type réels de la propriété domainClass que possède chaque classe de domaine.

entityClass.domainClass.getProperties().each() { 
    println "Property '${it.name}' is of type '${it.type}'" 
} 
Questions connexes