java - Spring:解码 XML 字符串时出现 OXM 错误(castor)

标签 java xml spring spring-integration oxm

我正在做 Spring Integration 项目。我想通过解码转换器将 XML 字符串发布到一个 channel 并在另一个 channel 中接收 Java 对象。

在我的 Spring 配置中,我使用了这些 channel 和 bean:

<!-- channel to for publishing XML string -->
<int:publish-subscribe-channel id="channels.pubsub.inXml" />

<!-- channel for receiving transformed reply -->
<int:channel id="channels.fromXmlChannel">
    <int:queue capacity="10" />
</int:channel>

<!-- transformer unmarshalling XML to Java object -->
<int-xml:unmarshalling-transformer
    unmarshaller="marshaller"
    input-channel="channels.pubsub.inXml"
    output-channel="channels.fromXmlChannel" />

<!-- marshaller bean -->
<bean id="marshaller" class="org.springframework.oxm.castor.CastorMarshaller" />

我正在单元测试中尝试这个,所以我有自动连接的 channel 可以使用:

@Autowired @Qualifier("channels.pubsub.inXml")
MessageChannel inXmlChannel;

@Autowired @Qualifier("channels.fromXmlChannel")
MessageChannel fromXmlChannel;

我想要解码的贸易类是非常琐碎的 POJO:

class Trade {
    String id;
    String direction;
    // getters, setters, constructors
}

这是我的 JUnit 测试方法,但我在第 3 行遇到异常:

    @Test
public void testUnmarshallingTransformer() {
    String xml = "<trade id='ID-01' direction='DIR-PRG' />";

    Message<String> message = MessageBuilder.withPayload(xml).build();
    inXmlChannel.send(message, TIMEOUT);
    Message<?> received = ((PollableChannel) fromXmlChannel).receive(TIMEOUT);

    System.out.println("\n\n" + received.getPayload());
}

最后是堆栈跟踪:

org.springframework.integration.transformer.MessageTransformationException: failed to transform message
    at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:44)
    at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:67)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:97)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
    at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:105)
    at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:96)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:61)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
    at sk.xorty.transformers.BuiltinTransformersTest.testUnmarshallingTransformer(BuiltinTransformersTest.java:190)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.springframework.oxm.UnmarshallingFailureException: Castor unmarshalling exception; nested exception is org.exolab.castor.xml.MarshalException: The class for the root element 'trade' could not be found.{File: [not available]; line: 1; column: 41}
    at org.springframework.oxm.castor.CastorMarshaller.convertCastorException(CastorMarshaller.java:487)
    at org.springframework.oxm.castor.CastorMarshaller.unmarshalReader(CastorMarshaller.java:399)
    at org.springframework.oxm.support.AbstractMarshaller.unmarshalStreamSource(AbstractMarshaller.java:371)
    at org.springframework.oxm.support.AbstractMarshaller.unmarshal(AbstractMarshaller.java:134)
    at org.springframework.integration.xml.transformer.UnmarshallingTransformer.transformPayload(UnmarshallingTransformer.java:107)
    at org.springframework.integration.transformer.AbstractPayloadTransformer.doTransform(AbstractPayloadTransformer.java:33)
    at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33)
    ... 39 more
Caused by: org.exolab.castor.xml.MarshalException: The class for the root element 'trade' could not be found.{File: [not available]; line: 1; column: 41}
    at org.exolab.castor.xml.Unmarshaller.convertSAXExceptionToMarshalException(Unmarshaller.java:866)
    at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:763)
    at org.springframework.oxm.castor.CastorMarshaller.unmarshalReader(CastorMarshaller.java:396)
    ... 44 more
Caused by: org.xml.sax.SAXException: The class for the root element 'trade' could not be found.
    at org.exolab.castor.xml.UnmarshalHandler.processFirstElement(UnmarshalHandler.java:890)
    at org.exolab.castor.xml.StartElementProcessor.compute(StartElementProcessor.java:103)
    at org.exolab.castor.xml.UnmarshalHandler.startElementProcessing(UnmarshalHandler.java:811)
    at org.exolab.castor.xml.UnmarshalHandler.startElement(UnmarshalHandler.java:733)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
    at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:182)
    at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.emptyElement(XMLDTDValidator.java:766)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1302)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$ContentDriver.scanRootElementHook(XMLDocumentScannerImpl.java:1275)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3063)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:881)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at org.exolab.castor.xml.Unmarshaller.unmarshal(Unmarshaller.java:751)
    ... 45 more

最佳答案

要解决此问题,您需要指定要解析的类。 CastorMarshaller 有两个属性 targetClasses,它是一个对象数组和 targetPackages,它是一个字符串数组,您可以验证此类的来源。

下面的代码将在没有映射文件的情况下解决您的问题。

<bean id="marshaller" class="org.springframework.oxm.castor.CastorMarshaller">
  <property name="targetClasses">
    <array>
      <value>Your class location (ex : com.domain.YourClass)</value>
    </array>
  </property>
</bean>

如果要解析的类仍然未知,则必须验证您的 xml 文件格式。

示例:

Java 类

public class MyUser {
  // class attributs

  private String firstNameField;
  private String lastNameField;

  // class methods
  //...... 
}

xml文件

<?xml version="1.0" encoding="UTF-8"?>
<my-user>
  <first-name-field>firstName</first-name-field>
  <last-name-field>lastName</last-name-field>
</my-user>

关于java - Spring:解码 XML 字符串时出现 OXM 错误(castor),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11154172/

相关文章:

Java JSONObject.getJSONArray 始终返回 null

android - 将 xml 数据解析为哈希表并显示在 ListView 中?

java - 未找到 ClassPathXmlApplicationContext 类路径

spring - PGD​​atasource 不会连接到远程服务器

java - Spring MVC 处理列表中的按钮事件

Java二叉搜索树_根到最近叶子的距离

java - 如何在 java 程序中检索 catalina.out 的路径?

java - Log4j 自定义 Appender 最初抛出 ClassNotFoundException?

Android 和 XML

java - Android - 编辑操作栏按钮文本