MOXy jaxb编组:找不到类的描述符

时间:2015-10-14 22:31:34

标签: xml junit jaxb marshalling moxy

在摆弄旧项目一段时间后,现在试图让它包含JAXB功能我遇到了麻烦,如果有人能提供它,我想要一些外部输入。除了相同的类以及更多的其他类型之外,还可以很好地工作(仅仅感谢来自MOXy主管的Stackoverflow上的一些其他答案,非常感谢那些!)但是编组失败了。

我得到的例外:

[Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class <edited out for anonymisation of project>.util.streamprocessor.handler.Acknowledge was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:459)
    at <edited out for anonymisation of project>.util.streamprocessor.FieldMessageJaxbTest.testFieldMessageXmlTransformation(FieldMessageJaxbTest.java:98)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class <edited out for anonymisation of project>..util.streamprocessor.handler.Acknowledge was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
    at org.eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.java:154)
    at org.eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.java:137)

这个类本身(注意:我已经在类中摆弄它使它成为一个简单的pojo,只有1个字段而没有父节点,编组时产生的异常是相同的):     @XmlRootElement     @XmlType     @XmlAccessorType(XmlAccessType.NONE)     public class Acknowledge extends AbstractFieldObject实现了ResponseProtocol,HasLocation {         public static final int ID = 0x2199;         public static final String NAME =&#34; Acknowledge&#34;;

    public int __id__() { return ID; }
    public String __name__() { return NAME; }

    // generated from CodeGenerator.fieldDeclaration
    @XmlElement
    private java.util.Date timestamp;
    // generated from CodeGenerator.fieldDeclaration
    @XmlElement
    private AcknowledgementData data;

    @XmlElement
    private CoreMachine sourceMachine_;
    /** Get the machine from which this message originated */
    public CoreMachine getSourceMachine_() { return sourceMachine_; }
    /** Set the machine from which this message originated - FOR TESTING ONLY */
    public void setSourceMachine_(CoreMachine sourceMachine_) {
        if (sourceMachine_ == null) {
            this.sourceMachine_ = FieldMessageUtil.createAnonymousMachine(null, sourceURL_, 0);
        } else {
            this.sourceMachine_ = sourceMachine_;
        }
    }

    @XmlElement
    private URL sourceURL_;
    /** Get the URL from which this message originated */
    public URL getSourceURL_() { return sourceURL_; }
    /** Set the URL from which this message originated - FOR TESTING ONLY */
    public void setSourceURL_(URL sourceURL_) { this.sourceURL_ = sourceURL_; }

    @XmlElement
    private Date arrivalTime_;
    /** Get the time at which this message was received in the office */
    public Date getArrivalTime_() { return arrivalTime_; }
    /** Set the time at which this message was received in the office - FOR TESTING ONLY */
    public void setArrivalTime_(Date arrivalTime_) { this.arrivalTime_ = arrivalTime_; }

    @XmlElement
    private int sequenceNumber_;
    /** Get sequence number with which this message was sent from the field */
    public int getSequenceNumber_() { return sequenceNumber_; }
    /** Set sequence number with which this message was sent from the field - FOR TESTING ONLY */
    public void setSequenceNumber_(int sequenceNumber_) { this.sequenceNumber_ = sequenceNumber_; }

    @XmlElement
    private int protocolType_;
    /** Get protocol type with which this message was sent from the field */
    public int getProtocolType_() { return protocolType_; }
    /** Set protocol type with which this message was sent from the field - FOR TESTING ONLY */
    public void setProtocolType_(int protocolType_) { this.protocolType_ = protocolType_; }

    public Acknowledge() {
    }

    public Acknowledge(Packet pkt) {
        setSourceURL_(pkt.getURL());
        setSourceMachine_(pkt.getMachine());
        setArrivalTime_(pkt.date());
        setSequenceNumber_(pkt.sequenceNo());
        initFromBlock(pkt.getMessage());
    }

    public Acknowledge(Block block) {
        initFromBlock(block);
    }

    private void initFromBlock(Block block) {

        if (block == null) return;


        // generated from CodeGenerator.constructorField1
        if (block.getChild("timestamp") != null) {
            // generated from CodeGenerator.constructorField4a
            this.timestamp = block.getDate("timestamp");
        }
        // generated from CodeGenerator.constructorField1
        if (block.getChild("data") != null) {
            // generated from CodeGenerator.constructorField2
            this.data = new AcknowledgementData((Block)block.getChild("data"), this);
        }
    }


    // generated from CodeGenerator.getter0
    public java.util.Date getTimestamp() {
         return timestamp;
    }

    // generated from CodeGenerator.getter0
    public AcknowledgementData getData() {
         return data;
    }

    // generated from CodeGenerator.setter
    public void setTimestamp(java.util.Date timestamp) {
        this.timestamp = timestamp;
    }

    // generated from CodeGenerator.setter
    public void setData(AcknowledgementData data) {
        this.data = data;
    }


    // generated from CodeGenerator.toString1
    public String toString() { return "Acknowledge"; }

    public @Nonnull String toXML() {
        StringBuilder s = new StringBuilder();
        s.append("<Acknowledge>\n");
        // generated from CodeGenerator.toStringMachine1
        if (sourceMachine_ != null) s.append("<machine>"+sourceMachine_+"<machine>\n");
        if (sourceURL_ != null) s.append("<url>"+sourceURL_+"<url>\n");
        if (arrivalTime_ != null) s.append("<arrivalTime>"+arrivalTime_+"<arrivalTime>\n");
        // generated from CodeGenerator.toStringField2
        s.append("<timestamp>"+timestamp+"</timestamp>\n");
        // generated from CodeGenerator.toStringField1
        if (data != null) {
            // generated from CodeGenerator.toStringField2a
            s.append(data.toXML());
        }
        // generated from CodeGenerator.toString2
        s.append("</Acknowledge>\n");
        return s.toString();
    }

    public Location getLocation() { return (data != null) ? data.getLocation() : null; }
}

用于编组/解组的JUnit代码(由于解压缩oxm -... xml文件而没有使用initialContext,JUnit测试会因JAXBContext创建而崩溃)

/**
 * Smal test trying marshalling & unmarshalling of a FieldMessage with Jaxb.
 *
 * Created by colinm2 on 14/10/2015.
 */
public class FieldMessageJaxbTest {

    @Test
    public void testFieldMessageXmlTransformation() {
        try {
            // Create initial context
            System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                    "org.apache.naming.java.javaURLContextFactory");
            System.setProperty(Context.URL_PKG_PREFIXES,
                    "org.apache.naming");
            InitialContext ic = new InitialContext();
        } catch (NamingException e) {
            e.printStackTrace();
        }

        // Create the Object
        Acknowledge ackInput = new Acknowledge();
        Acknowledge ackOutput = new Acknowledge();
        ackInput.setArrivalTime_(new Date());
        AcknowledgementData ackData = new AcknowledgementData();
        ackData.setError(0);
        ackData.setHandle(0);
        ackData.setSize(5);
        ackInput.setData(ackData);
        ackInput.setProtocolType_(2);
        ackInput.setSequenceNumber_(1234);
        ackInput.setTimestamp(new Date());
        try {
            ackInput.setSourceURL_(new URL("http://www.google.com"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        // Create the JAXBContext
        JAXBContext jaxbContext = null;
        try {
            Map<String, Object> properties = new HashMap<String, Object>(1);
            FileReader file1 = new FileReader("src/main/res/<edited out for anonymisation of project>./util/streamprocessor/oxm_1.xml");
            FileReader file2 = new FileReader("src/main/res/<edited out for anonymisation of project>./util/streamprocessor/oxm_2.xml");
            FileReader file3 = new FileReader("src/main/res/<edited out for anonymisation of project>./util/streamprocessor/oxm_3.xml");
            FileReader file4 = new FileReader("src/main/res/<edited out for anonymisation of project>./util/streamprocessor/oxm_4.xml");
            FileReader file5 = new FileReader("src/main/res/<edited out for anonymisation of project>./util/streamprocessor/oxm_5.xml");

            List<Object> fileList = new ArrayList<Object>();
            fileList.add(file1);
            fileList.add(file2);
            fileList.add(file3);
            fileList.add(file4);
            fileList.add(file5);
            properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, fileList);
            jaxbContext = JAXBContext.newInstance(Acknowledge.class.getPackage().getName(),
                    Acknowledge.class.getClassLoader(), properties);
            Marshaller m = jaxbContext.createMarshaller();

            // Create the Document
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.newDocument();

            m.marshal(ackInput, document);

            // Output the Document
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer t = tf.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(System.out);
            t.transform(source, result);

            Unmarshaller u = jaxbContext.createUnmarshaller();
            ackOutput = (Acknowledge) u.unmarshal(document);
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }


        assertEquals(ackInput.hashCode(), ackOutput.hashCode());
    }
}

编辑:为了使上面的代码有效,即使我只是编组/解组1个类,我也必须使用classes数组构造函数:

 Class[] classes = new Class[1];
 classes[0] = Acknowledge.class;
 jaxbContext = JAXBContext.newInstance(classes, properties);

工作模式生成器(以防万一,这里可能不需要):

/**
 * Created by colinm2 on 12/10/2015.
 */
public class XsdGenerator {

    public static void main(String[] args) {
        Reflections reflections = new Reflections("<edited out for anonymisation of project>.util.streamprocessor.handler");

        Set<Class<? extends AbstractFieldObject>> allClasses =
                reflections.getSubTypesOf(AbstractFieldObject.class);
        Set<Class<? extends Object>> jaxbClasses = new HashSet<>();
        for (Class clazz : allClasses) {
            if (!clazz.getName().endsWith("Constants") &&
                    !clazz.getName().endsWith("MessageGenerator") &&
                    !clazz.getName().endsWith("Processor") &&
                    !clazz.getName().contains("$")){
                jaxbClasses.add(clazz);
            }
        }

        Class[] classes = jaxbClasses.toArray(new Class[jaxbClasses.size()]);
        JAXBContext jaxbContext = null;
        try {
            Map<String, Object> properties = new HashMap<String, Object>(1);
            FileReader file1 = new FileReader("src/main/res/<edited out for anonymisation of project>/util/streamprocessor/oxm_1.xml");
            FileReader file2 = new FileReader("src/main/res/<edited out for anonymisation of project>/util/streamprocessor/oxm_2.xml");
            FileReader file3 = new FileReader("src/main/res/<edited out for anonymisation of project>/util/streamprocessor/oxm_3.xml");
            FileReader file4 = new FileReader("src/main/res/<edited out for anonymisation of project>/util/streamprocessor/oxm_4.xml");
            FileReader file5 = new FileReader("src/main/res/<edited out for anonymisation of project>/util/streamprocessor/oxm_5.xml");

            List<Object> fileList = new ArrayList<Object>();
            fileList.add(file1);
            fileList.add(file2);
            fileList.add(file3);
            fileList.add(file4);
            fileList.add(file5);
            properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, fileList);
            jaxbContext = JAXBContext.newInstance(classes, properties);
            SchemaOutputResolver sor = new XsdSchemaOutputResolver();
                jaxbContext.generateSchema(sor);
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class XsdSchemaOutputResolver extends SchemaOutputResolver {
        public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
            File file = new File("target/generated-resources/<edited out for anonymisation of project>/util/streamprocessor/handler/" + suggestedFileName);
            file.getParentFile().mkdirs();
            StreamResult result = new StreamResult(file);
            result.setSystemId(file.toURI().toURL().toString());
            return result;
        }

    }
}

有没有人知道为什么编组无法找到我班级Acknowledge的注释?任何帮助都会受到赞赏,我一直在反对这个问题已经很长时间了,现在我已经找到了自己的东西。

干杯, 迈克尔

编辑:修正了一些拼写错误。

0 个答案:

没有答案