I am trying to have a camel route, which would accept a payload on a http endpoint and then write that payload to a JMS queue.
The route that I have so far is below. But an empty message gets delivered to the jms queue. A message gets there, but it has no body.
Heres the route:
<route >
<from uri="jetty:http://0.0.0.0:8050/add/Customer"/>
<inOnly uri="jms:queue:Q.Customer" />
</route>
Heres the payload that I'm sending into to 'http://0.0.0.0:8050/add/Customer' endpoint:
<Customer xmlns="http://www.openapplications.org/9" xmlns:lw="http://www.org/9">
<Name>John</Name>
<Gender>Female</Gender>
</Customer>
Any inputs on why the message body is not being written to the jms queue?
Thanks...
Your routes worked as expected. I tested it with following setup:
<broker xmlns="http://activemq.apache.org/schema/core" useJmx="true" persistent="false">
<transportConnectors>
<transportConnector uri="tcp://localhost:61616" />
</transportConnectors>
</broker>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="failover:tcp://localhost:61616" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route >
<from uri="jetty:http://0.0.0.0:8050/add/Customer"/>
<inOnly uri="jms:queue:Q.Customer" />
</route>
<route>
<from uri="jms:queue:Q.Customer" />
<log message="Body: ${body}" />
</route>
</camelContext>
I tested the route using the org.apache.camel.spring.Main helper class:
Main main = new Main();
main.setApplicationContextUri("META-INF/spring/jms-inout-producer.xml"); // change this
main.start();
final Object body = "<Customer xmlns=\"http://www.openapplications.org/9\" xmlns:lw=\"http://www.org/9\"><Name>John</Name><Gender>Female</Gender></Customer>";
final ProducerTemplate template = main.getCamelTemplate();
template.requestBody("http://localhost:8050/add/Customer", body);
This lead to following output:
INFO Body: <Customer xmlns="http://www.openapplications.org/9" xmlns:lw="http://www.org/9"><Name>John</Name><Gender>Female</Gender></Customer>
Related
I want to handle errors depending on the http code response.
I would also like to know how to enable *throwExceptionOnFailure* on my route. For example, if the response code is 500x, send the message to the queue "redmine_errors"
UPDATE 4:
my blueprint after add exception from answer #fg78nc (don't work)
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd
http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
">
<bean id="tfsToRedmineMapper"
class="com.stackabuse.example.TfsToRedmineMapper" />
<bean id="myBean" class="com.stackabuse.example.MyBean" />
<camelContext
xmlns="http://camel.apache.org/schema/blueprint">
<onException>
<exception>org.apache.camel.http.common.HttpOperationFailedException
</exception>
<onWhen>
<method ref="myBean" method="parseException" />
</onWhen>
<handled>
<constant>true</constant>
</handled>
<to uri="log:redmine_errors" />
</onException>
<route>
<from uri="jetty:http://0.0.0.0:8082/test" />
<inOnly uri="activemq://from_tfs" />
</route>
<route>
<from uri="activemq://from_tfs" />
<process ref="tfsToRedmineMapper" />
<to uri="activemq://for_redmine" />
</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>my_redmine_api_token</constant>
</setHeader>
<toD uri="${header.url}" />
</route>
ERROR:
2019-02-15 09:35:12,103 | ERROR | mix-7.0.1/deploy | BlueprintCamelContext | 40 - org.apache.camel.camel-blueprint - 2.16.5 | Error occurred during starting Camel: CamelContext(camel-32) due Failed to create route route48 at: >>> OnException[null When[bean{} -> []] -> [To[activemq://redmine_errors]]] <<< in route: Route(route48)[[From[jetty:http://0.0.0.0:8082/test]] -> [On... because of org.apache.camel.http.common.HttpOperationFailedException
org.apache.camel.FailedToCreateRouteException: Failed to create route route48 at: >>> OnException[null When[bean{} -> []] -> [To[activemq://redmine_errors]]] <<< in route: Route(route48)[[From[jetty:http://0.0.0.0:8082/test]] -> [On... because of org.apache.camel.http.common.HttpOperationFailedException
enter image description here
enter image description here
Unfortunately, Camel does not set correctly Http status code.
Solution below is a little bit convoluted, but it works.
It can also be solved within XML with the simple language predicate, but somehow it did not work for me, so I used Java for predicate.
Blueprint :
<bean id="myBean" class="com.example.MyBean" />
<onException>
<exception>org.apache.camel.http.common.HttpOperationFailedException</exception>
<onWhen>
<method ref="myBean" method="parseException" />
</onWhen>
<handled>
<constant>true</constant>
</handled>
<to uri="jms:redmine_errors"/>
</onException>
Java :
package com.example;
public class MyBean {
public boolean parseException(Exchange exchange){
return exchange.getProperty("CamelExceptionCaught")
.toString().contains("statusCode: 500");
}
}
I am using Apache camel and jboss fuse, I have created a sample route blue print listed below in, i have sucessfully handling exceptions in all my routes now the problem is i can not find any example of throttling in routes as i have defined. in apache camel documentation, they have given simple DSL throttling and in stackoverflow i have found rabbitMq throttling which is not my case. how to throttle routes like this in apache camel
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cxf:rsServer address="/testservice" id="testserver" serviceClass="com.company.HelloBean">
<camelContext id="testContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route id="testRoute" >
<throttle timePeriodMillis="10000">
<constant>3</constant>
<from id="_from1" uri="cxfrs:bean:testserver"/>
<bean beanType="com.company.HelloBean"
id="_bean1" method="hello"/>
</throttle>
</route>
</camelContext>
</blueprint>
this give error when in deploy application in jboss fuse. that can not find service
hy, all you need is you are currently defining your from endpoint in throttle tag which is wrong you need to define the throttling tag only in TO tag like this
<throttle id="_throttle1" rejectExecution="true" timePeriodMillis="10000">
<constant>1</constant>
<bean beanType="com.company.HelloBean"
id="_bean1" method="hello"/>
</throttle>
when requests come to an end point from, you will throttle while requests are going TO another end point you are using beans so, you can do something like this
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cxf:rsServer address="/testservice" id="testserver" serviceClass="com.evampsaanga.gethomepage.GetHomePageDataLand">
<cxf:providers>
<bean class="com.evampsaanga.restresponses.ExceptionHandler" id="securityException"/>
</cxf:providers>
</cxf:rsServer>
<!-- <bean class="com.saanga.servicetest.THR" id="myPolicy"/> -->
<camelContext id="testContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route id="testRoute" >
<from id="_from1" uri="cxfrs:bean:testserver"/>
<log id="_log1" message="header : ${headers}"/>
<setHeader headerName="headerbalance" id="_setHeader1">
<simple>${headers}</simple>
</setHeader>
<setBody id="_setBody1">
<simple>${body}</simple>
</setBody>
<throttle id="_throttle1" rejectExecution="true" timePeriodMillis="10000">
<constant>1</constant>
<bean beanType="com.evampsaanga.gethomepage.GetHomePageDataLand"
id="_bean1" method="Get"/>
</throttle>
</route>
</camelContext>
</blueprint>
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.
I have to stock my object (CcRequest) in a DeadLetterQueue with Json format.
How it is possible ?
Here my simple context :
<camelContext id="el1DMRCamelContext" autoStartup="true" xmlns="http://camel.apache.org/schema/blueprint" >
<template id="producerTemplate" />
<!-- Routes -->
<route id="createCcProcessorRoute" errorHandlerRef="createCcErrorHandler" >
<from uri="activemq:queue:createCc" />
<process ref="createCcProcessor" />
</route>
</camelContext>
<bean id="createCcErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder" >
<property name="deadLetterUri" value="activemq:queue:createCcDLQ" />
<property name="redeliveryPolicy" ref="redeliveryPolicy" />
</bean>
I would like my object (CcRequest stocked in the body of the exchange) in my activemq:queue:createCcDLQ to be in Json format instead of binaries.
Is it possible ?
I would not classify what you want to do as a dead letter handler. Dead letter is usually just moving/redelivery of the original message.
It is pretty simple you use the excetion clause instead.
<dataFormats>
<json id="jsonFormat" library="Jackson"/>
</dataFormats>
<onException>
<exception>java.lang.RuntimeException</exception>
<marshal ref="jsonFormat"/>
<to uri="activemq:queue:createCcDLQ"/>
</onException>
Camel Exception Clause docs
Camel JSON docs
I have a service which has two operations.
RegisterUser
UpdateUser
I have a camel rout:
<camel:route id="myRoute">
<camel:from uri="cxf:bean:myListenerEndpoint?dataFormat=POJO&synchronous=true" />
<camel:bean ref="processor" method="processMessage"/>
<camel:to uri="xslt:file:resources/service/2.0.0/UserRegistration.xsl"/>
<camel:to uri="cxf:bean:myTargetEndpoint"/>
</camel:route>
In my processor bean, when I specify:
RegisterUser registerUser = exchange.getIn().getBody(RegisterUser.class);
I get the register user object. Everything works fine.
The problem is that I want camel to route my request conditionally, for e.g:
If the service operation is RegisterUser I want to route the message to my specific bean and if the service operation is UpdateUser I want to route the message to the other bean.
I have tried to use camel xPath, but it not seems to be working.
<camel:route id="myRoute">
<camel:from uri="cxf:bean:myListenerEndpoint?dataFormat=POJO&synchronous=true" />
<camel:choice>
<camel:when>
<camel:xpath>
//RegisterUser
</camel:xpath>
<camel:bean ref="processor" method="processMessage"/>
<camel:to uri="xslt:file:resources/service/2.0.0/UserRegistration.xsl"/>
</camel:when>
</camel:choice>
<camel:to uri="cxf:bean:myTargetEndpoint"/>
</camel:route>
I was searching how to set up camel to route to the different targets but did not find anything. Maybe somebody knows where might be the problem?
The information of the operation required will be in the header of the message.
The header you are looking for is called 'operationName'
So here is an example :
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route id="example">
<from uri="cxf:bean:myListenerEndpoint?dataFormat=POJO&synchronous=true" />
<log message="The expected operation is :: ${headers.operationName}" />
<choice>
<when>
<simple>${headers.operationName} == 'RegisterUser'</simple>
<bean ref="processor" method="processMessage"/>
<to uri="xslt:file:resources/service/2.0.0/UserRegistration.xsl"/>
</when>
<when>
<simple>${headers.operationName} == 'UpdateUser'</simple>
<!-- Do the update user logic here -->
<bean ref="processor" method="updateUser" />
</when>
</choice>
<to uri="cxf:bean:myTargetEndpoint"/>
</route>
</camelContext>
(Note the example is using apache aries blueprint - but it will be identical for spring, other than the namespace)
try using camel-simple expressions instead of xpath for this...
<when><simple>${body} is 'com.RegisterUser'</simple><to uri="..."/></when>
Spring XML route
In my case I use inbound Jetty EP.
I check parametr in request.
Invole URL http://localhost:8080/srv?alg=1
<choice id="_choice1">
<when id="_when1">
<simple>${in.header.alg} == '1'</simple>
<log id="_log10" message="LOG ALG 1"/>
</when>
...
<otherwise id="_otherwise1">
<setFaultBody id="_setFaultBody1">
<constant>Return message about ERROR</constant>
</setFaultBody>
</otherwise>
</choice>
final CamelContext context = exchange.getContext();
if (isAlive) {
context.startRoute("table-reader-route");
log.info("starting dailycase route= " + response);
} else {
context.stopRoute("table-reader-route");
log.info("stoping dailycase route= " + response);
}