Sweet Baby Jesus, I got it, guys!  Thank you so much.

I hadn't used xpath() before, so I started reading and playing with it.

The messages I have to parse are pretty simple, with unique root tags: 
"StatusMessage" or "DataMessage".

So I tried the following and started having success with it:

                .choice()
                    .when().xpath("name(/*) = 'StatusMessage'")
                        .to("direct:StatusMessage")
                    .when().xpath("name(/*) = 'DataMessage'")
                        .to("direct:DataMessage")
                    .otherwise()
                        .log("***** ERROR!  Got an unknown message 
type!\n${body}");

But then I quickly saw that the body was *again* null when entering the 2 
"direct" routes.

I decided not to waste too much time trying to figure out the xpath 
idiosyncracies and instead thought about our old friend "simple" and working 
with the original message as a string (i.e. no unmarshalling).  

It worked like a charm!

Ultimately I went with the following:

        from("netty4:udp://[blahblah]")
                .choice()
                    .when(simple("${bodyAs(String)} contains 'StatusMessage'"))
                        .to("direct:StatusMessage")
                    .when(simple("${bodyAs(String)} contains 'DataMessage'"))
                        .to("direct:DataMessage")
                    .otherwise()
                        .log("***** ERROR!  Got an unknown message 
type!\n${body}");

        from("direct:StatusMessage")
                .doTry()
                    .unmarshal(statusMessageFormat)
                    .process(new StatusMessageProcessor())
                .doCatch(Exception.class)
                    .log("*** ERROR: handling Status Message - exception: 
${exception.message}");

> On June 25, 2019 at 12:52 PM "Hart, James W." <jwh...@seic.com> wrote:
> 
> 
> 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