Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 30 additions & 17 deletions TXFramework/wsba-participant-completion-simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,36 @@ The following expected output should appear. The output explains what actually w

Test success:

08:02:36,791 INFO [stdout] (http-localhost-127.0.0.1-8080-2) Starting 'testSuccess'. This test invokes a WS within a BA. The BA is later closed, which causes the WS call to complete successfully.
08:02:36,791 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] Creating a new Business Activity
08:02:36,791 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] Beginning Business Activity (All calls to Web services that support WS-BA wil be included in this activity)
08:02:36,809 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] invoking placeOrder('a book') on WS
08:02:37,038 INFO [stdout] (http-localhost-127.0.0.1-8080-4) [SERVICE] invoked placeOrder('a book')
08:02:37,038 INFO [stdout] (http-localhost-127.0.0.1-8080-4) [SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.
08:02:37,161 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] Closing Business Activity (This will cause the BA to complete successfully)
13:20:08,190 INFO [stdout] (http-localhost/127.0.0.1:8080-1) Starting 'testSuccess'. This test invokes a WS within a BA. The BA is later closed, which causes the WS call to complete successfully.
13:20:08,190 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Creating a new Business Activity
13:20:08,190 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Beginning Business Activity (All calls to Web services that support WS-BA wil be included in this activity)
13:20:08,400 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] invoking placeOrder('test@test.com, a book') on WS
13:20:08,582 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] invoked placeOrder('a book')
13:20:08,582 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.
13:20:08,582 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] sent email: 'Order confirmed' to: 'test@test.com'
13:20:08,680 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Closing Business Activity (This will cause the BA to complete successfully)

Test cancel:

08:02:37,517 INFO [stdout] (http-localhost-127.0.0.1-8080-2) Starting 'testCancel'. This test invokes a WS within a BA. The BA is later cancelled, which causes these WS call to be compensated.
08:02:37,517 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] Creating a new Business Activity
08:02:37,517 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] Beginning Business Activity (All calls to Web services that support WS-BA will be included in this activity)
08:02:37,535 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] invoking placeOrder('a book') on WS
08:02:37,789 INFO [stdout] (http-localhost-127.0.0.1-8080-4) [SERVICE] invoked placeOrder('a book')
08:02:37,789 INFO [stdout] (http-localhost-127.0.0.1-8080-4) [SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.
08:02:37,789 INFO [stdout] (http-localhost-127.0.0.1-8080-4) [SERVICE] sent email: 'Your order is now confirmed for the following item: 'a book''
08:02:37,909 INFO [stdout] (http-localhost-127.0.0.1-8080-2) [CLIENT] Cancelling Business Activity (This will cause the work to be compensated)
08:02:38,059 INFO [stdout] (TaskWorker-1) [SERVICE] @Compensate
08:02:38,060 INFO [stdout] (TaskWorker-1) [SERVICE] sent email: 'Unfortunately, we have had to cancel your order for item 'a book''
13:20:09,064 INFO [stdout] (http-localhost/127.0.0.1:8080-1) Starting 'testCancel'. This test invokes a WS within a BA. The BA is later cancelled, which causes these WS call to be compensated.
13:20:09,064 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Creating a new Business Activity
13:20:09,064 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Beginning Business Activity (All calls to Web services that support WS-BA will be included in this activity)
13:20:09,084 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] invoking placeOrder('test@test.com, a book') on WS
13:20:09,159 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] invoked placeOrder('a book')
13:20:09,159 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.
13:20:09,160 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] sent email: 'Order confirmed' to: 'test@test.com'
13:20:09,210 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Cancelling Business Activity (This will cause the work to be compensated)
13:20:09,352 INFO [stdout] (TaskWorker-1) [SERVICE] @Compensate called
13:20:09,352 INFO [stdout] (TaskWorker-1) [SERVICE] sent email: 'Order cancelled' to: 'test@test.com'

Test application exception:

13:20:09,477 INFO [stdout] (http-localhost/127.0.0.1:8080-1) Starting 'testApplicationException'. This test invokes a WS within a BA. The order is made with an invalid email address which causes the placeOrder operation to fail. As a res
ult the service throws an exception and the coordinator is informed that the BA cannot complete.
13:20:09,477 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Creating a new Business Activity
13:20:09,477 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] Beginning Business Activity (All calls to Web services that support WS-BA will be included in this activity)
13:20:09,495 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] invoking placeOrder('test@test, a book') on WS
13:20:09,576 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] invoked placeOrder('a book')
13:20:09,577 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.
13:20:09,577 INFO [stdout] (http-localhost/127.0.0.1:8080-3) [SERVICE] Unable to send email due to an invalid address: 'test@test'. We currently only support '.com' addresses
13:20:09,700 INFO [stdout] (http-localhost/127.0.0.1:8080-1) [CLIENT] 'placeOrder' failed, so canceling the BA
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,36 @@
*/
package org.jboss.narayana.quickstarts.wsba.participantcompletion.simple;

import java.util.ArrayList;
import java.util.List;

/**
* Mock implementation of an email sender. This class simulates the sending of an email by outputting the message to the console.
*
* It also stores the mail in a list so that the tests can assert that the expected mail was 'sent'
*
* @author paul.robinson@redhat.com, 2012-05-02
*/
public class EmailSender {

public static void sendEmail(String message) throws OrderServiceException
{
System.out.println("[SERVICE] sent email: '" + message + "'");
private static volatile List<String> mailBox = new ArrayList<String>();

public static final String MAIL_TEMPLATE_CONFIRMATION = "Order confirmed";
public static final String MAIL_TEMPLATE_CANCELLATION = "Order cancelled";

public static void sendEmail(String emailAddress, String message) throws OrderServiceException {

if (emailAddress.endsWith(".com")) {
mailBox.add(message);
System.out.println("[SERVICE] sent email: '" + message + "' to: '" + emailAddress + "'");
} else {
System.out.println("[SERVICE] Unable to send email due to an invalid address: '" + emailAddress + "'. We currently only support '.com' addresses");
throw new OrderServiceException("Unable to send email due to an invalid address: '" + emailAddress + "'. We currently only support '.com' addresses");
}

}

public static List<String> retrieveMail() {
return mailBox;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import javax.servlet.annotation.WebServlet;

/**
* A simple Web service that accepts product orders and sends confirmation emails. If the BA is cancelled, then a cancellation EMail is sent.
* A simple Web service that accepts product orders and sends confirmation emails. If the BA is compensated, a cancellation email is sent.
*
* @author Paul Robinson (paul.robinson@redhat.com)
*/
Expand All @@ -49,56 +49,50 @@
public class OrderServiceBAImpl implements OrderServiceBA {

/*
The @DataManagement injection provides a map that that is isolated to the transaction participant. This allows the service to store data that
The @TXDataMap injection provides a map that that is isolated to both the transaction and this participant. This allows the service to store data that
can be retrieved when the protocol lifecycle methods are invoked by the coordinator (those annotated with @Compensate, @Cancel, etc).
The Map is isolated within a particular transaction; therefore it is safe for multiple transactions to use this map without seeing each others' data.
The data is automatically removed after the transaction has ended.
*/
@Inject
private TXDataMap<String, String> txDataMap;

/*
* This flag is used by the test to check whether the order was confirmed or cancelled. It is not thread safe as the same instance is used by all threads.
* As this is a simple example and the variable is only used by the (sequentially ran) test, we are not too concerned about this.
*/
private static volatile boolean orderConfirmed = false;

/**
* Places an order for the specified item. As this is a simple example, all the method does is attempt to send the confirmation email.
*
* @param item Item to order
* @throws OrderServiceException if an error occurred when making the order
* The method is annotated with '@Completes' which means that providing the method doesn't throw an Exception, the coordinator will
* be automatically notified that the participant completed.
*
* @param emailAddress The email address of the person making the order.
* @param item Item to be purchased
* @throws OrderServiceException if an error occurred when making the order. In this case if an invalid email address is provided.
*/
@WebMethod
@ServiceRequest // This annotation is used by the TXFramework to know that this method participates in the BA
@Completes
public void placeOrder(String item) throws OrderServiceException {
public void placeOrder(String emailAddress, String item) throws OrderServiceException {

System.out.println("[SERVICE] invoked placeOrder('" + item + "')");

//Store value for use by compensation.
txDataMap.put("value", item);

/*
* this service employs the participant completion protocol which means it has completed the work for this BA.
* If the local changes (emailing the order confirmation to the customer) succeeded, we notify the coordinator that we have
* completed. Otherwise, we notify the coordinator that we cannot complete. If any other participant fails or the client
* decides to cancel we can rely upon being told to compensate.
* Do some work to create the order. For example, create an entry in a database.
*
* This has been left out of this example to keep it simple.
*/
System.out.println("[SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.");
String orderId = "someId"; //Normally generated when creating the order. Maybe the generated PK of the Order record.

EmailSender.sendEmail("Your order is now confirmed for the following item: '" + item + "'");
orderConfirmed = true;
}
/*
* Store data for use by compensation.
*/
txDataMap.put("emailAddress", emailAddress);
txDataMap.put("orderId", orderId);

/**
* The BA has canceled, and the participant should undo any work. The participant cannot have informed the
* coordinator that it has completed.
*/
@Cancel
public void cancel() {

System.out.println("[SERVICE] @Cancel (The participant should compensate any work done within this BA)");
doCompensate();
/* If the following fails (due to an invalid email address, in this example) an exception will be thrown and the middleware will notify the coordinator
* that this participant was unable to complete.
*/
System.out.println("[SERVICE] Attempt to email an order confirmation. Failure would raise an exception causing the coordinator to be informed that this participant cannot complete.");
EmailSender.sendEmail(emailAddress, EmailSender.MAIL_TEMPLATE_CONFIRMATION);
}

/**
Expand All @@ -108,38 +102,15 @@ public void cancel() {
@Compensate
public void compensate() {

System.out.println("[SERVICE] @Compensate");
doCompensate();
}

private void doCompensate() {
System.out.println("[SERVICE] @Compensate called");

String item = txDataMap.get("value");
EmailSender.sendEmail("Unfortunately, we have had to cancel your order for item '" + item + "'");
orderConfirmed = false;
}


/**
* Query to check if the order ws confirmed or cancelled. This is used by the tests.
*
* @return true if the value was present, false otherwise.
*/
@WebMethod
public boolean orderConfirmed() {
//Lookup the item Do something to cancel the order, maybe remove it from the database. This is outside the scope of this quickstart.
String orderId = txDataMap.get("orderId");

return orderConfirmed;
}

/**
* reset the orderConfirmed flag. This is used by the tests.
* <p/>
* Note: To simplify this example, this method is not part of the compensation logic, so will not be undone if the BA is
* compensated. It can also be invoked outside of an active BA.
*/
@WebMethod
public void reset() {

orderConfirmed = false;
/*
* Email the customer to notify them that the order ws cancelled.
*/
String emailAddress = txDataMap.get("emailAddress");
EmailSender.sendEmail(emailAddress, EmailSender.MAIL_TEMPLATE_CANCELLATION);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@
* @author paul.robinson@redhat.com, 2012-01-04
*/
public class OrderServiceException extends RuntimeException {

public OrderServiceException(String message) {
super(message);
}

public OrderServiceException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,11 @@ public interface OrderServiceBA {
/**
* Place an order
*
* @param item Item to order
* @param emailAddress email adress of the purchaser
* @param item Item to purchase
* @throws org.jboss.narayana.quickstarts.wsba.participantcompletion.simple.OrderServiceException if an error occurred when making the order
*/
@WebMethod
public void placeOrder(String item) throws OrderServiceException;

/**
* Check to see if order was confirmed and not canceled.
*
* @return true if the order was confirmed, false if it was not confirmed or if it was later cancelled
*/
@WebMethod
public boolean orderConfirmed();

/**
* Reset the orderConfirmed flag to false.
*/
@WebMethod
public void reset();
public void placeOrder(String emailAddress, String item) throws OrderServiceException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,12 @@ public Client() throws MalformedURLException {

/**
* Place an order
*
*
* @param emailAddress The email address of the person placing the order
* @param item Item to order
* @throws OrderServiceException if an error occurred when making the order
*/
public void placeOrder(String item) throws OrderServiceException {
order.placeOrder(item);
}

/**
* Check to see if order was confirmed and not canceled.
*
* @return true if the order was confirmed, false if it was not confirmed or if it was later cancelled
*/
public boolean orderConfirmed() {
return order.orderConfirmed();
}

/**
* Reset the orderConfirmed flag to false.
*/
public void reset() {
order.reset();
public void placeOrder(String emailAddress, String item) throws OrderServiceException {
order.placeOrder(emailAddress, item);
}
}
Loading