2009-07-21 12 views
20

Estoy tratando de hacer que JAXB trabaje con una clase mía maravillosa, sin embargo, parece que no funciona, pero la versión de Java sí. Aquí está el código ...¿Cómo hago para que Groovy y JAXB jueguen bien juntos?

Éstos son los Escenarios:

Si 2 y 3 son sin comentar que trabaja muy bien.

Si 1 y 4 no están comentadas consigo:

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

Si 1 y 5 son sin comentar consigo:

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

¿Alguna idea?

Java:

import javax.xml.bind.annotation.XmlRootElement; 

    @XmlRootElement 
    public class Player { 
    } 

maravilloso:

import javax.xml.bind.annotation.XmlRootElement 

    @XmlRootElement 
    public class PlayerGroovy { 
    } 

prueba:

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

Respuesta

21

descomentando 1 y 4 es la forma correcta de establecer JAXB con maravillosa. La razón por la que no funciona es que cada Clase Groovy tiene una propiedad metaClass. JAXB intenta exponer esto como una propiedad JAXB que obviamente falla. Como usted no declara la propiedad metaClass usted mismo, no es posible anotarla para que JAXB la ignore. En su lugar, configure el XmlAccessType en NINGUNO. Este deshabilita el descubrimiento automático de propiedades de JAXB para exponer como elementos XML. Después de hacer eso, necesita declarar explícitamente cualquier campo que desee exponer.

Ejemplo:

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

+1 excelente respuesta – skaffman

15

que estaba teniendo el mismo problema, mientras que la exposición de un objeto Grails GORM. Después de investigar la solución publicada anteriormente, usando @XmlAccessorType(XmlAccessType.NONE), rápidamente me cansé de marcar todo como @XmlAttribute.

estoy teniendo mucho éxito usando:

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

Ver: XmlAccessType

Gracias a la respuesta original por iniciarme en la dirección correcta.

+5

Para tener en cuenta este efecto, lo que se devuelve. XmlAccessType.FIELD devuelve el valor del "Valor de cadena", no cualquier manipulación que ocurra en getters y setters. Es por eso que no me gusta tanto de esta manera. Pero sí hace que las cosas sean menos detalladas. – Jackie

1

La solución no parece funcionar en una subclase abstracta. Creo que es porque el compilador no genera el código de anulación getMetaClass. Terminé imitando los pasos de this question de la siguiente manera:

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

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

Sí, es un poco raro. En mi caso, tengo un código como éste:

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

Y para ejecutar mis guiones, que tengo:

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

preferiría una solución mejor, pero en este momento esto es todo lo que tengo.

+0

Este código también parece funcionar, aunque no estoy seguro de si realmente es una buena idea. 'MetaClass MetaClass = new DelegatingMetaClass (Ajustes)' ' @ XmlTransient' ' MetaClass getMetaClass() { '' metaClass' '}' – ngreen

Cuestiones relacionadas