2009-07-21 8 views
20

Я пытаюсь заставить JAXB работать с классным классом, однако, похоже, он не работает, но версия java. Вот код ...Как заставить Groovy и JAXB играть хорошо вместе

Вот Сценарии:

Если 2 и 3 являются раскомментирована он работает отлично.

Если 1 и 4 раскомментировал я получаю:

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

Если 1 и 5 являются раскомментирована я получаю:

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

Любые идеи?

Java:

import javax.xml.bind.annotation.XmlRootElement; 

    @XmlRootElement 
    public class Player { 
    } 

Groovy:

import javax.xml.bind.annotation.XmlRootElement 

    @XmlRootElement 
    public class PlayerGroovy { 
    } 

Тест:

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

ответ

21

раскомментировать 1 и 4 является правильным способом установить JAXB с Groovy. Причина, по которой он не работает, заключается в том, что каждый класс Groovy имеет на нем свойство metaClass. JAXB пытается разоблачить это как свойство JAXB, которое, очевидно, терпит неудачу. Поскольку вы не объявляете свойство metaClass самостоятельно, невозможно аннотировать его, чтобы JAXB проигнорировал его. Вместо этого вы установите XmlAccessType в NONE. Это отключает JAXB автоматическое обнаружение свойств для отображения в виде элементов XML. После этого вам нужно явно объявить любые поля, которые вы хотите открыть.

Пример:

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

+1 отличный ответ – skaffman

15

У меня была та же проблема, в то время как подвергая объект Grails GORM. Изучив решение, опубликованное выше, используя @XmlAccessorType(XmlAccessType.NONE), я быстро устал отмечать все как @XmlAttribute.

У меня много успеха с помощью:

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

См: XmlAccessType

Благодаря оригинальный ответ на получение меня началось в правильном направлении.

+5

Следует отметить этот эффект, который возвращается. XmlAccessType.FIELD возвращает значение «String value», а не любые манипуляции, которые происходят в геттерах и сеттерах. Вот почему мне так не нравится этот путь. Но да, это делает вещи менее подробными. – Jackie

1

Решение, похоже, не работает в абстрактном подклассе. Я думаю, это связано с тем, что компилятор не генерирует код переопределения getMetaClass. Я закончил тем, имитируя шаги от this question следующим образом:

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

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

Да, это своего рода странно. В моем случае, у меня есть такой код:

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

И исполнять мои сценарии, у меня есть:

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

Я предпочитаю лучшее решение, но сейчас это все у меня есть.

+0

Этот код также работает, хотя я не уверен, что это действительно хорошая идея. 'метакласса метакласса = новые DelegatingMetaClass (Настройки)' ' @ XmlTransient' ' метакласса getMetaClass() { '' metaClass' '}' – ngreen