2013-03-20 35 views
2

我有延伸Thread,我希望能够存储配置信息的XML作为一类。由于所有其他属性以及Thread类中的内容,这显然不起作用。在编组我得到一个不错的堆栈跟踪:如何在编组/解组期间忽略基类?

Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions 
java.lang.Thread$UncaughtExceptionHandler is an interface, and JAXB can't handle interfaces. 
    this problem is related to the following location: 
     at java.lang.Thread$UncaughtExceptionHandler 
     at public java.lang.Thread$UncaughtExceptionHandler java.lang.Thread.getUncaughtExceptionHandler() 
     at java.lang.Thread 
     at Test 
java.lang.Thread$UncaughtExceptionHandler does not have a no-arg default constructor. 
    this problem is related to the following location: 
     at java.lang.Thread$UncaughtExceptionHandler 
     at public java.lang.Thread$UncaughtExceptionHandler java.lang.Thread.getUncaughtExceptionHandler() 
     at java.lang.Thread 
     at Test 

    at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91) 
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:451) 
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:283) 
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126) 
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1142) 
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235) 
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:445) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584) 
    at Test.main(Test.java:22) 

下面是一个简单的类来说明这个问题:

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 



@XmlRootElement 
public class Test extends Thread{ 

    @XmlAttribute 
    public String something; 

    public Test(){ 
    } 

    public static void main(String[] args) throws JAXBException { 
     Test test = new Test(); 
     test.something = "My Value"; 

     JAXBContext jaxbContext = JAXBContext.newInstance(Test.class); 

     Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 
     // output pretty printed 
     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     jaxbMarshaller.marshal(test, System.out); 

    } 

} 

基本上我只关心什么是在Test类,而不是他得到了继承。因此,像:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<test something="My Value"/> 

那么,如何忽略编组/解组时的基类?

回答

3

为什么要扩展主题,而不是实现Runnable?无论如何,我认为你的解决方案不是对marshall和unmarshall线程或任何扩展它的类,而是创建一个单独的配置类,它包含你将编组和解组的重要状态数据。

例如,

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 

public class Test implements Runnable { 

    private TestConfig config = new TestConfig(); 

    public Test() { 
    } 

    public void setConfigSomething(String something) { 
     config.setSomething(something); 
    } 

    public TestConfig getConfig() { 
     return config; 
    } 

    public void setConfig(TestConfig config) { 
     this.config = config; 
    } 

    @Override 
    public void run() { 
     // foo 
    } 

    public static void main(String[] args) throws JAXBException { 
     Test test = new Test(); 
     test.setConfigSomething("My Value"); 

     JAXBContext jaxbContext = JAXBContext.newInstance(TestConfig.class); 

     Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 
     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     jaxbMarshaller.marshal(test.getConfig(), System.out);  
    } 
} 

@XmlRootElement 
class TestConfig { 
    private String something; 

    @XmlAttribute 
    public String getSomething() { 
     return something; 
    } 

    public void setSomething(String something) { 
     this.something = something; 
    } 
} 

这将导致预期产量:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<testConfig something="My Value"/> 

我想,另一种可能的解决办法是尽量使用适配器类型,如XmlAdapter,也许最好的解决方案是使用MOXy as per Blaise Doughan's suggestion

+0

谢谢,你是正确的,我大概应该已经实现,而不是扩展Thread开始与Runnable接口。这可以解决我的问题,而无需改变太多,或者添加另一个类(我试图避免)。 – 2013-03-20 13:44:48

+0

@jschoen:很高兴提供帮助,但请留意此线索,看看Blaise Doughan是否会回复,因为他可能会给您一个您需要的最佳规范答案。 – 2013-03-20 14:02:37