[jboss-svn-commits] JBL Code SVN: r37229 - in labs/jbosstm/trunk/rest-tx/quickstarts: recovery and 8 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Jul 4 19:21:10 EDT 2011
Author: mmusgrov
Date: 2011-07-04 19:21:10 -0400 (Mon, 04 Jul 2011)
New Revision: 37229
Added:
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/pom.xml
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/readme.txt
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.bat
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.sh
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/JaxrsServer.java
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/ParticipantRecovery.java
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/TransactionAwareResource.java
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/test/
labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/test/java/
Modified:
labs/jbosstm/trunk/rest-tx/quickstarts/pom.xml
labs/jbosstm/trunk/rest-tx/quickstarts/readme.txt
labs/jbosstm/trunk/rest-tx/quickstarts/service/pom.xml
labs/jbosstm/trunk/rest-tx/quickstarts/service/readme.txt
labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/JaxrsServer.java
labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/MultipleParticipants.java
labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/TransactionAwareResource.java
labs/jbosstm/trunk/rest-tx/quickstarts/simple/pom.xml
Log:
[JBTM-856] Recovery Quickstart
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/pom.xml
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/pom.xml 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/pom.xml 2011-07-04 23:21:10 UTC (rev 37229)
@@ -54,5 +54,6 @@
<modules>
<module>simple</module>
<module>service</module>
+ <module>recovery</module>
</modules>
</project>
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/readme.txt
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/readme.txt 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/readme.txt 2011-07-04 23:21:10 UTC (rev 37229)
@@ -14,7 +14,9 @@
OVERVIEW
--------
-All the quickstarts related to rest-tx are found in this folder structure. Each quickstart has a readme.txt to show how to execute the quickstart and what is happening in it. Each quickstart also contains a script to run the quickstart automatically and check the result automatically.
+All the quickstarts related to rest-tx are found in this folder structure. Each quickstart has
+a readme.txt to show how to execute the quickstart and what is happening in it. Each quickstart
+also contains a script to run the quickstart automatically and check the result automatically.
USAGE
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/pom.xml
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/pom.xml (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/pom.xml 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>quickstarts</artifactId>
+ <groupId>org.jboss.narayana.rts.quickstarts</groupId>
+ <version>5.0.0.M1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>recovery</artifactId>
+ <name>RESTful Atomic Transaction Quickstart: Participant Service with Recovery</name>
+ <description>Example of how a web service can recover from failures during transaction completion</description>
+
+ <repositories>
+ <!-- Jersey -->
+ <repository>
+ <id>maven2-repository.dev.java.net</id>
+ <name>Java.net Repository for Maven</name>
+ <url>http://download.java.net/maven/2/</url>
+ <layout>default</layout>
+ </repository>
+ <!-- end Jersey -->
+ </repositories>
+
+ <dependencies>
+
+ <!-- the implementation of REST Atomic Transactions -->
+ <dependency>
+ <groupId>org.jboss.narayana.rts</groupId>
+ <artifactId>rest-tx-api</artifactId>
+ <version>5.0.0.M1-SNAPSHOT</version>
+ </dependency>
+
+ <!-- Jersey container for running participant services -->
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-server</artifactId>
+ <version>1.5-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.5-SNAPSHOT</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>com.sun.grizzly</groupId>
+ <artifactId>grizzly-servlet-webserver</artifactId>
+ <version>1.9.18-i</version>
+ </dependency>
+ <!-- end Jersey -->
+ </dependencies>
+
+</project>
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/readme.txt
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/readme.txt (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/readme.txt 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,100 @@
+OVERVIEW
+--------
+This example builds on the service quickstart by showing how you can make your web services transactional
+and still recover when the VM hosting the service crashes whilst the transaction is being committed.
+
+
+USAGE
+-----
+Deploy the rest-tx war (rest-tx-web-5.0.0.M1-SNAPSHOT.war) into a running AS7 (or AS6) application server listening
+for http requests on localhost (if you use a different host/port change the url in MultipleParticipants.TXN_MGR_URK).
+
+To test recovery you will need to run the example twice, once to generate a failure condition:
+
+ mvn compile exec:java -Dexec.mainClass=quickstart.ParticipantRecovery -Dexec.args="-f"
+
+and a second time in order to test that the web service is asked to replay the commit phase:
+
+ mvn exec:java -Dexec.mainClass=quickstart.ParticipantRecovery -Dexec.args="-r"
+
+Use the run.sh or run.bat script to run both parts together.
+
+If you just want the same behaviour as the service example - ie without failures then run the example without
+any arguments:
+
+ mvn exec:java -Dexec.mainClass=quickstart.ParticipantRecovery
+
+
+EXPECTED OUTPUT
+---------------
+
+On the first run when generating a failure you should see two messages from the webservice enlisting
+two sets of urls into the transaction:
+
+ Service: Enlisting terminator=http://localhost:58082/service/1/1/terminate;durableparticipant=http://localhost:58082/service/1/1/terminator
+ Service: Enlisting terminator=http://localhost:58082/service/1/2/terminate;durableparticipant=http://localhost:58082/service/1/2/terminator
+
+Followed by the client announcing that it is going to ask the second participant to halt the VM during commit
+(and after prepare):
+
+ Client: Failing work load 2
+ Client: Committing transaction
+
+You will then see 5 messages from the participants showing requests from the transaction coordinator
+asking participants to prepare and commit their work. The final message is from the second participant
+saying that it is going to halt the VM:
+
+ Service: PUT request to terminate url: wId=2, status:=txStatus=TransactionPrepared
+ Service: PUT request to terminate url: wId=1, status:=txStatus=TransactionPrepared
+ Service: PUT request to terminate url: wId=1, status:=txStatus=TransactionCommitted
+ Service: PUT request to terminate url: wId=2, status:=txStatus=TransactionCommitted
+ Service: Halting VM during commit of work unit wId=2
+
+On the second run when recovering after generating the failure you should see the following messages:
+
+ Client: waiting for recovery in 2 second intervals (for a max of 130 secs)
+ Service: PUT request to terminate url: wId=2, status:=txStatus=TransactionCommitted
+ SUCCESS participant was recovered after 22 seconds. Number of commits: 1
+
+The first message states that the example is waiting for the recovery system (running in the AS
+you deployed the war to) to perform a recovery scan. The default interval between recovery scans is 120 seconds.
+
+The second output line shows that the web service received a prepare request and hence recovery ran
+successfully. And the final output line indicates a successful run.
+
+
+WHAT JUST HAPPENED?
+-------------------
+1. We deployed a JAX-RS servlet that implements a RESTful interface to the Narayana transaction manager (TM)
+(running in an AS7 or AS6 container).
+
+2. The client (MultipleParticpants.java) started an embedded web server (JaxrsServer.java) for hosting web services.
+
+3 The client then started a REST Atomic Transaction and got back two urls: one for completing the transaction
+and one for use with enlisting durable participants (implemented by the class TransactionAwareResource.java)
+into the transaction.
+
+4. The client then made two HTTP requests to a web service and passed the participant enlistment url as part
+of the context of the request (using a query parameter).
+
+5. The participants used the enlistment url to join the transaction. In this naive example we assumes that
+each request is for a separate unit of transactional work and in this way we end up with multiple participants
+being involved in the transaction. Having more than one participant means we can demonstrate that either all
+participants will commit or none them will.
+
+6. The client sets a static variable on the second participant to force it to halt the VM just before
+it commits its work. This will only work with an embedded web server running in the same VM as the client.
+If you wanted to change the example so that the service runs in a separate VM then you might instead send the
+the service a request telling it to halt during prepare.
+
+7. The client commits the transaction using the resource url it got back when it created the transaction.
+
+8. The transaction manager implementation knows that there are two resources involved and asks them both to
+prepare their work (using the resource urls it got from the participants when they enlisted into the transaction).
+If the participant resources respond with the correct HTTP status code and body then the transaction manager
+proceeds to request commitment.
+
+9. On the first run the second participant halts the VM leaving a recovery record in the AS in need of recover.
+
+10 On the second run the example waits for the service to indicate when the recovery system has called commit
+in order to complete the transaction.
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.bat
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.bat (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.bat 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,10 @@
+ at echo off
+
+echo "Running recovery quickstart"
+
+mvn compile exec:java -Dexec.mainClass=quickstart.ParticipantRecovery -Dexec.args="-f"
+IF %ERRORLEVEL% NEQ 0 exit -1
+echo "Recovering failed service - this could take up to 2 minutes"
+mvn compile exec:java -Dexec.mainClass=quickstart.ParticipantRecovery -Dexec.args="-r"
+IF %ERRORLEVEL% NEQ 0 exit -1
+echo "Service recovery example succeeded"
Property changes on: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.bat
___________________________________________________________________
Added: svn:executable
+ *
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.sh
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.sh (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.sh 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,19 @@
+# ALLOW JOBS TO BE BACKGROUNDED
+set -m
+
+echo "Running recovery quickstart"
+
+mvn compile exec:java -Dexec.mainClass=quickstart.ParticipantRecovery -Dexec.args="-f"
+# We expect this to fail
+#if [ "$?" != "0" ]; then
+# exit -1
+#fi
+echo "Recovering failed service - this could take up to 2 minutes"
+mvn compile exec:java -Dexec.mainClass=quickstart.ParticipantRecovery -Dexec.args="-r"
+if [ "$?" != "0" ]; then
+ echo "Service recovery example FAILED"
+ exit -1
+else
+ echo "Service recovery example SUCCEEDED"
+fi
+
Property changes on: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/run.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/JaxrsServer.java
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/JaxrsServer.java (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/JaxrsServer.java 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,57 @@
+package quickstart;
+
+import com.sun.grizzly.http.SelectorThread;
+import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;
+
+import javax.ws.rs.core.UriBuilder;
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Start a simple embedded web server for hosting web services that will participate in
+ * REST Atomic transactions.
+ *
+ * We use Grizzly since it is the reference implementation and it supports JAX-RS.
+ * Using JAX-RS make our web service example is trivial to implement.
+ */
+public class JaxrsServer {
+ private static SelectorThread threadSelector = null;
+
+/* public static void startTJWS(String host, int port) {
+ org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer server;
+ server = new org.jboss.resteasy.plugins.server.tjws.TJWSEmbeddedJaxrsServer();
+ server.setPort(port);
+ server.start();
+
+ org.jboss.resteasy.spi.Registry registry = server.getDeployment().getRegistry();
+
+ registry.addPerRequestResource(TransactionAwareResource.class);
+ }*/
+
+ public static void startGrizzly(String host, int port) {
+ final URI baseUri= UriBuilder.fromUri("http://" + host + ':' + port + '/').build();
+ final Map<String, String> initParams = new HashMap<String, String>();
+ String packages = TransactionAwareResource.class.getPackage().getName();
+
+ initParams.put("com.sun.jersey.config.property.packages", packages);
+
+ try {
+ threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);
+ } catch (IOException e) {
+ throw new RuntimeException("Error starting JAX-RS container: " + e.getMessage(), e);
+ }
+ }
+
+ public static void startServer(String host, int port) {
+ startGrizzly(host, port);
+ }
+
+ public static void stopServer() {
+ if (threadSelector != null)
+ threadSelector.stopEndpoint();
+
+ threadSelector = null;
+ }
+}
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/ParticipantRecovery.java
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/ParticipantRecovery.java (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/ParticipantRecovery.java 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,74 @@
+package quickstart;
+
+import org.jboss.jbossts.star.util.TxSupport;
+import java.net.HttpURLConnection;
+
+public class ParticipantRecovery {
+ private static final int host = 0;
+ private static final String[] hosts = {"localhost:8080", "184.72.71.236", "jbossapp1-mmusgrov1.dev.rhcloud.com"};
+ private static final String TXN_MGR_URL = "http://" + hosts[host] + "/rest-tx/tx/transaction-manager";
+
+ private static final int SERVICE_PORT = 58082;
+ private static final String SERVICE_URL = "http://localhost:" + SERVICE_PORT + '/' + TransactionAwareResource.PSEGMENT;
+
+ public static void main(String[] args) {
+ String opt = (args.length == 0 ? "" : args[0]);
+
+ // the example uses an embedded JAX-RS server for running the service that will take part in a transaction
+ JaxrsServer.startServer("localhost", SERVICE_PORT);
+
+ // get a helper for using RESTful transactions, passing in the well know resource endpoint for the transaction manager
+ TxSupport txn = new TxSupport(TXN_MGR_URL);
+
+ if ("-r".equals(opt)) {
+ System.out.println("Client: waiting for recovery in 2 second intervals (for a max of 130 secs)");
+
+ for (long i = 0l; i < 130l; i += 2) {
+ try {
+ // ask the service how many transactions it has committed since the VM started
+
+ String cnt = txn.httpRequest(new int[] {HttpURLConnection.HTTP_OK}, SERVICE_URL + "/query", "GET", TxSupport.PLAIN_MEDIA_TYPE, null, null);
+
+ if (cnt != null && !"0".equals(cnt)) {
+ System.out.println("SUCCESS participant was recovered after " + i + " seconds. Number of commits: " + cnt);
+ System.exit(0);
+ }
+
+ Thread.sleep(i * 1000);
+
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ System.out.println("FAILURE participant was not recovered");
+ System.exit(1);
+ }
+
+ // start a REST Atomic transaction
+ txn.startTx();
+
+ /*
+ * Send two web service requests. Include the resource url for registering durable participation
+ * in the transaction with the request
+ */
+ String serviceRequest = SERVICE_URL + "?enlistURL=" + txn.enlistUrl();
+
+ String wId1 = txn.httpRequest(new int[] {HttpURLConnection.HTTP_OK}, serviceRequest, "GET", TxSupport.PLAIN_MEDIA_TYPE, null, null);
+ String wId2 = txn.httpRequest(new int[] {HttpURLConnection.HTTP_OK}, serviceRequest, "GET", TxSupport.PLAIN_MEDIA_TYPE, null, null);
+
+ // commit the transaction
+ if ("-f".equals(opt)) {
+ System.out.println("Client: Failing work load " + wId2);
+ TransactionAwareResource.FAIL_COMMIT = wId2;
+ }
+
+ System.out.println("Client: Committing transaction");
+ txn.commitTx();
+
+ // the web service should have received prepare and commit requests from the transaction manager (TXN_MGR_URL)
+
+ // shutdown the embedded JAX-RS server
+ JaxrsServer.stopServer();
+ }
+}
Added: labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/TransactionAwareResource.java
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/TransactionAwareResource.java (rev 0)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/recovery/src/main/java/quickstart/TransactionAwareResource.java 2011-07-04 23:21:10 UTC (rev 37229)
@@ -0,0 +1,82 @@
+package quickstart;
+
+import org.jboss.jbossts.star.util.TxSupport;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.net.HttpURLConnection;
+
+/**
+ * An example of how a REST resource can act as a participant in a REST Atomic transaction.
+ * For a complete implementation of a participant please refer to the test suite, in particular the inner class:
+ * org.jboss.jbossts.star.test.BaseTest$TransactionalResource which implements all the responsibilities of a participant
+ *
+ * The example sends a service request which is handled by the method someServiceRequest. The request includes the
+ * URL for registering durable participants within the transaction. This naive implementation assumes every request
+ * with a valid enlistment URL is a request a new unit of transactional work and enlists a new URL into the transaction.
+ * Thus if a client makes two http requests to the method someServiceRequest then the participant is enlisted twice
+ * into the transaction but with different completion URLs. This facilitates the demonstration of 2 phase commit
+ * processing.
+ */
+ at Path(TransactionAwareResource.PSEGMENT)
+public class TransactionAwareResource {
+ public static final String PSEGMENT = "service";
+ public static String FAIL_COMMIT;
+ private static int workId = 1;
+ private static int commitCnt = 0;
+
+ @GET
+ public Response someServiceRequest(@Context UriInfo info, @QueryParam("enlistURL") @DefaultValue("")String enlistUrl) {
+ if (enlistUrl == null || enlistUrl.length() == 0)
+ return Response.ok("non transactional request").build();
+
+ String serviceURL = info.getBaseUri() + info.getPath();
+ String workURL = serviceURL + "/1/" + workId;
+
+ String terminator = workURL + "/terminate";
+ String participant = workURL + "/terminator";
+
+ String pUrls = TxSupport.getParticipantUrls(terminator, participant);
+ System.out.println("Service: Enlisting " + pUrls);
+
+ new TxSupport().httpRequest(new int[] {HttpURLConnection.HTTP_CREATED}, enlistUrl,
+ "POST", TxSupport.POST_MEDIA_TYPE, pUrls, null);
+
+ return Response.ok(Integer.toString(workId++)).build();
+ }
+
+ @GET
+ @Path("query")
+ public Response someServiceRequest() {
+ return Response.ok(Integer.toString(commitCnt)).build();
+ }
+
+ /*
+ * this method handles PUT requests to the url that the participant gave to the REST Atomic Transactions implementation
+ * (in the someServiceRequest method). This is the endpoint that the transaction manager interacts with when it needs
+ * participants to prepare/commit/rollback their transactional work.
+ */
+ @PUT
+ @Path("{pId}/{wId}/terminate")
+ public Response terminate(@PathParam("pId") @DefaultValue("")String pId, @PathParam("wId") @DefaultValue("")String wId, String content) {
+ System.out.println("Service: PUT request to terminate url: wId=" + wId + ", status:=" + content);
+ String status = TxSupport.getStatus(content);
+
+ if (TxSupport.isPrepare(status)) {
+ return Response.ok(TxSupport.toStatusContent(TxSupport.PREPARED)).build();
+ } else if (TxSupport.isCommit(status)) {
+ if (wId.equals(FAIL_COMMIT)) {
+ System.out.println("Service: Halting VM during commit of work unit wId=" + wId);
+ Runtime.getRuntime().halt(1);
+ }
+ commitCnt += 1;
+ return Response.ok(TxSupport.toStatusContent(TxSupport.COMMITTED)).build();
+ } else if (TxSupport.isAbort(status)) {
+ return Response.ok(TxSupport.toStatusContent(TxSupport.ABORTED)).build();
+ } else {
+ return Response.status(HttpURLConnection.HTTP_BAD_REQUEST).build();
+ }
+ }
+}
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/service/pom.xml
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/service/pom.xml 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/service/pom.xml 2011-07-04 23:21:10 UTC (rev 37229)
@@ -10,7 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>service</artifactId>
- <name>quickstart Participant Service</name>
+ <name>RESTful Atomic Transaction Quickstart: Participant Service</name>
<description>Examples show how a web service can participate in a transaction</description>
<repositories>
@@ -50,6 +50,7 @@
</build>
<dependencies>
+
<!-- the implementation of REST Atomic Transactions -->
<dependency>
<groupId>org.jboss.narayana.rts</groupId>
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/service/readme.txt
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/service/readme.txt 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/service/readme.txt 2011-07-04 23:21:10 UTC (rev 37229)
@@ -1,23 +1,22 @@
OVERVIEW
--------
-This example shows how you can make your web services transactional. [The example uses Jersey and Grizzly
-for deploying the participant web services but any conforming web container will do].
+This example shows how you can make your web services transactional. [It uses Jersey and Grizzly
+for deploying the participant web services, but any conforming web container will do].
USAGE
-----
-Deploy the rest-tx war (rest-tx-web-5.0.0.M1-SNAPSHOT.war) into a running AS7 (or AS6) application server listening
-for http requests on localhost (if you use a different host/port change the url in MultipleParticipants.TXN_MGR_URK).
+Deploy the rest-tx war (rest-tx-web-5.0.0.M1-SNAPSHOT.war) into a running AS7 (or AS6) application server
+that is listening for http requests on localhost (if you use a different host/port change the url in
+MultipleParticipants.TXN_MGR_URL).
mvn compile exec:exec
+or use the run.sh or run.bat script.
+
EXPECTED OUTPUT
---------------
-1. You will see 2 lines of output showing the service enlisting into the transaction.
-2. A message showing the client committing transaction.
-3. Two resouces will output two messages during the transaction committment protocol. One
-saying that it has prepared and the other reporting that it has committed.
4. And finally the build will report success or failure:
[INFO] BUILD SUCCESS
@@ -25,6 +24,26 @@
indicates a successful outcome.
+1. You will see 2 lines of output showing the service enlisting into the transaction:
+ Service: Enlisting terminator=http://localhost:58082/service/1/1/terminate;durableparticipant=http://localhost:58082/service/1/1/terminator
+ Service: Enlisting terminator=http://localhost:58082/service/1/2/terminate;durableparticipant=http://localhost:58082/service/1/2/terminator
+
+2. A message showing the client committing transaction:
+
+ Client: Committing transaction
+
+3. Two resources will output two messages during the transaction commitment protocol. One
+saying that it has prepared and the other reporting that it has committed.
+
+ Service: PUT request to terminate url: wId=2, status:=txStatus=TransactionPrepared
+ Service: PUT request to terminate url: wId=1, status:=txStatus=TransactionPrepared
+ Service: PUT request to terminate url: wId=1, status:=txStatus=TransactionCommitted
+ Service: PUT request to terminate url: wId=2, status:=txStatus=TransactionCommitted
+
+4. The client checks that the service got both commit requests:
+
+ SUCCESS: Both service work loads received commit requests
+
WHAT JUST HAPPENED?
-------------------
1. We deployed a JAX-RS servlet that implements a RESTful interface to the Narayana transaction manager (TM)
@@ -41,12 +60,15 @@
5. The participants used the enlistment url to join the transaction. In this naive example we assumes that
each request is for a separate unit of transactional work and in this way we end up with multiple participants
-beining involved in the transaction. Having more than one participant means we can demonstrate that either all
+being involved in the transaction. Having more than one participant means we can demonstrate that either all
participants will commit or none them will.
6. The client commits the transaction using the resource url it got back when it created the transaction.
7. The transaction manager implementation knows that there are two resources involved and asks them both to
prepare their work (using the resource urls it got from the participants when they enlisted into the transaction).
-If the particpant resources respond with the correct HTTP status code and body then the transaction manager
-proceeds to request committment. Refer to the REST Atomic Transactions spec for full details.
+If the participant resources respond with the correct HTTP status code and body then the transaction manager
+proceeds to request commitment. Refer to the REST Atomic Transactions spec for full details.
+
+8. The client sends a request to the service asking how many times it was asked to commit work units.
+If it was twice then SUCCESS is printed otherwise FAILURE is printed.
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/JaxrsServer.java
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/JaxrsServer.java 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/JaxrsServer.java 2011-07-04 23:21:10 UTC (rev 37229)
@@ -34,12 +34,13 @@
final URI baseUri= UriBuilder.fromUri("http://" + host + ':' + port + '/').build();
final Map<String, String> initParams = new HashMap<String, String>();
String packages = TransactionAwareResource.class.getPackage().getName();
+
initParams.put("com.sun.jersey.config.property.packages", packages);
try {
threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);
} catch (IOException e) {
- e.printStackTrace();
+ throw new RuntimeException("Error starting JAX-RS container: " + e.getMessage(), e);
}
}
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/MultipleParticipants.java
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/MultipleParticipants.java 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/MultipleParticipants.java 2011-07-04 23:21:10 UTC (rev 37229)
@@ -4,10 +4,12 @@
import java.net.HttpURLConnection;
public class MultipleParticipants {
+ // construct the well known http endpoint for the REST Atomic Transactions coordinator
private static final int host = 0;
private static final String[] hosts = {"localhost:8080", "184.72.71.236", "jbossapp1-mmusgrov1.dev.rhcloud.com"};
private static final String TXN_MGR_URL = "http://" + hosts[host] + "/rest-tx/tx/transaction-manager";
+ // construct the endpoint for the example web service that will take part in a transaction
private static final int SERVICE_PORT = 58082;
private static final String SERVICE_URL = "http://localhost:" + SERVICE_PORT + '/' + TransactionAwareResource.PSEGMENT;
@@ -15,27 +17,39 @@
// the example uses an embedded JAX-RS server for running the service that will take part in a transaction
JaxrsServer.startServer("localhost", SERVICE_PORT);
- // get a helper for using RESTful transactions passing in the resource endpoint for the transaction manager
+ // get a helper for using REST Atomic Transactions, passing in the well know resource endpoint for the transaction coordinator
TxSupport txn = new TxSupport(TXN_MGR_URL);
- // start a RESTful transaction
+ // start a REST Atomic transaction
txn.startTx();
/*
* Send two web service requests. Include the resource url for registering durable participation
- * in the transaction with the request
+ * in the transaction with the request (namely txn.enlistUrl())
+ *
+ * Each request should cause the service to enlist a unit of work within the transaction.
*/
String serviceRequest = SERVICE_URL + "?enlistURL=" + txn.enlistUrl();
txn.httpRequest(new int[] {HttpURLConnection.HTTP_OK}, serviceRequest, "GET", TxSupport.PLAIN_MEDIA_TYPE, null, null);
txn.httpRequest(new int[] {HttpURLConnection.HTTP_OK}, serviceRequest, "GET", TxSupport.PLAIN_MEDIA_TYPE, null, null);
- // commit the transaction
- System.out.println("committing transaction");
+ /*
+ * Commit the transaction (we expect the service to receive a prepare followed by a commit request for each work unit it enlists)
+ * Note that if there was only one work unit then the implementation would skip the prepare step.
+ */
+ System.out.println("Client: Committing transaction");
txn.commitTx();
- // the web service should have received prepare and commit requests from the transaction manager (TXN_MGR_URL)
+ // the web service should have received prepare and commit requests from the transaction coordinator (TXN_MGR_URL) for each work unit
+ String cnt = txn.httpRequest(new int[] {HttpURLConnection.HTTP_OK}, SERVICE_URL + "/query", "GET", TxSupport.PLAIN_MEDIA_TYPE, null, null);
+ // check that the service has been asked to commit twice
+ if ("2".equals(cnt))
+ System.out.println("SUCCESS: Both service work loads received commit requests");
+ else
+ System.out.println("FAILURE: At leas one server work load did not receive a commit request: " + cnt);
+
// shutdown the embedded JAX-RS server
JaxrsServer.stopServer();
}
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/TransactionAwareResource.java
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/TransactionAwareResource.java 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/service/src/main/java/quickstart/TransactionAwareResource.java 2011-07-04 23:21:10 UTC (rev 37229)
@@ -9,39 +9,50 @@
import java.net.HttpURLConnection;
/**
- * An example of how a REST resource can act as a participant in a RESTful transaction.
+ * An example of how a REST resource can act as a participant in a REST Atomic transaction.
* For a complete implementation of a participant please refer to the test suite, in particular the inner class:
- * org.jboss.jbossts.star.test.BaseTest$TransactionalResource implements all the responsibilities of a participant
+ * org.jboss.jbossts.star.test.BaseTest$TransactionalResource which implements all the responsibilities of a participant
*
* The example sends a service request which is handled by the method someServiceRequest. The request includes the
* URL for registering durable participants within the transaction. This naive implementation assumes every request
* with a valid enlistment URL is a request a new unit of transactional work and enlists a new URL into the transaction.
* Thus if a client makes two http requests to the method someServiceRequest then the participant is enlisted twice
- * into the transaction but with different completion URLs.
+ * into the transaction but with different completion URLs. This facilitates the demonstration of 2 phase commit
+ * processing.
*/
- at Path("service")
+ at Path(TransactionAwareResource.PSEGMENT)
public class TransactionAwareResource {
public static final String PSEGMENT = "service";
- private static int workId = 0;
+ public static String FAIL_COMMIT;
+ private static int workId = 1;
+ private static int commitCnt = 0;
@GET
- public String someServiceRequest(@Context UriInfo info, @QueryParam("enlistURL") @DefaultValue("")String enlistUrl) {
+ public Response someServiceRequest(@Context UriInfo info, @QueryParam("enlistURL") @DefaultValue("")String enlistUrl) {
if (enlistUrl == null || enlistUrl.length() == 0)
- return ("non transactional request");
+ return Response.ok("non transactional request").build();
String serviceURL = info.getBaseUri() + info.getPath();
- String workURL = serviceURL + "/1/" + ++workId;
+ String workURL = serviceURL + "/1/" + workId;
String terminator = workURL + "/terminate";
String participant = workURL + "/terminator";
String pUrls = TxSupport.getParticipantUrls(terminator, participant);
- System.out.println("enlisting " + pUrls);
+ System.out.println("Service: Enlisting " + pUrls);
- return new TxSupport().httpRequest(new int[] {HttpURLConnection.HTTP_CREATED}, enlistUrl,
+ new TxSupport().httpRequest(new int[] {HttpURLConnection.HTTP_CREATED}, enlistUrl,
"POST", TxSupport.POST_MEDIA_TYPE, pUrls, null);
+
+ return Response.ok(Integer.toString(workId++)).build();
}
+ @GET
+ @Path("query")
+ public Response someServiceRequest() {
+ return Response.ok(Integer.toString(commitCnt)).build();
+ }
+
/*
* this method handles PUT requests to the url that the participant gave to the REST Atomic Transactions implementation
* (in the someServiceRequest method). This is the endpoint that the transaction manager interacts with when it needs
@@ -50,12 +61,17 @@
@PUT
@Path("{pId}/{wId}/terminate")
public Response terminate(@PathParam("pId") @DefaultValue("")String pId, @PathParam("wId") @DefaultValue("")String wId, String content) {
- System.out.println("participant terminate resource: PUT request: wId=" + wId + ", status:=" + content);
+ System.out.println("Service: PUT request to terminate url: wId=" + wId + ", status:=" + content);
String status = TxSupport.getStatus(content);
if (TxSupport.isPrepare(status)) {
return Response.ok(TxSupport.toStatusContent(TxSupport.PREPARED)).build();
} else if (TxSupport.isCommit(status)) {
+ if (wId.equals(FAIL_COMMIT)) {
+ System.out.println("Service: Halting VM during commit of work unit wId=" + wId);
+ Runtime.getRuntime().halt(1);
+ }
+ commitCnt += 1;
return Response.ok(TxSupport.toStatusContent(TxSupport.COMMITTED)).build();
} else if (TxSupport.isAbort(status)) {
return Response.ok(TxSupport.toStatusContent(TxSupport.ABORTED)).build();
Modified: labs/jbosstm/trunk/rest-tx/quickstarts/simple/pom.xml
===================================================================
--- labs/jbosstm/trunk/rest-tx/quickstarts/simple/pom.xml 2011-07-04 19:01:30 UTC (rev 37228)
+++ labs/jbosstm/trunk/rest-tx/quickstarts/simple/pom.xml 2011-07-04 23:21:10 UTC (rev 37229)
@@ -25,7 +25,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>simple</artifactId>
<version>5.0.0.M1-SNAPSHOT</version>
- <name>RESTful Atomic Transaction Quickstarts</name>
+ <name>RESTful Atomic Transaction Quickstart: Basic</name>
<description>Basic example of how to start and stop a REST Atomic transaction</description>
<build>
More information about the jboss-svn-commits
mailing list