2013-03-20 66 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