2009-07-21 10 views
20

Ich versuche JAXB mit einer groovigen Klasse von mir zu arbeiten, aber es scheint, es funktioniert nicht, aber die Java-Version tut. Hier ist der Code ...Wie bekomme ich Groovy und JAXB zusammen zu spielen

Hier sind die Szenarien:

Wenn 2 und 3 uncommented sind es funktioniert gut.

Wenn 1 und 4 unkommentiert erhalte ich:

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 
     2 counts of IllegalAnnotationExceptions 
groovy.lang.MetaClass is an interface, and JAXB can't handle interfaces. 

Wenn 1 und 5 uncommented I erhalten:

javax.xml.bind.JAXBException: class org.oclc.presentations.simplejaxb.PlayerGroovy 
     nor any of its super class is known to this context. 

Irgendwelche Ideen?

Java:

import javax.xml.bind.annotation.XmlRootElement; 

    @XmlRootElement 
    public class Player { 
    } 

Groovy:

import javax.xml.bind.annotation.XmlRootElement 

    @XmlRootElement 
    public class PlayerGroovy { 
    } 

Test:

import org.junit.Test 
    import javax.xml.bind.JAXBContext 
    import javax.xml.bind.Marshaller 
    import org.junit.Assert 

    class PlayerTest { 
     @Test 
     public void testJaXB(){ 
      //1 PlayerGroovy player = new PlayerGroovy() 
      //2 Player player = new Player() 
      StringWriter writer = new StringWriter(); 
      //3 JAXBContext context = JAXBContext.newInstance(Player.class); 
      //4 JAXBContext context = JAXBContext.newInstance(PlayerGroovy.class); 
      //5 JAXBContext context = JAXBContext.newInstance(PlayerGroovy.getClass()); 
      Marshaller m = context.createMarshaller(); 
      m.marshal(player, writer); 
      println(writer) 
      Assert.assertTrue(true) 
     } 
    } 

Antwort

21

uncommenting 1 und 4 ist der richtige Weg JAXB mit Groovy bis zu setzen. Der Grund, warum es nicht funktioniert, ist, dass jede Groovy-Klasse eine MetaClass-Eigenschaft besitzt. JAXB versucht dies als eine JAXB-Eigenschaft zu offenbaren, die offensichtlich fehlschlägt. Da Sie die MetaClass-Eigenschaft nicht selbst deklarieren, ist es nicht möglich, sie mit Anmerkungen zu versehen, damit JAXB sie ignoriert. Stattdessen setzen Sie den XmlAccessType auf NONE. Die automatische Erkennung von Eigenschaften, die von JAXB als XML-Elemente verfügbar gemacht werden sollen. Nachdem Sie dies getan haben, müssen Sie explizit alle Felder angeben, die Sie verfügbar machen möchten.

Beispiel:

@XmlAccessorType(XmlAccessType.NONE) 
@XmlRootElement 
public class PlayerGroovy { 
    @XmlAttribute 
    String value 
} 
+3

+1 ausgezeichnete Antwort – skaffman

15

I das gleiche Problem wurde, während ein Grails GORM Objekt aussetzt. Nachdem ich die Lösung, die oben beschrieben wurde, unter Verwendung von @XmlAccessorType(XmlAccessType.NONE) untersucht hatte, wurde ich schnell müde, alles als @XmlAttribute zu markieren.

ich viel Erfolg mit ein:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement 
public class PlayerGroovy { 
    String value 
} 

See: XmlAccessType

Dank der ursprünglichen Antwort für mich in die richtige Richtung begonnen.

+5

Zu bemerken, dass diese Effekte, was zurückgegeben wird. XmlAccessType.FIELD gibt den Wert des "String-Werts" und keine Manipulation in Getter und Setter zurück. Deshalb mag ich diesen Weg nicht so sehr. Aber ja, es macht die Dinge weniger ausschweifend. – Jackie

1

Die Lösung scheint nicht in einer abstrakten Unterklasse zu funktionieren. Ich denke, das liegt daran, dass der Compiler den getMetaClass Override-Code nicht generiert. Ich beendete die Schritte von this question nachahmt sich wie folgt zusammen:

@XmlAccessorType(XmlAccessType.NONE) 
package groovy.lang; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 

Ja, es ist irgendwie komisch. In meinem Fall habe ich Code wie folgt:

package pkg; 
abstract class ScriptMomma extends groovy.lang.Script { 
    // write some nice supporting code here 
} 

Und meine Skripte auszuführen, die ich habe:

def config = new org.codehaus.groovy.control.CompilerConfiguration() 
config.scriptBaseClass = 'pkg.ScriptMomma' 
ScriptMomma mine = new GroovyShell(config).evaluate(scriptFile, 'TheOne') 

Ich würde eine bessere Lösung bevorzugen, aber im Moment ist das alles was ich habe.

+0

Dieser Code scheint auch zu funktionieren, obwohl ich nicht sicher bin, ob es wirklich eine gute Idee ist. 'MetaClass metaclass = new DelegatingMetaClass (Einstellungen)' ' @ XmlTransient' ' MetaClass getMetaClass() { '' metaClass' '}' – ngreen

Verwandte Themen