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;
    }}

Reply via email to