2009-06-10 18 views
14

Sto provando a creare dinamicamente oggetti di dominio in Grails e ho riscontrato il problema che per qualsiasi proprietà che fa riferimento a un altro oggetto di dominio la metaproperty mi dice che il suo tipo è "java.lang.Object" e non il tipo atteso.Come posso ottenere il tipo (classe) di una proprietà di un oggetto di dominio Grails?

Ad esempio:

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

è l'inizio di una classe di dominio, che fa riferimento a un'altra classe di dominio "Sito".

Se cerco di trovare in modo dinamico i tipi di proprietà per questa classe utilizzando questo codice (in un servizio):

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}'" 
} 

allora il risultato è che riconosce le classi Java, ma non la classe di dominio Grails . L'output contiene le seguenti righe:

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' 

Il problema è che desidero utilizzare la ricerca dinamica per trovare oggetti corrispondenti, ad esempio fare un

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

dove il propertyClass viene recuperato tramite l'introspezione, idName è il nome della proprietà per guardare in alto (non necessariamente l'ID del database) e idValue è il valore da trovare.

tutto finisce 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] 

C'è un modo per trovare la classe dominio effettivo per la proprietà? O forse qualche altra soluzione al problema di trovare un'istanza di una classe di dominio il cui tipo non è dato (solo un nome di proprietà che ha il tipo)?

Funziona se uso la convenzione che il nome tipo è il nome della proprietà in maiuscolo ("sito" -> "Sito") per cercare la classe tramite l'istanza grailsApplication, ma vorrei evitarlo.

risposta

15

Grails consente di accedere ad alcune meta-informazioni del modello di dominio tramite l'istanza GrailsApplication. Si può guardare in su in questo modo:

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

Grazie, funziona. C'è qualche panoramica di questa API da qualche parte? Stavo cercando qualcosa di simile ma non riuscivo a trovarlo. –

+0

Non ci sono riferimenti validi che abbia mai visto oltre ai javadocs (http://grails.org/doc/1.1/api/org/codehaus/groovy/grails/commons/DefaultGrailsApplication.html). Trovo anche molto utile guardare il codice sorgente di Grails. Inoltre uso molto questo tipo di cose nel plug-in build-test-data per esaminare i vincoli dell'oggetto dominio e generare automaticamente oggetti test che superano i vincoli se stai cercando esempi (http://bitbucket.org/tednaleid/grails- test-dati/wiki/Home). –

+1

Sto chiamando 'getDomainClass' invece. 'grailsApplication.getDomainClass (PhysicalSiteAssessment) .getPropertyByName ('site'). Type' –

0

Nota: questa risposta non è direttamente alla domanda ma riguarda abbastanza IMO.

stavo sbattere la testa al muro, a terra e che circonda gli alberi quando si cerca di risolvere il "tipo generico" di un'associazione collezione:

class A { 
    static hasMany = { 
     bees: B 
    } 

    List bees 
} 

si è rivelato il modo più semplice e tuttavia suono era semplice (e che non ho provato ma dopo 3 ore):

A.getHasMany()['bees'] 
2

La risposta di cui sopra fornita da Siegfried è diventata obsoleta da qualche parte intorno a Grails 2.4. ApplicationHolder è obsoleto.

Ora è possibile ottenere nomi di tipi reali dalla proprietà domainClass di cui è dotata ogni classe di dominio.

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