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." <[email protected]> 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:[email protected]]
> Sent: Tuesday, June 25, 2019 12:10 PM
> To: [email protected]
> 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 <[email protected]> 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" <[email protected]> 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.
> >
> >
> >
> >