4

I am doing Spring Integration project. I'd like to publish XML string to one channel and receive Java object in other channel, via unmarshalling transformer.

In my Spring config I am using these channels and beans:

<!-- 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" />

I am trying this in unit test, so I have autowired channels to use:

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

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

Trade class, which I want to have unmarshalled is very trivial POJO:

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

Here's my JUnit test method, but I get exception on 3rd line:

    @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());
}

And finally here's stacktrace:

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
Xorty
  • 18,367
  • 27
  • 104
  • 155

6 Answers6

2

To resolve this issue you need to specify your class that you want to parse. CastorMarshaller has two attribute targetClasses wich is an array of Objects and targetPackages wich is an array of Strings you can verify the source of this class.

The code below will resolve your problem without a mapping file.

<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>

If the class to parse still unknown, you have to verify your xml file format.

Example :

Java class

public class MyUser {
  // class attributs

  private String firstNameField;
  private String lastNameField;

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

xml file

<?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>
1

See the java docs for the CastorMarshaller. Add <property name="targerClass" value="foo.Trade"/> to the marshaller.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Thanx for reply. I added property with Trade class to bean marshaller but I am still getting same error. Any more ideas? – Xorty Jun 22 '12 at 12:42
0

You have to specify in either the castor configuration file or as part of the unmarshaller configuration that your trade tag should map to your Trade class, this seems to be the issue here.

You should be able to do it directly using CastorMarshaller itself:

<bean id="marshaller" class="org.springframework.oxm.castor.CastorMarshaller">
<property name="targetClasses>
 <list>
  <value>Trade.class</value>
 </list>
</property>
</bean>
Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
  • Nope, didn't help. I tried both targetClasses and targetClass. On transformer I cannot find corresponding property for binding it with Trade class. And I believe in value element you specify class name without ".class" suffix, but that's just minor issue. – Xorty Jun 22 '12 at 12:26
0

Use this below code it will solve this problem.

<bean id="marshaller" class="org.springframework.oxm.castor.CastorMarshaller">
 <property name="targetClasses" value="Trade">

</property>

Trade should be your pojo name.

Amit
  • 15,217
  • 8
  • 46
  • 68
Vijay
  • 1
  • 1
0

Use this property:

marshaller.setUseXSITypeAtRoot(true);

then in the xml you will see attribute xsi:type= in root element with exact class. Unmarshaller will work after that.

rejthy
  • 446
  • 3
  • 4
0

Try this example format, the Main thing to watch for is - unMarshaller.setClass(com.hello.test.order.cw.bind.Message.class); which will find the class in non-default package, by default unmarshaller expects the class to be in default package.

/**
 * 
 * @param inType
 * @param elements
 * @param orderInXml
 * @return
 */
private boolean 
    validateXMLForTargetElements(String inType,
            List<String> elements,String orderInXml) {
    try {
        Unmarshaller unMarshaller = new Unmarshaller();
        StringReader stringReader = new StringReader(orderInXml);
        unMarshaller.setClass(com.hello.test.order.cw.bind.Message.class);

        System.out.println("The XML After Modification "+orderInXml);
        com.hello.test.order.cw.bind.Message message = 
                (Message) unMarshaller.unmarshal(stringReader);
        System.out.println("The Object Message After"
                + " Converting from XML is "+message);
    } catch(Exception ex) {
        ex.printStackTrace();
    }
    return false;
}
kanaparthikiran
  • 523
  • 12
  • 15