You can unmarshal well formed xml without the type and then use an xpath and 
choice to decide what to do with the different XMLs.  This might mean some 
extra steps, but it should work.  The error handling method could be a little 
messy.

Another lower level way would be to inspect what's in the body in a processor 
and setting a header or property of the type.  Then you can use a choice to 
basically route to the correct unmarshal code.  You can use String find, or 
regex if you want to do this and keep the body intact, then you can unmarshal 
the way you do below.


-----Original Message-----
From: Ron Cecchini [mailto:roncecch...@comcast.net] 
Sent: Tuesday, June 25, 2019 12:10 PM
To: users@camel.apache.org
Subject: Re: How to unmarshal when you don't know what you're unmarshalling?

[[ SEI WARNING *** This email was sent from an external source. Do not open 
attachments or click on links from unknown or suspicious senders. *** ]]


Unfortunately, I can't.

The device I'm listening to sends a mix of "Status" and "Data" messages over 
the same UDP port.

I've been trying to implement the strategy I alluded to, using doTry/doCatch to 
try unmarshalling as one message type, and then the other ... but things have 
gotten gnarly:

I first solved the problem having to do with the Camel Java DSL not handling 
nested doTry blocks very well.  (I broke up the route, used some "direct" 
routes, etc.)

Ok, fine.

The problem I've been banging my head on *now*, though, is the fact that it 
*seems* that trying to do the first unmarshal() blows away any properties I set 
on the exchange!  What the heck...

In other words:

When I first get something off the wire (the message over UDP), I save a copy 
of the body:

        .setProperty("bodyCopy", body())

Here's the first bit of processing.  I've added a bunch of logging.
In the log statement immediately before the unmarshal, the 'bodyCopy' is there.
Immediately after the unmarshal, it's gone. 

        .doTry()
            .log("doTry: BEFORE unmarshal - bodyCopy: ${property[bodyCopy]}")
            .unmarshal(dataMessageFormat)
            .log("doTry: BEFORE process - bodyCopy: ${property[bodyCopy]}")
            .process(new DataMessageProcessor())
        .doCatch(Exception.class)
            .log("*** ERROR: couldn't unmarshal or process Data Message; will 
try as Status Message")
            .log("about to setBody - bodyCopy: ${property[bodyCopy]}")
            .setBody(exchangeProperty("bodyCopy"))
            .to("direct:tryStatusMessage")

I found only one other person reporting something similar, back in October 2018:

http://camel.465427.n5.nabble.com/Apache-Camel-JAXB-unmarshalling-returns-null-properties-after-upgrade-from-Camel-from-2-20-4-to-2-211-tt5824549.html

The recommendation was to downgrade the version of 'jaxb-impl' being used -- 
which I'm not using.

FWIW, I created this project from the Camel Spring Boot archetype, which is 
setting the Camel version at 2.21.1.  I'm using 'camel-jaxb-starter' for my 
JAXB, and I wasn't specifying a version.  As a test, I tried changing the 
'camel-jaxb-starter' version to several things, going all the way back to 
version 2.18.0, but that didn't solve my problem.

Strange.....

I'm going to have to come up with some other trick to hang on to the body - so 
that I can reset the body - so that I can attempt the 2nd unmarshal.

Wish me luck....

> On June 25, 2019 at 9:50 AM Michael Davis <michael.da...@solace.com> wrote:
> 
> 
> Can you get the sender to specify which type of file it is using a particular 
> topic or message header or something?
> 
> Michael Davis
> 
> On 2019-06-21, 5:29 PM, "Ron Cecchini" <roncecch...@comcast.net> wrote:
> 
>     Hey, all.
>     
>     I have a route that's sitting on a port and it can receive 1 of 2 
> different XML messages.
>     
>     I was simply going to try to unmarshal with the first one, and if it 
> errors, unmarshal with the next one.
>     
>     But is there a smarter or best practices way to handle this?
>     
>     Thanks.
>     
>     
>     
>

Reply via email to