8

we are developing an application with following characteristics:

  • standalone spring 3.1.0.RELEASE application
  • JPA with Hibernate 3.6.7.Final
  • AMQP (RabbitMQ as Server, Spring AMQP as Client)
  • SQL Server 2008 with jTDS driver

We need to synchronize transactions between RabbitMQ and SQL Server, so we are trying to setup XA with atomikos. The problem is that we can´t find a single spring sample configuration file for that situation that actually works. We tried so many combinations using samples from Spring documentation, google, forums, etc. Something is allways missing.

Could someone, please, provide us a such file so we can use it as a starting template for our configuration.

P.S. Do we really need XA?

Thanks.

Ivan Bosnic
  • 1,916
  • 5
  • 21
  • 31
  • Reading some docs it seems that rabbitmq does not support XA. Now I am really curious about what would be a 'perfect' solution... – Ivan Bosnic Apr 12 '12 at 00:41
  • For the synchronization layer, have you considered [Change Data Capture](https://en.wikipedia.org/wiki/Change_data_capture)? [This thread](http://stackoverflow.com/questions/9918519/generating-events-from-sql-server) goes into a little more detail in prose, but it doesn't cover your solution in depth or in code. If this is your fancy, I'll be happy to answer to this here. :) – MrGomez Apr 13 '12 at 23:49

2 Answers2

1

After digging through the various candidate solutions (use of Change Data Capture, adapters for SQL Server Service Broker, and possible conversions from MSMQ to RabbitMQ), I came to a solution that should work for you.

It turns out you can bind WCF clients and service contracts to SQL Server. From here, you can use RabbitMQ's AMQP binding for WCF to translate messages back and forth, as the aforelinked PDF documents in great detail.

I'm unclear on whether an additional transaction manager like XA will be required here, but if you suffer problems with transaction duplication, loops, and mismessaging, it's worth investigating as an intermediary for the connection. If you go that route, you'd need to weld that into your gateway in the same way you've defined in the problem statement. If this needs clarification, I'd be happy to expand on this here.

Best of luck with your application. It sounds like an integration hydra from the outside, but once you get everything talking together, it should work nicely.

MrGomez
  • 23,788
  • 45
  • 72
  • Our application is Java based, so I don't know how (and why) should we use WCF. For now, we are building a custom set of classes for controlling database and message commits. – Ivan Bosnic Apr 15 '12 at 01:25
  • @bosnic The idea here is to use the standard WCF facilities for SQL Server as an interface into RabbitMQ's AMQP bindings, which will allow you to bridge communication between RabbitMQ and SQL Server. This is [very well documented](http://www.rabbitmq.com/releases/rabbitmq-dotnet-client/v1.5.1/rabbitmq-dotnet-client-1.5.1-wcf-service-model.pdf), and it allows you to keep all of the application programming in Java on the RabbitMQ side of things. At least, that's how I see it, if I understand your goals correctly? – MrGomez Apr 15 '12 at 01:35
0

As i know RabbitMQ does not support XA style transactions.

And yes you can do it in Java:

TestConfiguration.java

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.AbstractRabbitConfiguration;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.SingleConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfiguration extends AbstractRabbitConfiguration {

    private String routingKey = "test.queue";
    private String testQueueName = "test.queue";

    public ConnectionFactory getConnectionFactory() {
        SingleConnectionFactory connectionFactory = new SingleConnectionFactory("localhost");
        connectionFactory.setUsername("guest");
        connectionFactory.setPassword("guest");
        return connectionFactory;
    }

    @Override
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory());
        rabbitTemplate.setRoutingKey(routingKey);
        rabbitTemplate.setQueue(testQueueName);
        return rabbitTemplate;

Simple example of send:

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;

public class MessageSender {

    @Autowired
    private AmqpTemplate template;

    public void send(String text) {
        template.convertAndSend(text);
    }
}

..and receive:

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
public class MessageHandler implements MessageListener {
    @Override
    public void onMessage(Message message) {
        System.out.println("Received message: " + message);
    }
}
Voislav Sauca
  • 3,007
  • 2
  • 18
  • 12
  • Um... if I understand the OP correctly, this is precisely the documentation they'd looked at previously and determined did not meet their needs. The trouble is you can't easily go from `SingleConnectionFactory` to a JMS connection to SQL Server, without using one of the solutions that appears, at least from a cursory read, to be unsupported. It bears questioning if @bosnic's team is currently using the [JDBC drivers for SQL Server](http://msdn.microsoft.com/en-us/sqlserver/aa937724) and are simply retrofitting them to meet their needs (as surmised by previous correspondence). – MrGomez Apr 15 '12 at 21:27