Custom XAResource (JTA)

1.4k views Asked by At

Today my team lead asked me to implement a custom XAResource wrapper for one of our internal product (it provides functionality like an SFTP server, but it is distributed, written in Java and has a lot of additional things... Never mind =) ).

An important point here, that our application is a standalone one (thus I need to use an embedded JTA transaction manager like Atomikos) which already has Spring, JMS and Hibernate (that must also be included in a distributed transaction) inside.

The problem is I have Googled for some time and I haven't managed to find any resource with an example of implementing and configuring custom XAResource implementations. P.S. Actually, I have found the XADisk framework, but it would be better to understand the whole process step by step =)

Could somebody, please, share a link or a resource with such an example? Thanks in advance!

UPDATE:

Threre is a useful resource to get an overview of the whole thing: Spring documentation

1

There are 1 answers

1
Dmitry On BEST ANSWER

I ended up with the following. After I had added the Bitronix' libraries to my project with all the sources I saw an interesting example of the EhCache XAResource inside it. I checked how it all worked and duplicated the logic. The only one question left after this: 'How to enlist my resource for a transaction manager?'. In order to do that I wrote the following factory (in my case I needed to make an SFTP resource XA-aware):

@Service
public class XaSftpSessionFactory {

   @Autowired
   private JtaTransactionManager transactionManager;

   public XaSftpSession getSession(final ConnectionSettings settings) {
      if (settings == null) {
           throw new IllegalArgumentException("The specified SFTP connection settings must be not null.");
      }

      final XaSftpSession xaSession = new XaSftpSession(settings);
      final XaSftpResource xaResource = new XaSftpResource(xaSession);
      xaSession.setXaResource(xaResource);

      XaSftpResourceProducer.registerXAResource(settings.getName(), xaResource);

      try {
           Transaction transaction = transactionManager.getTransactionManager().getTransaction();
           transaction.enlistResource(xaResource);
           transaction.registerSynchronization(
            new Synchronization() {
                @Override
                public void beforeCompletion() {
                }

                @Override
                public void afterCompletion( int status ) {
                    XaSftpResourceProducer.unregisterXAResource(settings.getName(), xaResource );
                }
            }
        );
       } catch (RollbackException | SystemException exception) {
          throw new IllegalStateException(
            String.format("Can't create an SFTP session for the '%s' instance.", settings.getName()),
            exception
        );
       }

       return xaSession;
   }
}