Hi Willem,
I have built a camel-cxf module that includes your patch. Now the rollback
basically works.
The problem is that it happens for all exceptions. I think a good default
would be to return a fault for all exceptions that the service explicitly
defines and roll back for all other exceptions. The problem is I have no
idea how this could be done.
In the meantime I will try to use a onException() clause to do this
differentiation.
I have also created a jira issue for the whole problem.
https://issues.apache.org/activemq/browse/CAMEL-2128
Greetings
Christian
Christian Schneider
Team Handel und Risikomanagement
Informationsverarbeitung Business Solutions Trading
EnBW Systeme Infrastruktur Support GmbH
Informationsverarbeitung
Business Solutions
Handel und Dispatching
Durlacher Allee 93
76131 Karlsruhe
Tel : +49-(0)721-63-15482
Mail: [email protected]
Sitz der Gesellschaft: Karlsruhe
Handelsregister: Amtsgericht Mannheim HRB 108550
Vorsitzender des Aufsichtsrats: Dr. Bernhard Beck
Geschäftsführer: Jochen Adenau, Dr. Peter Krampf
-----Ursprüngliche Nachricht-----
Von: Willem Jiang [mailto:[email protected]]
Gesendet: Montag, 2. November 2009 15:40
An: [email protected]
Betreff: Re: AW: AW: Problem with SOAP/JMS and transactions
Hi Christian,
I'm glade it works on camel side.
For the CXF side , I think we need to check the CXF message's exception
in the Camel transport and let camel throw the exception.
Here is my patch on the latest trunk code (not be verified yet), please
feel free to give it a try.
### Eclipse Workspace Patch 1.0
#P camel-cxf
Index:
src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java
===================================================================
---
src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java
(revision 831871)
+++
src/main/java/org/apache/camel/component/cxf/transport/CamelDestination.java
(working copy)
@@ -271,6 +271,12 @@
propagateResponseHeadersToCamel(outMessage, camelExchange);
+ // check if the outMessage has an exception
+ Exception exception = outMessage.getContent(Exception.class);
+ if (exception != null) {
+ camelExchange.setException(exception);
+ }
+
CachedOutputStream outputStream =
(CachedOutputStream)outMessage.getContent(OutputStream.class);
camelExchange.getOut().setBody(outputStream.getBytes());
getLogger().log(Level.FINE, "send the response message: "
+ outputStream);
Schneider Christian wrote:
Hi Claus,
I have replaced the cxf server with the folowing route:
<route>
<from
uri="jms://queue.net.enbw.services.etg.examples.customerservice.CustomerServ
ice" />
<transacted/>
<to uri="serviceImplProc"/>
</route>
Inside the Processor I simply throw a RuntimeException again. This
configuration works like expected. The transaction is rolled back and the
message gets redelivered. I also had to configure my queue now for
maxRedeliveries to avoid a endless loop.
Btw. I think the redlivery could also be easily controlled inside camel as
Tibco sets the property JMSXDeliveryCount. So I think this could also be
handled in the route if the developer has no access to the jms server
config.
So this part works great.
Thanks already for your help
Christian
Christian Schneider
Team Handel und Risikomanagement
Informationsverarbeitung Business Solutions Trading
EnBW Systeme Infrastruktur Support GmbH
Informationsverarbeitung
Business Solutions
Handel und Dispatching
Durlacher Allee 93
76131 Karlsruhe
Tel : +49-(0)721-63-15482
Mail: [email protected]
Sitz der Gesellschaft: Karlsruhe
Handelsregister: Amtsgericht Mannheim HRB 108550
Vorsitzender des Aufsichtsrats: Dr. Bernhard Beck
Geschäftsführer: Jochen Adenau, Dr. Peter Krampf
-----Ursprüngliche Nachricht-----
Von: Claus Ibsen [mailto:[email protected]]
Gesendet: Montag, 2. November 2009 14:56
An: [email protected]
Betreff: Re: AW: Problem with SOAP/JMS and transactions
On Mon, Nov 2, 2009 at 2:47 PM, Schneider Christian
<[email protected]> wrote:
Hi Willem,
I also suspected it has to do with CXF Wrapping the Exception and not
simply
rethrowing it. Do you think it would help to use pure CXF JMS Transport?
For the start I will try how Claus suggested to get transactions working
without CXF. When this works I will try again to get Camel CXF working
with
it.
You may be able to use
// catch the exceptions here you want to rollback
onException(Exception.class).markRollbackOnly();
Which let Camel mark it as rollback in the spring TX manager.
And which hopefully is sufficient to mark it as rollback on the JMS
broker even thought CXF is wrapping the exception.
However this requires that Camel detects the exception before CXF does :)
And to use the latest code from trunk.
But try out with CXF at first to get it working.
Greetings
Christian
Christian Schneider
Team Handel und Risikomanagement
Informationsverarbeitung Business Solutions Trading
EnBW Systeme Infrastruktur Support GmbH
Informationsverarbeitung
Business Solutions
Handel und Dispatching
Durlacher Allee 93
76131 Karlsruhe
Tel : +49-(0)721-63-15482
Mail: [email protected]
Sitz der Gesellschaft: Karlsruhe
Handelsregister: Amtsgericht Mannheim HRB 108550
Vorsitzender des Aufsichtsrats: Dr. Bernhard Beck
Geschäftsführer: Jochen Adenau, Dr. Peter Krampf
-----Ursprüngliche Nachricht-----
Von: Willem Jiang [mailto:[email protected]]
Gesendet: Montag, 2. November 2009 14:27
An: [email protected]
Betreff: Re: AW: Problem with SOAP/JMS and transactions
Hi Christian,
I think it may relate to the CamelDestination just deal with input and
output stream.
As you know if you throw the exception from the service impl, the
exception will be caught by the CXF interceptor chain and it will be
turned into a soap fault message, then be passed back to the client.
Since the CamelDestination can't know the under layer message is the
fault message, it can't throw the exception to let the camel-jms
component roll back.
Maybe we need to find another way to resolve your issue.
Willem
Schneider Christian wrote:
Hi Willem,
I have adjusted my applicationContext but still my message gets
acknowledged
instead of being rolled back.
My service impl contains:
throw new RuntimeException("Test for transaction");
Any idea what still goes wrong?
Greetings
Christian
----
My applicationcontext now looks like the following. I have also added
<transacted/> to the route for the server.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://cxf.apache.org/transports/camel
http://cxf.apache.org/transports/camel.xsd"
<context:annotation-config/>
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"
/>
<import resource="classpath:META-INF/cxf/cxf-extension-camel.xml"
/>
<import resource="classpath:serviceRuntimeContext.xml" />
<bean id="configProps"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigure
r">
<property name="locations">
<list>
<value>classpath:jms.properties</value>
</list>
</property>
</bean>
<!-- Make sure to read the best practices for design and
implementation before
developing a service for production use.
http://wissen.enbw.net/display/etgsoa/3+-+Design
http://wissen.enbw.net/display/etgsoa/4+-+Entwicklung
-->
<bean id="appModule" class="net.enbw.endur.AppModule">
<property name="customerService" ref="customerService"/>
</bean>
<bean id="serviceImpl" class="net.enbw.endur.ServiceImpl">
</bean>
<!-- SOA configs below -->
<endpoint id="customerServiceEndpoint"
xmlns="http://cxf.apache.org/jaxws"
xmlns:service="http://examples.etg.services.enbw.net/"
serviceName="service:CustomerService"
endpointName="service:CustomerServiceEndpoint"
address="camel://direct:server"
implementor="#serviceImpl">
<features>
<!-- Enables logging of SOAP messages. -->
<logging xmlns="http://cxf.apache.org/core" />
</features>
</endpoint>
<client id="customerService" xmlns="http://cxf.apache.org/jaxws"
xmlns:service="http://examples.etg.services.enbw.net/"
serviceName="service:CustomerService"
endpointName="service:CustomerServiceEndpoint"
serviceClass="net.enbw.services.etg.examples.customerservice.CustomerService
V1"
address="camel://direct:client">
<features>
<!-- Enables logging of SOAP messages. -->
<!-- logging xmlns="http://cxf.apache.org/core"
/-->
</features>
</client>
<camelContext id="camelContext" trace="false"
xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:client"/>
<to
uri="jms://queue.net.enbw.services.etg.examples.customerservice.CustomerServ
ice" />
</route>
<route>
<from
uri="jms://queue.net.enbw.services.etg.examples.customerservice.CustomerServ
ice" />
<transacted/>
<to uri="direct:server" />
</route>
</camelContext>
<!-- See http://camel.apache.org/jms.html -->
<bean id="jms"
class="org.apache.camel.component.jms.JmsComponent">
<constructor-arg index="0">
<ref bean="jmsConfiguration" />
</constructor-arg>
<property name="connectionFactory"
ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfiguration"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="useMessageIDAsCorrelationID" value="true"
/>
<property name="acknowledgementModeName"
value="TRANSACTED"
/>
<property name="explicitQosEnabled" value="true" />
<property name="receiveTimeout"
value="${jms.receiveTimeout}" />
<property name="requestTimeout"
value="${jms.requestTimeout}" />
<property name="recoveryInterval"
value="${jms.recoveryInterval}" />
<property name="timeToLive" value="${jms.timeToLive}" />
<property name="transacted" value="true" />
<property name="transactedInOut" value="true" />
<property name="transactionManager"
ref="jmsTransactionManager"/>
</bean>
<bean id="jmsTransactionManager"
class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory"
ref="jmsConnectionFactory" />
</bean>
<!-- See Tibco EMS documentation -->
<bean id="jmsConnectionFactory"
class="com.tibco.tibjms.TibjmsConnectionFactory">
<property name="serverUrl" value="${jms.serverUrl}" />
<property name="userName" value="${jms.userName}" />
<property name="userPassword" value="${jms.userPassword}"
/>
<property name="reconnAttemptCount"
value="${jms.reconnAttemptCount}" />
<property name="reconnAttemptDelay"
value="${jms.reconnAttemptDelay}" />
</bean>
</beans>