Discussion:
Sending CXF JMS message in a transaction
Robert .
2018-10-25 08:09:25 UTC
Permalink
I'm using CXF 3.2.6 and Spring 5.1.0 to create a HTTP SOAP webservice that
uses a JaxWsProxyFactoryBean to call a (one-way) webservice over SOAP JMS.
I would like the message not to be sent if an exception occurs in the
(local) webservice method. So I would like the method to run in a
transaction that commits or rollbacks sending a JMS message.

I have tried several ways to inject the transactional behavior I added the
Transactional annotation to MyHttpWebServiceImpl and defined a
JmsTransactionManager bean, create a JMSConfiguration that sets the
transaction manager, and add the feature to the endpoint. However this has
no effect. The setTransactionManager is also deprecated, but it doesn't
specify what I should do instead. The ActiveMQConnectionFactory
unfortunately also has no method to set a transaction manager. I found very
little documentation how Spring transactions and CXF should play together.
Example code without transactional support:

@Servicepublic class MyHttpWebServiceImpl implements MyHttpWebService {
private MyJmsWebService client;

public void set(MyJmsWebService client) {
this.client = client;
}

public MyResponse update(MyRequest request) {
client.update(request);
throw new RuntimeException("test rollback"); //doesn't work
} }
@Configurationpublic class MyConfiguration {
// JMS webservice endpoint configuration ommitted
private MyHttpWebService webService;

@AutoWired
public void setWebService(MyHttpWebService webService) {
this.webService = webService;
}

@Bean
public ConnectionFactory getConnectionFactory() {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
factory.setBrokerURL("tcp://localhost:61616");
return factory;
}

@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}

@Bean
public Endpoint httpSoapEndpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), webService);
endpoint.publish("/myws");
return endpoint;
}

@Bean
public MyJmsWebService client() {
return (MyJmsWebService) proxyFactoryBean().create();
}

@Bean
public JaxWsProxyFactoryBean proxyFactoryBean() {
String address = "jms:queue:MyQueue?sessionTransacted=true";
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setFeatures(Collections.singletonList(new
ConnectionFactoryFeature(connectionFactory)));
factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setServiceClass(MyJmsWebService.class);
factory.setAddress(address);
return factory;
}}
Christian Schneider
2018-10-26 11:12:06 UTC
Permalink
Hi Robert,

this doc from redhat might help:
https://access.redhat.com/documentation/en-us/red_hat_jboss_fuse/6.2.1/html/transaction_guide/xajms

The key part is to use an ActiveMQXAConnectionFactory and wrap it with a
JcaPooledConnectionFactory. There you inject the transaction manager.

Christian



Am Do., 25. Okt. 2018 um 10:09 Uhr schrieb Robert . <
Post by Robert .
I'm using CXF 3.2.6 and Spring 5.1.0 to create a HTTP SOAP webservice that
uses a JaxWsProxyFactoryBean to call a (one-way) webservice over SOAP JMS.
I would like the message not to be sent if an exception occurs in the
(local) webservice method. So I would like the method to run in a
transaction that commits or rollbacks sending a JMS message.
I have tried several ways to inject the transactional behavior I added the
Transactional annotation to MyHttpWebServiceImpl and defined a
JmsTransactionManager bean, create a JMSConfiguration that sets the
transaction manager, and add the feature to the endpoint. However this has
no effect. The setTransactionManager is also deprecated, but it doesn't
specify what I should do instead. The ActiveMQConnectionFactory
unfortunately also has no method to set a transaction manager. I found very
little documentation how Spring transactions and CXF should play together.
@Servicepublic class MyHttpWebServiceImpl implements MyHttpWebService {
private MyJmsWebService client;
public void set(MyJmsWebService client) {
this.client = client;
}
public MyResponse update(MyRequest request) {
client.update(request);
throw new RuntimeException("test rollback"); //doesn't work
} }
@Configurationpublic class MyConfiguration {
// JMS webservice endpoint configuration ommitted
private MyHttpWebService webService;
@AutoWired
public void setWebService(MyHttpWebService webService) {
this.webService = webService;
}
@Bean
public ConnectionFactory getConnectionFactory() {
ActiveMQConnectionFactory factory = new
ActiveMQConnectionFactory();
factory.setBrokerURL("tcp://localhost:61616");
return factory;
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public Endpoint httpSoapEndpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), webService);
endpoint.publish("/myws");
return endpoint;
}
@Bean
public MyJmsWebService client() {
return (MyJmsWebService) proxyFactoryBean().create();
}
@Bean
public JaxWsProxyFactoryBean proxyFactoryBean() {
String address = "jms:queue:MyQueue?sessionTransacted=true";
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setFeatures(Collections.singletonList(new
ConnectionFactoryFeature(connectionFactory)));
factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICATION_TRANSPORTID);
factory.setServiceClass(MyJmsWebService.class);
factory.setAddress(address);
return factory;
}}
--
--
Christian Schneider
http://www.liquid-reality.de

Computer Scientist
http://www.adobe.com
Loading...