在摆弄旧项目一段时间后,现在试图让它包含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的注释?任何帮助都会受到赞赏,我一直在反对这个问题已经很长时间了,现在我已经找到了自己的东西。
干杯, 迈克尔
编辑:修正了一些拼写错误。