// Path: connector/genericconnector-api/src/main/java/ch/maxant/generic_jca_adapter/BasicTransactionAssistanceFactory.java
// public interface BasicTransactionAssistanceFactory {
// 
//     /**
//      * Get transaction assistant from factory so that a callback can be 
//      * bound into the transaction as well as recovery which is controlled
//      * by the app server's transaction manager.
//      * @exception ResourceException Thrown if an assistant can't be obtained
//      */
//     TransactionAssistant getTransactionAssistant() throws ResourceException;   
//     
// }
// 
// Path: connector/genericconnector-api/src/main/java/ch/maxant/generic_jca_adapter/CommitRollbackCallback.java
// public interface CommitRollbackCallback extends Serializable {
// 
//     /** The container will call this function 
//      * to commit a transaction that was successful.
//      * The implementation of this method should
//      * call the EIS in order to commit
//      * the transaction. */
//     void commit(String txid) throws Exception;
//     
//     /** The container will call this function 
//      * to rollback an unsuccessful transaction.
//      * The implementation of this method should
//      * call the EIS in order to rollback
//      * the transaction. */
//     void rollback(String txid) throws Exception;
// 	
// }
// 
// Path: connector/genericconnector-api/src/main/java/ch/maxant/generic_jca_adapter/TransactionAssistant.java
// public interface TransactionAssistant extends AutoCloseable {
// 
//     /** Submit some work (a function) to be bound into the
//      * currently active transaction. */
//     <O> O executeInActiveTransaction(ExecuteCallback<O> tc) throws Exception;
// 
//     /** Call before completing the transaction in order 
//      * to free up resources used by the app server. */
//     @Override
//     void close();
// }
// 
// Path: connector/genericconnector-atomikos-api/src/main/java/ch/maxant/generic_jca_adapter/TransactionConfigurator.java
// public final class TransactionConfigurator {
// 
// 	private TransactionConfigurator() {}
// 	
// 	private static Map<String, RecoverableMSResource> resources = new HashMap<String, RecoverableMSResource>();
// 	
// 	/** one time configuration required for setting up a microservice in a transactional environment. */
// 	public static void setup(String jndiName, final CommitRollbackCallback commitRollbackCallback){
//     	UserTransactionServiceImp utsi = new UserTransactionServiceImp();
//         MicroserviceXAResource ms = new MicroserviceXAResource(jndiName, commitRollbackCallback);
// 		RecoverableMSResource resource = new RecoverableMSResource(ms);
// 		resources.put(jndiName, resource);
// 		utsi.registerResource(resource);
// 	}
// 
// 	/** when your application shutsdown, you should unregister all services that were setup using {@link #setup(String, CommitRollbackHandler)} 
// 	 * or {@link #setup(String, CommitRollbackHandler, long, File)} */
// 	public static void unregisterMicroserviceResourceFactory(String name) {
//     	UserTransactionServiceImp utsi = new UserTransactionServiceImp();
// 		utsi.removeResource(resources.remove(name));
// 	}
// 	
// 	/** @return the {@link CommitRollbackCallback} registered during setup, or null, if none found (eg never registered, or unregistered). */
// 	static CommitRollbackCallback getCommitRollbackCallback(String jndiName){
// 		RecoverableMSResource rr = resources.get(jndiName);
// 		if(rr != null){
// 			return rr.getMicroserviceResource().getUnderlyingConnection();
// 		}
// 		return null;
// 	}
// 	
// }


import ch.maxant.generic_jca_adapter.TransactionAssistant;
import ch.maxant.generic_jca_adapter.TransactionConfigurator;
import ch.maxant.jca_demo.bookingsystem.BookingSystem;
import ch.maxant.jca_demo.bookingsystem.BookingSystemWebServiceService;
import ch.maxant.jca_demo.letterwriter.LetterWebServiceService;
import ch.maxant.jca_demo.letterwriter.LetterWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.naming.Context;
import javax.sql.DataSource;
import bitronix.tm.BitronixTransaction;
import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.jndi.BitronixContext;
import bitronix.tm.resource.ResourceLoader;
import ch.maxant.generic_jca_adapter.BasicTransactionAssistanceFactory;
import ch.maxant.generic_jca_adapter.CommitRollbackCallback;

			private static final long serialVersionUID = 1L;
			@Override
			public void rollback(String txid) throws Exception {
				//compensate by cancelling the letter
				LetterWriter service = new LetterWebServiceService().getLetterWriterPort(); //or take from a pool if you want to
				service.cancelLetter(txid);
			}
			@Override
			public void commit(String txid) throws Exception {
				System.out.println("nothing to do, this service autocommits.");
			}
		};

        {//once per microservice that you want to use - do this when app starts, so that recovery can function immediately
        	TransactionConfigurator.setup("xa/bookingService", bookingCommitRollbackCallback);
        	TransactionConfigurator.setup("xa/letterService", letterCommitRollbackCallback);
        }
        
        String username = "ant";

        BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
        tm.begin();
        BitronixTransaction tx = tm.getCurrentTransaction();
        
        try{//start of service implementation:
	        Context ctx = new BitronixContext();
	        String msResponse = null;

	        //call microservice #1
	        BasicTransactionAssistanceFactory bookingMicroserviceFactory = (BasicTransactionAssistanceFactory) ctx.lookup("xa/bookingService");

// Path: connector/genericconnector-api/src/main/java/ch/maxant/generic_jca_adapter/BasicTransactionAssistanceFactory.java
// public interface BasicTransactionAssistanceFactory {
// 
//     /**
//      * Get transaction assistant from factory so that a callback can be 
//      * bound into the transaction as well as recovery which is controlled
//      * by the app server's transaction manager.
//      * @exception ResourceException Thrown if an assistant can't be obtained
//      */
//     TransactionAssistant getTransactionAssistant() throws ResourceException;   
//     
// }
// 
// Path: connector/genericconnector-api/src/main/java/ch/maxant/generic_jca_adapter/CommitRollbackCallback.java
// public interface CommitRollbackCallback extends Serializable {
// 
//     /** The container will call this function 
//      * to commit a transaction that was successful.
//      * The implementation of this method should
//      * call the EIS in order to commit
//      * the transaction. */
//     void commit(String txid) throws Exception;
//     
//     /** The container will call this function 
//      * to rollback an unsuccessful transaction.
//      * The implementation of this method should
//      * call the EIS in order to rollback
//      * the transaction. */
//     void rollback(String txid) throws Exception;
// 	
// }
// 
// Path: connector/genericconnector-api/src/main/java/ch/maxant/generic_jca_adapter/TransactionAssistant.java
// public interface TransactionAssistant extends AutoCloseable {
// 
//     /** Submit some work (a function) to be bound into the
//      * currently active transaction. */
//     <O> O executeInActiveTransaction(ExecuteCallback<O> tc) throws Exception;
// 
//     /** Call before completing the transaction in order 
//      * to free up resources used by the app server. */
//     @Override
//     void close();
// }
// 
// Path: connector/genericconnector-atomikos-api/src/main/java/ch/maxant/generic_jca_adapter/TransactionConfigurator.java
// public final class TransactionConfigurator {
// 
// 	private TransactionConfigurator() {}
// 	
// 	private static Map<String, RecoverableMSResource> resources = new HashMap<String, RecoverableMSResource>();
// 	
// 	/** one time configuration required for setting up a microservice in a transactional environment. */
// 	public static void setup(String jndiName, final CommitRollbackCallback commitRollbackCallback){
//     	UserTransactionServiceImp utsi = new UserTransactionServiceImp();
//         MicroserviceXAResource ms = new MicroserviceXAResource(jndiName, commitRollbackCallback);
// 		RecoverableMSResource resource = new RecoverableMSResource(ms);
// 		resources.put(jndiName, resource);
// 		utsi.registerResource(resource);
// 	}
// 
// 	/** when your application shutsdown, you should unregister all services that were setup using {@link #setup(String, CommitRollbackHandler)} 
// 	 * or {@link #setup(String, CommitRollbackHandler, long, File)} */
// 	public static void unregisterMicroserviceResourceFactory(String name) {
//     	UserTransactionServiceImp utsi = new UserTransactionServiceImp();
// 		utsi.removeResource(resources.remove(name));
// 	}
// 	
// 	/** @return the {@link CommitRollbackCallback} registered during setup, or null, if none found (eg never registered, or unregistered). */
// 	static CommitRollbackCallback getCommitRollbackCallback(String jndiName){
// 		RecoverableMSResource rr = resources.get(jndiName);
// 		if(rr != null){
// 			return rr.getMicroserviceResource().getUnderlyingConnection();
// 		}
// 		return null;
// 	}
// 	
// }


// Path: demo/genericconnector-demo-standalone-bitronix/src/main/java/ch/maxant/generic_jca_adapter/demo/Main.java
import ch.maxant.generic_jca_adapter.TransactionAssistant;
import ch.maxant.generic_jca_adapter.TransactionConfigurator;
import ch.maxant.jca_demo.bookingsystem.BookingSystem;
import ch.maxant.jca_demo.bookingsystem.BookingSystemWebServiceService;
import ch.maxant.jca_demo.letterwriter.LetterWebServiceService;
import ch.maxant.jca_demo.letterwriter.LetterWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.naming.Context;
import javax.sql.DataSource;
import bitronix.tm.BitronixTransaction;
import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.jndi.BitronixContext;
import bitronix.tm.resource.ResourceLoader;
import ch.maxant.generic_jca_adapter.BasicTransactionAssistanceFactory;
import ch.maxant.generic_jca_adapter.CommitRollbackCallback;

			private static final long serialVersionUID = 1L;
			@Override
			public void rollback(String txid) throws Exception {
				//compensate by cancelling the letter
				LetterWriter service = new LetterWebServiceService().getLetterWriterPort(); //or take from a pool if you want to
				service.cancelLetter(txid);
			}
			@Override
			public void commit(String txid) throws Exception {
				System.out.println("nothing to do, this service autocommits.");
			}
		};

        {//once per microservice that you want to use - do this when app starts, so that recovery can function immediately
        	TransactionConfigurator.setup("xa/bookingService", bookingCommitRollbackCallback);
        	TransactionConfigurator.setup("xa/letterService", letterCommitRollbackCallback);
        }
        
        String username = "ant";

        BitronixTransactionManager tm = TransactionManagerServices.getTransactionManager();
        tm.begin();
        BitronixTransaction tx = tm.getCurrentTransaction();
        
        try{//start of service implementation:
	        Context ctx = new BitronixContext();
	        String msResponse = null;

	        //call microservice #1
	        BasicTransactionAssistanceFactory bookingMicroserviceFactory = (BasicTransactionAssistanceFactory) ctx.lookup("xa/bookingService");

	        try(TransactionAssistant transactionAssistant = bookingMicroserviceFactory.getTransactionAssistant()){
