2009-07-21 12 views
20

Próbuję przekonać JAXB do współpracy z moją świetną klasą, jednak wygląda na to, że nie działa, ale robi to wersja Java. Oto kod ...Jak mogę zachęcić Groovy i JAXB do miłego grania?

Oto scenariusze:

Jeżeli 2 i 3 są komentarzem działa dobrze.

Jeżeli 1 i 4 są Odkomentowano uzyskać:

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

Jeżeli 1 i 5 są komentarzem uzyskać:

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

Jakieś pomysły?

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) 
     } 
    } 

Odpowiedz

21

odkomentowanie 1 i 4 jest prawidłowy sposób ustawić JAXB z Groovy. Powodem, dla którego nie działa, jest to, że każda klasa Groovy ma na sobie właściwość metaClass. JAXB próbuje odsłonić to jako właściwość JAXB, która oczywiście zawodzi. Ponieważ sam nie deklarujesz właściwości metaClass, nie można jej adnotować, aby JAXB ją ignorował. Zamiast tego ustaw XMLAccessType na BRAK. To wyłącza automatyczne wykrywanie właściwości JAXB w celu prezentacji jako elementy XML. Po wykonaniu tej czynności musisz jawnie zadeklarować wszystkie pola, które chcesz ujawnić.

przykład:

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

+1 doskonała odpowiedź – skaffman

15

I był ten sam problem podczas poddawania obiektu Grails gorm. Po zapoznaniu się z rozwiązaniem zamieszczonym powyżej, używając @XmlAccessorType(XmlAccessType.NONE), szybko zmęczyłem się oznaczaniem wszystkiego jako @XmlAttribute.

Mam mnóstwo sukcesów przy użyciu:

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

Patrz: XmlAccessType

Dzięki oryginalnej odpowiedzi na coraz mnie rozpoczął się w dobrym kierunku.

+5

Należy zauważyć, że powoduje to, co jest zwracane. XmlAccessType.FIELD zwraca wartość "wartości String", a nie jakiejkolwiek manipulacji, która ma miejsce w programach pobierających i ustawiających. Dlatego tak nie lubię w ten sposób. Ale tak, czyni to mniej gadatliwym. – Jackie

1

Rozwiązanie nie działa na abstrakcyjnej podklasie. Myślę, że dzieje się tak, ponieważ kompilator nie generuje kodu przesłaniania getMetaClass. Skończyło się naśladując kroki od this question następująco:

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

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

Tak, to trochę dziwne. W moim przypadku, mam kod jak poniżej:

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

i wykonywania moich skryptów, mam:

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

wolałbym lepsze rozwiązanie, ale teraz jest to wszystko, co mam.

+0

Ten kod też wydaje się działać, chociaż nie jestem pewien, czy to naprawdę dobry pomysł. 'metaklasą metaklasą = Nowe DelegatingMetaClass (ustawienia)' '@ XmlTransient' ' metaklasą getMetaClass() { ' ' metaClass' '}' – ngreen

Powiązane problemy