How to set HTTP Method dynamically from blueprint(Camel-http) - java

I use camel-apache companent camel-http. I'm trying to set the http method from my custom header. I use blueprint
override process:
exchange.getOut().setHeader("custom_http_method", "GET");
blueprint route:
<route>
<from uri="activemq://for_redmine" />
<setHeader headerName="Content-Type">
<constant>application/json; charset=utf-8</constant>
</setHeader>
<setHeader headerName="X-Redmine-API-Key">
<constant>beb50ea768f5d16c96030a9dbbf3cb5c4a5ccdcd</constant>
</setHeader>
<setHeader headerName="CamelHttpMethod">
<constant>${header.custom_http_method}</constant>
</setHeader>
<toD uri="${header.url}"/>
</route>
error:
org.apache.camel.TypeConversionException: Error during type conversion from type: java.lang.String to the required type: org.apache.camel.http.common.HttpMethods with value ${header.custom_http_method} due java.lang.IllegalArgumentException: No enum constant org.apache.camel.http.common.HttpMethods.${header.custom_http_method}
as far as I understood, $ {header.custom_http_method} did not return value.
toD uri="${header.url}" - works correctly

Try to use simple instead of constant when setting the header CamelHttpMethod
<route>
<from uri="activemq://for_redmine" />
....
<setHeader headerName="CamelHttpMethod">
<simple>${header.custom_http_method}</simple>
</setHeader>
<toD uri="${header.url}"/>
</route>

Related

Apache Camel. How to manage with a Custom Processor the error raised at runtime

I'm trying to convert my route made with Java DSL in a route made with XML.
The following is my original route that works. And what it does is simple.
Get as input an array of integer and at runtime throws some errors.
At the end of the route I need to read all the error raised by myself and not with a long stacktrace or other long messages in console.
other lines of code...
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
onException(Exception.class)
.handled(true)
.process(new ErrorProcessor());
from("direct:start_route")
.split(body())
.processRef("payloadProcessor")
.to("direct:a")
.end()
.to("direct:d");
from("direct:a")
.beanRef("stupidBean", "stupidMethod");
from("direct:d")
.beanRef("errorProcessor", "check");
}
});
other lines of code...
The following is my xml route that doesn't work.
...
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:call.playWithPayload" />
<onException>
<exception>java.lang.Exception</exception>
<process ref="errorProcessor" />
</onException>
<split onPrepareRef="payloadProcessor">
<simple>${body}</simple>
<to uri="direct:call.a" />
</split>
<to uri="direct:call.d" />
</route>
<!--SUB ROUTE-->
<route>
<from uri="direct:call.a" />
<bean ref="stupidBean" method="stupidMethod" />
</route>
<route>
<from uri="direct:call.d" />
<bean ref="errorProcessor" method="check" />
</route>
</camelContext>
...
What I need is that the direct:call.d is called after the split.
Thanks to this I can read all the errors added into a List<Exception> that is stored into the header.
I think that the problem is in the onException management.
When I try to add the handled to reproduce the my Java DSL
<onException>
...
<handled>
<constant>
true
</constant>
</handled>
...
I got this error:
Invalid content was found starting with element 'handled'.
One of '{"http://camel.apache.org/schema/spring":description, "http://camel.apache.org/schema/spring":exception}' is expected.
Found solution.
My problem was an incorrect format of my xml route.
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<process ref="errorProcessor" />
</onException>
now it works.

Send plain soap over http using camel

I am trying to set up a very simple route to send SOAP content over http and then show the response:
<route>
<from uri="direct:start"/>
<setBody>
<constant><![CDATA[<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"><SOAP:Header></SOAP:Header><SOAP:Body></SOAP:Body></SOAP:Envelope>]]>
</constant>
</setBody>
<to uri="https://localhost:8443/api"/>
<log message="${out.body}"/>
</route>
I am not getting any error but is not really showing the response.
What am I missing here?
I am simply runnig my app like this:
public class App {
public static void main( String[] args ) {
ApplicationContext
ctx = new ClassPathXmlApplicationContext("META-INF/spring/camel-config.xml");
}
}
You have not set some headers.
Try to modify your route like below:
<route>
<from uri="timer://foo?fixedRate=true&period=60000"/>
<setHeader headerName="CamelHttpMethod">
<constant>POST</constant>
</setHeader>
<setHeader headerName="Content-type">
<constant>text/xml;charset=UTF-8</constant>
</setHeader>
<setHeader headerName="Accept-Encoding">
<constant>gzip,deflate</constant>
</setHeader>
<setBody>
<constant><![CDATA[<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"><SOAP:Header></SOAP:Header><SOAP:Body></SOAP:Body></SOAP:Envelope>]]>
</constant>
</setBody>
<to uri="https://localhost:8443/api"/>
<log message="${out.body}"/>
</route>
I have changed the beginning of the route, because I don't know how you're sending messages to direct:start.

Camel get response from Route

I am able to called Web Service, now what ever response came from web service, i need to fetch same response in java code so that i am able to further processing.
<camelContext xmlns="http://camel.apache.org/schema/spring" trace="false">
<route id="my_Sample_Camel_Route_with_CXF">
<from uri="file:src/data?noop=true"/>
<log loggingLevel="INFO" message=">>> ${body}"/>
<to uri="cxf://http://www.webservicex.net/stockquote.asmx?wsdlURL=src/main/resources/META-INF/stockquote.wsdl&serviceName={http://www.webserviceX.NET/}StockQuote&portName={http://www.webserviceX.NET/}StockQuoteSoap&dataFormat=MESSAGE"/>
<log loggingLevel="INFO" message=">>> ${body}"/>
</route>
Instead of logging using

CAMEL: Adding Properties to a message in Spring DSL

I have a simple route in camel, which reads messages from an activemq queue 'A' and writes it to another activemq queue 'B'.I was able to get this to this part to work.
But I need to add a new property to the message before writing it to 'B'. I have tried to add the property 'prop1' to the message using the Spring DSL below, but the property is not being added to the message.
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:queue:A"/>
<setProperty propertyName="prop1">
<simple>prop1Value</simple>
</setProperty>
<to uri="activemq:queue:B"/>
</route>
</camelContext>
Is this the correct way to add a property to a message in SPRING DSL?
Use a header instead of a property:
<route>
<from uri="activemq:queue:A"/>
<setHeader headerName="prop1">
<constant>prop1Value</constant>
</setHeader>
<to uri="activemq:queue:B"/>
</route>
<route>
<from uri="activemq:queue:B" />
<log message="prop1 = ${header.prop1}" />
</route>
Camel headers are transferred to JMS properties which are transferred back to Camel headers as can be seen looking at the implementation of org.apache.camel.component.jms.JMSBinding. The Camel properties are skipped.

Camel AggregationStrategy behaving unexpectedly

I have a situation where I want to pass data into an Aggregator, but I don't want the aggregator to do anything until it has received messages from 3 distinct routes:
<route id="route-1">
<from uri="direct:fizz" />
<to uri="bean:bean1?method=process" />
<setHeader headerName="id">
<constant>1</constant>
</setHeader>
<to uri="direct:aggregator" />
</route>
<route id="route-2">
<from uri="direct:buzz" />
<to uri="bean:bean2?method=process" />
<setHeader headerName="id">
<constant>2</constant>
</setHeader>
<to uri="direct:aggregator" />
</route>
<route id="route-3">
<from uri="direct:foo" />
<to uri="bean:bean3?method=process" />
<setHeader headerName="id">
<constant>3</constant>
</setHeader>
<to uri="direct:aggregator" />
</route>
<route id="aggregator-route">
<from uri="direct:aggregator" />
<aggregate strategyRef="myAggregationStrategy" completionSize="1">
<correlationExpression>
<simple>header.id</simple>
</correlationExpression>
<to uri="bean:lastBean?method=process" />
</aggregate>
</route>
The way this is configured, when the aggregator's completionSize is set to 1 or 2, the aggregated Exchange is routed on to my lastBean. However, if I set completionSize to 3, for some reason, lastBean#process never gets invoked.
I'm sure that I'm using header.id and the aggregator incorrectly here. In the correlationExpression, I just need to make sure that we have 1 Message from each of the 3 routes.
So my question: what do I need to do to make my aggregator "wait" until it has received 1 message from route-1, 1 message from route-2 and 1 message from route-3?
If you are correlating messages from three routes, there needs to be a way for them all to have a matching header.id value by the time they reach the aggregating route.
In your example, each route sets a different id value so there would be no match. If you set the id value to "1" in each route, I think it would start to work as expected.

Categories

Resources