Appendix C. Endpoint Implementation Classes
The example below is the demonstration application configuration mentioned in Section 19.3.2.1, “JAX-WS Service Context Handlers”.
Example C.1. Application Configuration (context-handlers.xml
)
<?xml version="1.0" encoding="UTF-8"?> <!-- --> <handler-chains xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee"> <handler-chain> <handler> <handler-name>ContextHandler</handler-name> <handler-class>com.arjuna.mw.wst11.service.JaxWSHeaderContextProcessor</handler-class> </handler> </handler-chain> </handler-chains>
The following four code samples are demonstration implementations of the
javax.jws.WebService
and javax.jws.HandlerChain
annotations which are discussed in Section 19.3.2.1, “JAX-WS Service Context Handlers”.
Example C.2. RestaurantServiceAT.java
package com.jboss.jbosstm.xts.demo.services.restaurant; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.mw.wst11.TransactionManagerFactory; import com.arjuna.mw.wst11.UserTransactionFactory; import com.jboss.jbosstm.xts.demo.restaurant.IRestaurantServiceAT; import com.jboss.jbosstm.xts.demo.services.recovery.DemoATRecoveryModule; import javax.jws.HandlerChain; import javax.jws.WebParam; import javax.jws.WebService; import javax.jws.WebMethod; import javax.jws.soap.SOAPBinding; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryManager; /** * An adapter class that exposes the RestaurantManager business API as a * transactional Web Service. Also logs events to a RestaurantView object. * * @author Jonathan Halliday (jonathan.halliday@arjuna.com) * @version $Revision: 1.3 $ */ @WebService(serviceName="RestaurantServiceATService", portName="RestaurantServiceAT", name = "IRestaurantServiceAT", targetNamespace = "http://www.jboss.com/jbosstm/xts/demo/Restaurant", wsdlLocation = "/WEB-INF/wsdl/RestaurantServiceAT.wsdl") @HandlerChain(file = "../context-handlers.xml", name = "Context Handlers") @SOAPBinding(style=SOAPBinding.Style.RPC) public class RestaurantServiceAT implements IRestaurantServiceAT { /** * ensure that the recovery module for the dmeo is installed */ @PostConstruct void postConstruct() { // ensure that the xts-demo AT recovery helper module is registered DemoATRecoveryModule.register(); } /** * ensure that the recovery module for the dmeo is deinstalled */ @PreDestroy void preDestroy() { // ensure that the xts-demo AT recovery helper module is registered DemoATRecoveryModule.unregister(); } /** * Book a number of seats in the restaurant * Enrols a Participant if necessary, then passes * the call through to the business logic. * * @param how_many The number of seats to book */ @WebMethod public void bookSeats( @WebParam(name = "how_many", partName = "how_many") int how_many) { RestaurantView restaurantView = RestaurantView.getSingletonInstance(); RestaurantManager restaurantManager = RestaurantManager.getSingletonInstance(); String transactionId = null; try { // get the transaction context of this thread: transactionId = UserTransactionFactory.userTransaction().toString(); System.out.println("RestaurantServiceAT transaction id =" + transactionId); if (!restaurantManager.knowsAbout(transactionId)) { System.out.println("RestaurantServiceAT - enrolling..."); // enlist the Participant for this service: RestaurantParticipantAT restaurantParticipant = new RestaurantParticipantAT(transactionId); TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(restaurantParticipant, "org.jboss.jbossts.xts-demo:restaurantAT:" + new Uid().toString()); } } catch (Exception e) { System.err.println("bookSeats: Participant enrolment failed"); e.printStackTrace(System.err); return; } restaurantView.addMessage("******************************"); restaurantView.addMessage("id:" + transactionId + ". Received a booking request for one table of " + how_many + " people"); restaurantManager.bookSeats(transactionId, how_many); restaurantView.addMessage("Request complete\n"); restaurantView.updateFields(); } }
Example C.3. TaxiServiceBA.java
package com.jboss.jbosstm.xts.demo.services.taxi; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.mw.wst11.BusinessActivityManagerFactory; import com.arjuna.mw.wst11.BusinessActivityManager; import com.arjuna.wst11.BAParticipantManager; import com.arjuna.wst.SystemException; import com.jboss.jbosstm.xts.demo.taxi.ITaxiServiceBA; import javax.jws.HandlerChain; import javax.jws.WebMethod; import javax.jws.WebResult; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; /** * An adapter class that exposes the TaxiManager business API as a * transactional Web Service. Also logs events to a TaxiView object. * * @author Jonathan Halliday (jonathan.halliday@arjuna.com) * @version $Revision: 1.5 $ */ @WebService(serviceName="TaxiServiceBAService", portName="TaxiServiceBA", name = "ITaxiServiceBA", targetNamespace = "http://www.jboss.com/jbosstm/xts/demo/Taxi", wsdlLocation = "/WEB-INF/wsdl/TaxiServiceBA.wsdl") @HandlerChain(file = "../context-handlers.xml", name = "Context Handlers") @SOAPBinding(style=SOAPBinding.Style.RPC) public class TaxiServiceBA implements ITaxiServiceBA { /** * Book a taxi * Enrols a Participant if necessary and passes * the call through to the business logic. * * @return true on success, false otherwise. */ @WebMethod @WebResult(name = "bookTaxiBAResponse", partName = "bookTaxiBAResponse") public boolean bookTaxi() { TaxiView taxiView = TaxiView.getSingletonInstance(); TaxiManager taxiManager = TaxiManager.getSingletonInstance(); BusinessActivityManager activityManager = BusinessActivityManagerFactory.businessActivityManager(); // get the transaction context of this thread: String transactionId = null; try { transactionId = activityManager.currentTransaction().toString(); } catch (SystemException e) { System.err.println("bookTaxi: unable to obtain a transaction context!"); e.printStackTrace(System.err); return false; } // log the event: System.out.println("TaxiServiceBA transaction id =" + transactionId); taxiView.addMessage("******************************"); taxiView.addPrepareMessage("id:" + transactionId.toString() + ". Received a taxi booking request"); taxiView.updateFields(); // invoke the backend business logic: taxiManager.bookTaxi(transactionId); // attempt to finalise the booking if (taxiManager.prepareTaxi(transactionId)) { taxiView.addMessage("id:" + transactionId + ". Seats prepared, trying to commit and enlist compensation Participant"); taxiView.updateFields(); // it worked, so now we need a participant enlisted in case of compensation: TaxiParticipantBA taxiParticipant = new TaxiParticipantBA(transactionId); // enlist the Participant for this service: BAParticipantManager participantManager = null; try { participantManager = activityManager.enlistForBusinessAgreementWithParticipantCompletion(taxiParticipant, "org.jboss.jbossts.xts-demo:restaurantBA:" + new Uid().toString()); } catch (Exception e) { taxiView.addMessage("id:" + transactionId + ". Participant enrolement failed"); taxiManager.cancelTaxi(transactionId); System.err.println("bookTaxi: Participant enrolment failed"); e.printStackTrace(System.err); return false; } // finish the booking in the backend ensuring it is compensatable: taxiManager.commitTaxi(transactionId, true); try { // tell the manager we have finished our work: participantManager.completed(); } catch (Exception e) { System.err.println("bookTaxi: 'completed' callback failed"); taxiManager.cancelTaxi(transactionId); e.printStackTrace(System.err); return false; } } else { taxiView.addMessage("id:" + transactionId + ". Failed to reserve taxi. Cancelling."); taxiManager.cancelTaxi(transactionId); taxiView.updateFields(); return false; } taxiView.addMessage("Request complete\n"); taxiView.updateFields(); return true; } }
Example C.4. TaxiServiceAT.java
package com.jboss.jbosstm.xts.demo.services.taxi; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.mw.wst11.TransactionManagerFactory; import com.arjuna.mw.wst11.UserTransactionFactory; import com.jboss.jbosstm.xts.demo.taxi.ITaxiServiceAT; import com.jboss.jbosstm.xts.demo.services.recovery.DemoATRecoveryModule; import javax.jws.WebService; import javax.jws.HandlerChain; import javax.jws.WebMethod; import javax.jws.soap.SOAPBinding; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * An adapter class that exposes the TaxiManager business API as a * transactional Web Service. Also logs events to a TaxiView object. * * @author Jonathan Halliday (jonathan.halliday@arjuna.com) * @version $Revision: 1.3 $ */ @WebService(serviceName="TaxiServiceATService", portName="TaxiServiceAT", name = "ITaxiServiceAT", targetNamespace = "http://www.jboss.com/jbosstm/xts/demo/Taxi", wsdlLocation = "/WEB-INF/wsdl/TaxiServiceAT.wsdl") @HandlerChain(file = "../context-handlers.xml", name = "Context Handlers") @SOAPBinding(style=SOAPBinding.Style.RPC) public class TaxiServiceAT implements ITaxiServiceAT { /** * ensure that the recovery module for the dmeo is installed */ @PostConstruct void postConstruct() { // ensure that the xts-demo AT recovery helper module is registered DemoATRecoveryModule.register(); } /** * ensure that the recovery module for the dmeo is deinstalled */ @PreDestroy void preDestroy() { // ensure that the xts-demo AT recovery helper module is registered DemoATRecoveryModule.unregister(); } /** * Book a taxi * Enrols a Participant if necessary, then passes * the call through to the business logic. */ @WebMethod public void bookTaxi() { TaxiView taxiView = TaxiView.getSingletonInstance(); TaxiManager taxiManager = TaxiManager.getSingletonInstance(); String transactionId = null; try { // get the transaction context of this thread: transactionId = UserTransactionFactory.userTransaction().toString(); System.out.println("TaxiServiceAT transaction id =" + transactionId); if (!taxiManager.knowsAbout(transactionId)) { System.out.println("TaxiServiceAT - enrolling..."); // enlist the Participant for this service: TaxiParticipantAT taxiParticipant = new TaxiParticipantAT(transactionId); TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(taxiParticipant, "org.jboss.jbossts.xts-demo:taxiAT:" + new Uid().toString()); } } catch (Exception e) { System.err.println("bookTaxi: Participant enrolment failed"); e.printStackTrace(System.err); return; } taxiView.addMessage("******************************"); taxiView.addMessage("id:" + transactionId.toString() + ". Received a taxi booking request"); TaxiManager.getSingletonInstance().bookTaxi(transactionId); taxiView.addMessage("Request complete\n"); taxiView.updateFields(); } }
Example C.5. TheatreServiceAT.java
package com.jboss.jbosstm.xts.demo.services.theatre; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.mw.wst11.TransactionManagerFactory; import com.arjuna.mw.wst11.UserTransactionFactory; import com.jboss.jbosstm.xts.demo.theatre.ITheatreServiceAT; import com.jboss.jbosstm.xts.demo.services.recovery.DemoATRecoveryModule; import javax.jws.WebService; import javax.jws.WebParam; import javax.jws.HandlerChain; import javax.jws.WebMethod; import javax.jws.soap.SOAPBinding; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; /** * An adapter class that exposes the TheatreManager business API as a * transactional Web Service. Also logs events to a TheatreView object. * * @author Jonathan Halliday (jonathan.halliday@arjuna.com) * @version $Revision: 1.3 $ */ @WebService(serviceName="TheatreServiceATService", portName="TheatreServiceAT", name = "ITheatreServiceAT", targetNamespace = "http://www.jboss.com/jbosstm/xts/demo/Theatre", wsdlLocation = "/WEB-INF/wsdl/TheatreServiceAT.wsdl") @HandlerChain(file = "../context-handlers.xml", name = "Context Handlers") @SOAPBinding(style=SOAPBinding.Style.RPC) public class TheatreServiceAT implements ITheatreServiceAT { /** * ensure that the recovery module for the dmeo is installed */ @PostConstruct void postConstruct() { // ensure that the xts-demo AT recovery helper module is registered DemoATRecoveryModule.register(); } /** * ensure that the recovery module for the dmeo is deinstalled */ @PreDestroy void preDestroy() { // ensure that the xts-demo AT recovery helper module is registered DemoATRecoveryModule.unregister(); } /** * Book a number of seats in the Theatre * Enrols a Participant if necessary, then passes * the call through to the business logic. * * @param how_many The number of seats to book * @param which_area The area of the theatre to book seats in */ @WebMethod public void bookSeats( @WebParam(name = "how_many", partName = "how_many") int how_many, @WebParam(name = "which_area", partName = "which_area") int which_area) { TheatreView theatreView = TheatreView.getSingletonInstance(); TheatreManager theatreManager = TheatreManager.getSingletonInstance(); String transactionId = null; try { // get the transaction context of this thread: transactionId = UserTransactionFactory.userTransaction().toString(); System.out.println("TheatreServiceAT transaction id =" + transactionId); if (!theatreManager.knowsAbout(transactionId)) { System.out.println("theatreService - enrolling..."); // enlist the Participant for this service: TheatreParticipantAT theatreParticipant = new TheatreParticipantAT(transactionId); TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(theatreParticipant, "org.jboss.jbossts.xts-demo:theatreAT:" + new Uid().toString()); } } catch (Exception e) { System.err.println("bookSeats: Participant enrolment failed"); e.printStackTrace(System.err); return; } theatreView.addMessage("******************************"); theatreView.addMessage("id:" + transactionId.toString() + ". Received a theatre booking request for " + how_many + " seats in area " + which_area); TheatreManager.getSingletonInstance().bookSeats(transactionId, how_many, which_area); theatreView.addMessage("Request complete\n"); theatreView.updateFields(); } }