You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@servicemix.apache.org by Henrique Viecili <he...@myreks.com> on 2012/03/02 16:38:29 UTC

Namespace lost in conversion just before unmarshaling with JAXB

Guys,

I am facing a problem that has took already a couple days to figure out
what was happening, I've searched the camel source code and log files and I
am stuck:

*The Problem:*
The JAXB unmarshal throws an UnmarshalException because the element in the
XML is not qualified, i.e, the input XML of the consumer service does not
have a declared namespace. As the log bellow suggest, the namespace seems
to be lost at the moment of conversion between
*org.apache.xerces.dom.DeferredElementNSImpl
-> java.xml.transform.StreamSource* OR *java.xml.transform.StreamSource ->
java.io.InputStream.*
This last conversion happens
at org.apache.camel.processor.UnmarshalProcessor line 50: InputStream
stream = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);

*Environment:*
- ServiceMix 4.4.1 fuse 01-13
- Camel 2.8.0 fuse 01-13
- Saxon 9.1.0.8 (defined at SMX startup
with -Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl)

*Scenario:*
- 2 JBI services: 1 producing events and the other consuming events storing
them on database
- Camel Context with Spring DSL

*Routing logistic: *(simplistic)
- Producer: Input XML -> transform XSL -> split XPath -> Ouput XML
- Consumer: Input XML -> unmarshal JAXB -> bean:storeDatabase

*The Log: *(pay more attention to BodyType and Body)
1. This is what is sent from Producer to Consumer after the split with
XPath: (note the body has the declared namespace)
>>> (route4)
from(endpoint:urn:com.myreks:bus:txreport:ProcessReportChannelConsumer) -->
endpoint:urn:com.myreks:bus:event:ApplicatonEventsChannelProducer <<<
Pattern:InOnly, Headers:{...},
BodyType:org.apache.xerces.dom.DeferredElementNSImpl,
Body:<ApplicationEvent xmlns="http://api.myreks.com/ApplicationEvent">
      <uuid>b22ce63c-aa2b-30ed-bd71-4d5f470d8d03</uuid>
      <type>TX_REPORT</type>
      <action>PAYMENT-DONE</action>
      <timestamp>2011-04-07T15:28:00Z</timestamp>
      <txId>a0c0e205-50ee-49ed-a7de-ba58a6f39cd8</txId>
      <parentTxId/>
      <system>TXREPORT</system>
      <attributes>
         <entry key="commission">4</entry>
         <entry key="currencyCode">USD</entry>
         <entry key="shopId">ITUNES</entry>
         <entry key="status">PAYMENT-DONE</entry>
         <entry key="subId">&lt;none&gt;</entry>
      </attributes>
   </ApplicationEvent>

2. This is what is received at the Consumer just before unmarshaling with
JAXB (a conversion between types is performed, see BodyType and Body
properties):
>>> (route8)
from(endpoint:urn:com.myreks:bus:event:ApplicatonEventsChannelConsumer) -->
wireTap(endpoint:urn:com.myreks:bus:event:EventStoreChannelProducer) <<<
Pattern:InOnly, Headers:{...},
BodyType:org.apache.servicemix.nmr.core.util.StringSource, Body:[Body is
instance of java.xml.transform.StreamSource]

2.1. Log just before unmarshal: (nothing changes)
>>> (route6)
from(endpoint:urn:com.myreks:bus:event:EventStoreChannelConsumer) -->
log://events-logger-jaxb <<< Pattern:InOnly, Headers:{...},
BodyType:org.apache.servicemix.nmr.core.util.StringSource, Body:[Body is
instance of java.xml.transform.StreamSource]

2.2. The unmarshalling (although it says Marshal the tag used is
<camel:unmarshal/>):
>>> (route9) log://events-logger-jaxb -->
Marshal[ref:JAXB-com.myreks.api.model] <<< Pattern:InOnly, Headers:{...},
BodyType:org.apache.servicemix.nmr.core.util.StringSource, Body:[Body is
instance of java.xml.transform.StreamSource]

2.3. Then at line 50 of org.apache.camel.processor.UnmarshalProcessor a
conversion to InputStream is done and later on this exception is thrown:
java.io.IOException: javax.xml.bind.UnmarshalException: unexpected element
(uri:"", local:"ApplicationEvent"). Expected elements are <{
http://api.myreks.com/ApplicationEvent}ApplicationEvent>
at
org.apache.camel.converter.jaxb.JaxbDataFormat.unmarshal(JaxbDataFormat.java:162)[232:org.apache.camel.camel-jaxb:2.8.0.fuse-01-13]
at
org.apache.camel.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:57)[89:org.apache.camel.camel-core:2.8.0.fuse-01-13]
at
org.apache.camel.impl.converter.AsyncProcessorTypeConverter$ProcessorToAsyncProcessorBridge.process(AsyncProcessorTypeConverter.java:50)[89:org.apache.camel.camel-core:2.8.0.fuse-01-13]
at
org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:78)[89:org.apache.camel.camel-core:2.8.0.fuse-01-13]

*Extra info:*
I've wiretapped the message at step 2, forwarding it to a simple route
where I did <camel:convertBodyTo type="java.lang.String"/> and this was the
output: (no namespace)
>>> (route3)  --> log://events-logger-string <<< Pattern:InOnly,
Headers:{...}, BodyType:String, Body:<?xml version="1.0"
encoding="UTF-8"?><ApplicationEvent>
      <uuid>b22ce63c-aa2b-30ed-bd71-4d5f470d8d03</uuid>
      <type>TX_REPORT</type>
      <action>PAYMENT-DONE</action>
      <timestamp>2011-04-07T15:28:00Z</timestamp>
      <txId>a0c0e205-50ee-49ed-a7de-ba58a6f39cd8</txId>
      <parentTxId/>
      <system>TXREPORT</system>
      <attributes>
         <entry key="commission">4</entry>
         <entry key="currencyCode">USD</entry>
         <entry key="shopId">ITUNES</entry>
         <entry key="status">PAYMENT-DONE</entry>
         <entry key="subId">&lt;none&gt;</entry>
      </attributes>
   </ApplicationEvent>


Sorry for the long message, but I hope all this info may give you some
light to help me understand how to fix the lost namespace.

Regards,
*Henrique Viecili*
Myreks