Reputation: 576
We are building a message router based on Apache Camel and decided to use a generic flow for multiple formats. We input our message trough a generic rest endpoint and conditionally map the body of this call onto one of multiple specific message formats. We generated our specific dataformats from different XSD's.
The mapping happens in a processor, which dependending on the content of the message uses a different mapper. This processor puts the specific Java model in the body of the exchange.
In the next step we would like to marshal and validate the body to XML. This is a "generic" step, as all messages must be marshalled to XML. After this they get send to a dynamic endpoint, again based on the message content.
To marshal the XML we use the following route:
from("direct:marshal-xml")
.marshal(jaxbDataFormat)
.to("direct:validate-and-send");
Depending on a header property called "messageType", we would like to use a different jaxbDataFormat object to marshal to XML. We could do this with a choice in the route itself, but we would like to use a dedicated service which takes a string input, the messageType, and returns the correct jaxbDataFormat.
Now the question is how to pass the header property "messageType" as an argument to the service. We would like to use something like:
from("direct:marshal-xml")
.marshal(jaxbDataFormatService.getDataFormat(getHeader("messageType")))
.to("direct:validate-and-send");
But I can't seem to get the messageType as a string from the header. There seems to be a difference between the routebuilder, which "models" the route, and the runtime route, which is generated from this model.
I tried using simple expresions, but I can't seem to evaluate them without an exchange:
simple("${header.messageType}").evaluate(exchange, String.class);
How to solve this problem? Do I have to use the choice component in the routebuilder, or is it possible to use this dedicated service still?
Upvotes: 0
Views: 2033
Reputation: 51441
You can always implement your own "composite data format" for example by implementing org.apache.camel.spi.DataFormat
that will have knowledge of all the data formats you want to use and use the one that you want.
Something like this, just to give you an idea:
public class MyCompositeFormat implements DataFormat, CamelContextAware {
public MyCompositeFormat(DataFormat... formats) {
// store them to local variable
}
public CamelContext getCamelContext() {
return camelContext;
}
public void setCamelContext(CamelContext camelContext) {
this.camelContext = camelContext;
}
public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
if (exchange.getIn().getHeader("SomeHeader",String.class).equals("whatever") {
return someFormatYouStored.marshal(exchange,graph,stream);
} else {
return anotherFormat.marshal(exchange,graph,stream);
}
}
public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
// similar approach to marshal
}
}
And in your route:
MyCompositeFormat myCompositeFormat = new MyCompositeFormat(otherFormats);
from("direct:marshal-xml")
.marshal(myCustomFormat)
.to("direct:validate-and-send");
Upvotes: 2