You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Dragisa Krsmanovic <dk...@plos.org> on 2009/11/21 00:15:53 UTC
Original message body lost in transacted route
I have a transacted route and onException clause that tells Camel to use
original body on redelivery.
If I modify body somewhere in the route, I am expecting to still receive
original body on redelivery.
That works fine if I do something like setBody(constant("xyz")), but if
I use setBody(bean("somebean")) or to("bean:somebean") the body seems to
be lost.
Happens both in 2.1-SNAPSHOT and 2.0.0
Here is unit test:
===================== OnExceptionTest-context.xml ======================
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd">
<!-- This creates an embedded ActiveMQ Broker -->
<broker xmlns="http://activemq.apache.org/schema/core" useJmx="false"
persistent="false" id="activeMQBroker">
<transportConnectors>
<transportConnector uri="tcp://localhost:61616" />
</transportConnectors>
</broker>
<!-- setup JMS connection factory -->
<bean id="jmsConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory"
depends-on="activeMQBroker">
<property name="brokerURL" value="vm://localhost?create=false"/>
</bean>
<!-- setup spring jms TX manager -->
<bean id="jmsTransactionManager"
class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="foo" class="org.apache.camel.OnExceptionTest$FooBean"/>
<!-- define Camel activemq component -->
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<!-- define the jms consumer/producer as transacted -->
<property name="transacted" value="true"/>
<!-- setup the transaction manager to use -->
<property name="transactionManager" ref="jmsTransactionManager"/>
</bean>
<bean id="routeBuilder" class="org.apache.camel.OnExceptionTest
$TestRoutes"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="routeBuilder"/>
</camelContext>
</beans>
===================== OnExceptionTest.java ======================
package org.apache.camel;
import
org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.annotation.DirtiesContext;
import org.apache.camel.spring.SpringRouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.testng.annotations.Test;
/**
* @author Dragisa Krsmanovic
*/
@ContextConfiguration
public class OnExceptionTest extends AbstractTestNGSpringContextTests {
@EndpointInject(uri = "mock:end")
protected MockEndpoint endpoint;
@EndpointInject(uri = "mock:error")
protected MockEndpoint error;
@EndpointInject(uri = "mock:checkpoint")
protected MockEndpoint checkpoint;
@Produce(uri = "activemq:start")
protected ProducerTemplate start;
@Produce(uri = "activemq:broken")
protected ProducerTemplate broken;
@Test
@DirtiesContext
public void testWithBean() throws InterruptedException {
endpoint.expectedMessageCount(0);
error.expectedMessageCount(1);
checkpoint.expectedMessageCount(3);
checkpoint.allMessages().body().isEqualTo("foo");
broken.sendBody("foo");
checkpoint.assertIsSatisfied();
error.assertIsSatisfied();
endpoint.assertIsSatisfied();
}
@Test
@DirtiesContext
public void testWithConstant() throws InterruptedException {
endpoint.expectedMessageCount(0);
error.expectedMessageCount(1);
checkpoint.expectedMessageCount(3);
checkpoint.allMessages().body().isEqualTo("foo");
start.sendBody("foo");
checkpoint.assertIsSatisfied();
error.assertIsSatisfied();
endpoint.assertIsSatisfied();
}
public static class FooBean {
@Handler
public String process(@Body String body) {
return "oh no";
}
}
public static class TestRoutes extends SpringRouteBuilder {
@Override
public void configure() throws Exception {
onException(Exception.class)
.handled(true)
.useOriginalBody()
.maximumRedeliveries(2)
.to("mock:error");
from("activemq:broken")
.transacted()
.to("mock:checkpoint")
.setBody(bean("foo"))
.throwException(new Exception("boo"))
.to("mock:end");
from("activemq:start")
.transacted()
.to("mock:checkpoint")
.setBody(constant(""))
.throwException(new Exception("boo"))
.to("mock:end");
}
}
}
--
Dragisa Krsmanovic
Java Developer
Public Library of Science
http://www.plos.org
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This email is confidential to the intended recipient. If you have received it in error, please notify the sender and delete it from your system. Any unauthorized use, disclosure or copying is not permitted. The views or opinions presented are solely those of the sender and do not necessarily represent those of Public Library of Science unless otherwise specifically stated. Please note that neither Public Library of Science nor any of its agents accept any responsibility for any viruses that may be contained in this e-mail or its attachments and it is your responsibility to scan the e-mail and attachments (if any).
Re: Original message body lost in transacted route
Posted by Claus Ibsen <cl...@gmail.com>.
Hi
Your problem is that you defined a route as
onException(Exception.class)
.handled(true)
.useOriginalBody()
.maximumRedeliveries(2)
.to("mock:error");
from("activemq:broken")
.transacted()
.to("mock:checkpoint")
.setBody(bean("foo"))
.throwException(new Exception("boo"))
.to("mock:end");
Where you use .throrowException as a step in the DSL and expect that
it invokes the "route" at most 2 times because of the onException.
What Camel does is invoke the part of the route that failed and that
part is only the .throwException part.
The .setBody() worked fine.
So instead you should throw the exception from your bean instead so
its the setBody part that fails every time.
On Sat, Nov 21, 2009 at 12:15 AM, Dragisa Krsmanovic
<dk...@plos.org> wrote:
> I have a transacted route and onException clause that tells Camel to use
> original body on redelivery.
>
> If I modify body somewhere in the route, I am expecting to still receive
> original body on redelivery.
>
> That works fine if I do something like setBody(constant("xyz")), but if
> I use setBody(bean("somebean")) or to("bean:somebean") the body seems to
> be lost.
>
> Happens both in 2.1-SNAPSHOT and 2.0.0
>
> Here is unit test:
>
>
> ===================== OnExceptionTest-context.xml ======================
>
> <beans xmlns="http://www.springframework.org/schema/beans"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:amq="http://activemq.apache.org/schema/core"
> xsi:schemaLocation="
> http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
> http://camel.apache.org/schema/spring
> http://camel.apache.org/schema/spring/camel-spring.xsd
> http://activemq.apache.org/schema/core
> http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd">
>
> <!-- This creates an embedded ActiveMQ Broker -->
> <broker xmlns="http://activemq.apache.org/schema/core" useJmx="false"
> persistent="false" id="activeMQBroker">
> <transportConnectors>
> <transportConnector uri="tcp://localhost:61616" />
> </transportConnectors>
> </broker>
>
> <!-- setup JMS connection factory -->
> <bean id="jmsConnectionFactory"
> class="org.apache.activemq.ActiveMQConnectionFactory"
> depends-on="activeMQBroker">
> <property name="brokerURL" value="vm://localhost?create=false"/>
> </bean>
>
> <!-- setup spring jms TX manager -->
> <bean id="jmsTransactionManager"
> class="org.springframework.jms.connection.JmsTransactionManager">
> <property name="connectionFactory" ref="jmsConnectionFactory"/>
> </bean>
>
> <bean id="foo" class="org.apache.camel.OnExceptionTest$FooBean"/>
> <!-- define Camel activemq component -->
> <bean id="activemq"
> class="org.apache.activemq.camel.component.ActiveMQComponent">
> <property name="connectionFactory" ref="jmsConnectionFactory"/>
> <!-- define the jms consumer/producer as transacted -->
> <property name="transacted" value="true"/>
> <!-- setup the transaction manager to use -->
> <property name="transactionManager" ref="jmsTransactionManager"/>
> </bean>
>
> <bean id="routeBuilder" class="org.apache.camel.OnExceptionTest
> $TestRoutes"/>
>
> <camelContext xmlns="http://camel.apache.org/schema/spring">
> <routeBuilder ref="routeBuilder"/>
> </camelContext>
>
> </beans>
>
>
> ===================== OnExceptionTest.java ======================
>
>
> package org.apache.camel;
>
> import
> org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
> import org.springframework.test.context.ContextConfiguration;
> import org.springframework.test.annotation.DirtiesContext;
> import org.apache.camel.spring.SpringRouteBuilder;
> import org.apache.camel.component.mock.MockEndpoint;
> import org.testng.annotations.Test;
>
> /**
> * @author Dragisa Krsmanovic
> */
> @ContextConfiguration
> public class OnExceptionTest extends AbstractTestNGSpringContextTests {
>
> @EndpointInject(uri = "mock:end")
> protected MockEndpoint endpoint;
>
> @EndpointInject(uri = "mock:error")
> protected MockEndpoint error;
>
> @EndpointInject(uri = "mock:checkpoint")
> protected MockEndpoint checkpoint;
>
> @Produce(uri = "activemq:start")
> protected ProducerTemplate start;
>
> @Produce(uri = "activemq:broken")
> protected ProducerTemplate broken;
>
>
> @Test
> @DirtiesContext
> public void testWithBean() throws InterruptedException {
> endpoint.expectedMessageCount(0);
> error.expectedMessageCount(1);
> checkpoint.expectedMessageCount(3);
>
> checkpoint.allMessages().body().isEqualTo("foo");
>
> broken.sendBody("foo");
>
> checkpoint.assertIsSatisfied();
> error.assertIsSatisfied();
> endpoint.assertIsSatisfied();
> }
>
> @Test
> @DirtiesContext
> public void testWithConstant() throws InterruptedException {
> endpoint.expectedMessageCount(0);
> error.expectedMessageCount(1);
> checkpoint.expectedMessageCount(3);
>
> checkpoint.allMessages().body().isEqualTo("foo");
>
> start.sendBody("foo");
>
> checkpoint.assertIsSatisfied();
> error.assertIsSatisfied();
> endpoint.assertIsSatisfied();
> }
>
>
> public static class FooBean {
> @Handler
> public String process(@Body String body) {
> return "oh no";
> }
> }
>
> public static class TestRoutes extends SpringRouteBuilder {
>
> @Override
> public void configure() throws Exception {
>
> onException(Exception.class)
> .handled(true)
> .useOriginalBody()
> .maximumRedeliveries(2)
> .to("mock:error");
>
> from("activemq:broken")
> .transacted()
> .to("mock:checkpoint")
> .setBody(bean("foo"))
> .throwException(new Exception("boo"))
> .to("mock:end");
>
> from("activemq:start")
> .transacted()
> .to("mock:checkpoint")
> .setBody(constant(""))
> .throwException(new Exception("boo"))
> .to("mock:end");
>
> }
> }
> }
>
>
> --
> Dragisa Krsmanovic
> Java Developer
> Public Library of Science
> http://www.plos.org
>
>
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> This email is confidential to the intended recipient. If you have received it in error, please notify the sender and delete it from your system. Any unauthorized use, disclosure or copying is not permitted. The views or opinions presented are solely those of the sender and do not necessarily represent those of Public Library of Science unless otherwise specifically stated. Please note that neither Public Library of Science nor any of its agents accept any responsibility for any viruses that may be contained in this e-mail or its attachments and it is your responsibility to scan the e-mail and attachments (if any).
>
>
--
Claus Ibsen
Apache Camel Committer
Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus
Re: Original message body lost in transacted route
Posted by Claus Ibsen <cl...@gmail.com>.
Hi
I have created a ticket as I found a bug in Camel when you mix and
match transacted routes with Camel redelivery.
https://issues.apache.org/activemq/browse/CAMEL-2208
See my unit tests in this commit log:
http://svn.apache.org/viewvc?rev=882870&view=rev
On Sat, Nov 21, 2009 at 12:15 AM, Dragisa Krsmanovic
<dk...@plos.org> wrote:
> I have a transacted route and onException clause that tells Camel to use
> original body on redelivery.
>
> If I modify body somewhere in the route, I am expecting to still receive
> original body on redelivery.
>
> That works fine if I do something like setBody(constant("xyz")), but if
> I use setBody(bean("somebean")) or to("bean:somebean") the body seems to
> be lost.
>
> Happens both in 2.1-SNAPSHOT and 2.0.0
>
> Here is unit test:
>
>
> ===================== OnExceptionTest-context.xml ======================
>
> <beans xmlns="http://www.springframework.org/schema/beans"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:amq="http://activemq.apache.org/schema/core"
> xsi:schemaLocation="
> http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
> http://camel.apache.org/schema/spring
> http://camel.apache.org/schema/spring/camel-spring.xsd
> http://activemq.apache.org/schema/core
> http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd">
>
> <!-- This creates an embedded ActiveMQ Broker -->
> <broker xmlns="http://activemq.apache.org/schema/core" useJmx="false"
> persistent="false" id="activeMQBroker">
> <transportConnectors>
> <transportConnector uri="tcp://localhost:61616" />
> </transportConnectors>
> </broker>
>
> <!-- setup JMS connection factory -->
> <bean id="jmsConnectionFactory"
> class="org.apache.activemq.ActiveMQConnectionFactory"
> depends-on="activeMQBroker">
> <property name="brokerURL" value="vm://localhost?create=false"/>
> </bean>
>
> <!-- setup spring jms TX manager -->
> <bean id="jmsTransactionManager"
> class="org.springframework.jms.connection.JmsTransactionManager">
> <property name="connectionFactory" ref="jmsConnectionFactory"/>
> </bean>
>
> <bean id="foo" class="org.apache.camel.OnExceptionTest$FooBean"/>
> <!-- define Camel activemq component -->
> <bean id="activemq"
> class="org.apache.activemq.camel.component.ActiveMQComponent">
> <property name="connectionFactory" ref="jmsConnectionFactory"/>
> <!-- define the jms consumer/producer as transacted -->
> <property name="transacted" value="true"/>
> <!-- setup the transaction manager to use -->
> <property name="transactionManager" ref="jmsTransactionManager"/>
> </bean>
>
> <bean id="routeBuilder" class="org.apache.camel.OnExceptionTest
> $TestRoutes"/>
>
> <camelContext xmlns="http://camel.apache.org/schema/spring">
> <routeBuilder ref="routeBuilder"/>
> </camelContext>
>
> </beans>
>
>
> ===================== OnExceptionTest.java ======================
>
>
> package org.apache.camel;
>
> import
> org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
> import org.springframework.test.context.ContextConfiguration;
> import org.springframework.test.annotation.DirtiesContext;
> import org.apache.camel.spring.SpringRouteBuilder;
> import org.apache.camel.component.mock.MockEndpoint;
> import org.testng.annotations.Test;
>
> /**
> * @author Dragisa Krsmanovic
> */
> @ContextConfiguration
> public class OnExceptionTest extends AbstractTestNGSpringContextTests {
>
> @EndpointInject(uri = "mock:end")
> protected MockEndpoint endpoint;
>
> @EndpointInject(uri = "mock:error")
> protected MockEndpoint error;
>
> @EndpointInject(uri = "mock:checkpoint")
> protected MockEndpoint checkpoint;
>
> @Produce(uri = "activemq:start")
> protected ProducerTemplate start;
>
> @Produce(uri = "activemq:broken")
> protected ProducerTemplate broken;
>
>
> @Test
> @DirtiesContext
> public void testWithBean() throws InterruptedException {
> endpoint.expectedMessageCount(0);
> error.expectedMessageCount(1);
> checkpoint.expectedMessageCount(3);
>
> checkpoint.allMessages().body().isEqualTo("foo");
>
> broken.sendBody("foo");
>
> checkpoint.assertIsSatisfied();
> error.assertIsSatisfied();
> endpoint.assertIsSatisfied();
> }
>
> @Test
> @DirtiesContext
> public void testWithConstant() throws InterruptedException {
> endpoint.expectedMessageCount(0);
> error.expectedMessageCount(1);
> checkpoint.expectedMessageCount(3);
>
> checkpoint.allMessages().body().isEqualTo("foo");
>
> start.sendBody("foo");
>
> checkpoint.assertIsSatisfied();
> error.assertIsSatisfied();
> endpoint.assertIsSatisfied();
> }
>
>
> public static class FooBean {
> @Handler
> public String process(@Body String body) {
> return "oh no";
> }
> }
>
> public static class TestRoutes extends SpringRouteBuilder {
>
> @Override
> public void configure() throws Exception {
>
> onException(Exception.class)
> .handled(true)
> .useOriginalBody()
> .maximumRedeliveries(2)
> .to("mock:error");
>
> from("activemq:broken")
> .transacted()
> .to("mock:checkpoint")
> .setBody(bean("foo"))
> .throwException(new Exception("boo"))
> .to("mock:end");
>
> from("activemq:start")
> .transacted()
> .to("mock:checkpoint")
> .setBody(constant(""))
> .throwException(new Exception("boo"))
> .to("mock:end");
>
> }
> }
> }
>
>
> --
> Dragisa Krsmanovic
> Java Developer
> Public Library of Science
> http://www.plos.org
>
>
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> This email is confidential to the intended recipient. If you have received it in error, please notify the sender and delete it from your system. Any unauthorized use, disclosure or copying is not permitted. The views or opinions presented are solely those of the sender and do not necessarily represent those of Public Library of Science unless otherwise specifically stated. Please note that neither Public Library of Science nor any of its agents accept any responsibility for any viruses that may be contained in this e-mail or its attachments and it is your responsibility to scan the e-mail and attachments (if any).
>
>
--
Claus Ibsen
Apache Camel Committer
Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus
Re: Original message body lost in transacted route
Posted by Claus Ibsen <cl...@gmail.com>.
On Mon, Nov 23, 2009 at 6:31 PM, Dragisa Krsmanovic
<dk...@plos.org> wrote:
> On Sat, 2009-11-21 at 09:20 +0100, Claus Ibsen wrote:
>> Hi
>>
>> Digged a bit deeper and seems the issue is that the assertion on the
>> constant seems wrong as you set the body to an empty string.
>> Which then causes Camel to look into the backing JMS message where it
>> can find the "foo" body. Despite the body is "".
>>
>> Seems as Camel in the setBody should also set a DefaultMessage to
>> prevent still propagating specialized messages contains when you have
>> changed the body to something else.
>> Using this the backing JMS message will be gone and the "foo" message
>> is not present anymore.
>>
>> The problem is that you want to use transacted routes and using Camel
>> redelivery policies, eg the stuff you do with onException.
>> What happens at runtime is that the message is NOT rolled back to the
>> JMS queue as Camel does local error handling. So after 2 errors its
>> just handled=true and moved to a mock.
>>
>> And .useOriginalBody() is only triggered when the message is moved to
>> the mock:error queue.
>>
>>
>
> Thanks! This clears up many things. Perhaps documentation should be more
> detailed on transacted vs. non-transacted error handling.
>
There is already a lot of error handling documentation at the wiki.
And contributions is welcome.
See more at
http://camel.apache.org/contributing.html
I have enough write responsibility at the moment with the book. So I
dont have time to work on wiki docs.
As a matter of fact I am currently writing on chapter 9 which is about
using transactions with Camel.
So in the book you will have 30+ pages of documentation.
> Another question. I want to redeliver N times and, if all fail, send
> message to another queue. If I want messages to be rolled back to JMS
> each time (not redelivered to the failed part of the route). How would I
> do that ?
>
>
If I understand you questions correct then configure the JMS broker
to redeliver N times and move the message to X DLQ.
If using AMQ then check its documentation how to do this.
> --
> Dragisa Krsmanovic
> Java Developer
> Public Library of Science
> http://www.plos.org
>
>
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> This email is confidential to the intended recipient. If you have received it in error, please notify the sender and delete it from your system. Any unauthorized use, disclosure or copying is not permitted. The views or opinions presented are solely those of the sender and do not necessarily represent those of Public Library of Science unless otherwise specifically stated. Please note that neither Public Library of Science nor any of its agents accept any responsibility for any viruses that may be contained in this e-mail or its attachments and it is your responsibility to scan the e-mail and attachments (if any).
>
>
--
Claus Ibsen
Apache Camel Committer
Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus
Re: Original message body lost in transacted route
Posted by Dragisa Krsmanovic <dk...@plos.org>.
On Sat, 2009-11-21 at 09:20 +0100, Claus Ibsen wrote:
> Hi
>
> Digged a bit deeper and seems the issue is that the assertion on the
> constant seems wrong as you set the body to an empty string.
> Which then causes Camel to look into the backing JMS message where it
> can find the "foo" body. Despite the body is "".
>
> Seems as Camel in the setBody should also set a DefaultMessage to
> prevent still propagating specialized messages contains when you have
> changed the body to something else.
> Using this the backing JMS message will be gone and the "foo" message
> is not present anymore.
>
> The problem is that you want to use transacted routes and using Camel
> redelivery policies, eg the stuff you do with onException.
> What happens at runtime is that the message is NOT rolled back to the
> JMS queue as Camel does local error handling. So after 2 errors its
> just handled=true and moved to a mock.
>
> And .useOriginalBody() is only triggered when the message is moved to
> the mock:error queue.
>
>
Thanks! This clears up many things. Perhaps documentation should be more
detailed on transacted vs. non-transacted error handling.
Another question. I want to redeliver N times and, if all fail, send
message to another queue. If I want messages to be rolled back to JMS
each time (not redelivered to the failed part of the route). How would I
do that ?
--
Dragisa Krsmanovic
Java Developer
Public Library of Science
http://www.plos.org
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This email is confidential to the intended recipient. If you have received it in error, please notify the sender and delete it from your system. Any unauthorized use, disclosure or copying is not permitted. The views or opinions presented are solely those of the sender and do not necessarily represent those of Public Library of Science unless otherwise specifically stated. Please note that neither Public Library of Science nor any of its agents accept any responsibility for any viruses that may be contained in this e-mail or its attachments and it is your responsibility to scan the e-mail and attachments (if any).
Re: Original message body lost in transacted route
Posted by Claus Ibsen <cl...@gmail.com>.
Hi
Digged a bit deeper and seems the issue is that the assertion on the
constant seems wrong as you set the body to an empty string.
Which then causes Camel to look into the backing JMS message where it
can find the "foo" body. Despite the body is "".
Seems as Camel in the setBody should also set a DefaultMessage to
prevent still propagating specialized messages contains when you have
changed the body to something else.
Using this the backing JMS message will be gone and the "foo" message
is not present anymore.
The problem is that you want to use transacted routes and using Camel
redelivery policies, eg the stuff you do with onException.
What happens at runtime is that the message is NOT rolled back to the
JMS queue as Camel does local error handling. So after 2 errors its
just handled=true and moved to a mock.
And .useOriginalBody() is only triggered when the message is moved to
the mock:error queue.
On Sat, Nov 21, 2009 at 12:15 AM, Dragisa Krsmanovic
<dk...@plos.org> wrote:
> I have a transacted route and onException clause that tells Camel to use
> original body on redelivery.
>
> If I modify body somewhere in the route, I am expecting to still receive
> original body on redelivery.
>
> That works fine if I do something like setBody(constant("xyz")), but if
> I use setBody(bean("somebean")) or to("bean:somebean") the body seems to
> be lost.
>
> Happens both in 2.1-SNAPSHOT and 2.0.0
>
> Here is unit test:
>
>
> ===================== OnExceptionTest-context.xml ======================
>
> <beans xmlns="http://www.springframework.org/schema/beans"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> xmlns:amq="http://activemq.apache.org/schema/core"
> xsi:schemaLocation="
> http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
> http://camel.apache.org/schema/spring
> http://camel.apache.org/schema/spring/camel-spring.xsd
> http://activemq.apache.org/schema/core
> http://activemq.apache.org/schema/core/activemq-core-5.3.0.xsd">
>
> <!-- This creates an embedded ActiveMQ Broker -->
> <broker xmlns="http://activemq.apache.org/schema/core" useJmx="false"
> persistent="false" id="activeMQBroker">
> <transportConnectors>
> <transportConnector uri="tcp://localhost:61616" />
> </transportConnectors>
> </broker>
>
> <!-- setup JMS connection factory -->
> <bean id="jmsConnectionFactory"
> class="org.apache.activemq.ActiveMQConnectionFactory"
> depends-on="activeMQBroker">
> <property name="brokerURL" value="vm://localhost?create=false"/>
> </bean>
>
> <!-- setup spring jms TX manager -->
> <bean id="jmsTransactionManager"
> class="org.springframework.jms.connection.JmsTransactionManager">
> <property name="connectionFactory" ref="jmsConnectionFactory"/>
> </bean>
>
> <bean id="foo" class="org.apache.camel.OnExceptionTest$FooBean"/>
> <!-- define Camel activemq component -->
> <bean id="activemq"
> class="org.apache.activemq.camel.component.ActiveMQComponent">
> <property name="connectionFactory" ref="jmsConnectionFactory"/>
> <!-- define the jms consumer/producer as transacted -->
> <property name="transacted" value="true"/>
> <!-- setup the transaction manager to use -->
> <property name="transactionManager" ref="jmsTransactionManager"/>
> </bean>
>
> <bean id="routeBuilder" class="org.apache.camel.OnExceptionTest
> $TestRoutes"/>
>
> <camelContext xmlns="http://camel.apache.org/schema/spring">
> <routeBuilder ref="routeBuilder"/>
> </camelContext>
>
> </beans>
>
>
> ===================== OnExceptionTest.java ======================
>
>
> package org.apache.camel;
>
> import
> org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
> import org.springframework.test.context.ContextConfiguration;
> import org.springframework.test.annotation.DirtiesContext;
> import org.apache.camel.spring.SpringRouteBuilder;
> import org.apache.camel.component.mock.MockEndpoint;
> import org.testng.annotations.Test;
>
> /**
> * @author Dragisa Krsmanovic
> */
> @ContextConfiguration
> public class OnExceptionTest extends AbstractTestNGSpringContextTests {
>
> @EndpointInject(uri = "mock:end")
> protected MockEndpoint endpoint;
>
> @EndpointInject(uri = "mock:error")
> protected MockEndpoint error;
>
> @EndpointInject(uri = "mock:checkpoint")
> protected MockEndpoint checkpoint;
>
> @Produce(uri = "activemq:start")
> protected ProducerTemplate start;
>
> @Produce(uri = "activemq:broken")
> protected ProducerTemplate broken;
>
>
> @Test
> @DirtiesContext
> public void testWithBean() throws InterruptedException {
> endpoint.expectedMessageCount(0);
> error.expectedMessageCount(1);
> checkpoint.expectedMessageCount(3);
>
> checkpoint.allMessages().body().isEqualTo("foo");
>
> broken.sendBody("foo");
>
> checkpoint.assertIsSatisfied();
> error.assertIsSatisfied();
> endpoint.assertIsSatisfied();
> }
>
> @Test
> @DirtiesContext
> public void testWithConstant() throws InterruptedException {
> endpoint.expectedMessageCount(0);
> error.expectedMessageCount(1);
> checkpoint.expectedMessageCount(3);
>
> checkpoint.allMessages().body().isEqualTo("foo");
>
> start.sendBody("foo");
>
> checkpoint.assertIsSatisfied();
> error.assertIsSatisfied();
> endpoint.assertIsSatisfied();
> }
>
>
> public static class FooBean {
> @Handler
> public String process(@Body String body) {
> return "oh no";
> }
> }
>
> public static class TestRoutes extends SpringRouteBuilder {
>
> @Override
> public void configure() throws Exception {
>
> onException(Exception.class)
> .handled(true)
> .useOriginalBody()
> .maximumRedeliveries(2)
> .to("mock:error");
>
> from("activemq:broken")
> .transacted()
> .to("mock:checkpoint")
> .setBody(bean("foo"))
> .throwException(new Exception("boo"))
> .to("mock:end");
>
> from("activemq:start")
> .transacted()
> .to("mock:checkpoint")
> .setBody(constant(""))
> .throwException(new Exception("boo"))
> .to("mock:end");
>
> }
> }
> }
>
>
> --
> Dragisa Krsmanovic
> Java Developer
> Public Library of Science
> http://www.plos.org
>
>
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> This email is confidential to the intended recipient. If you have received it in error, please notify the sender and delete it from your system. Any unauthorized use, disclosure or copying is not permitted. The views or opinions presented are solely those of the sender and do not necessarily represent those of Public Library of Science unless otherwise specifically stated. Please note that neither Public Library of Science nor any of its agents accept any responsibility for any viruses that may be contained in this e-mail or its attachments and it is your responsibility to scan the e-mail and attachments (if any).
>
>
--
Claus Ibsen
Apache Camel Committer
Author of Camel in Action: http://www.manning.com/ibsen/
Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus