1 /* 2 * JBoss, Home of Professional Open Source 3 * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual 4 * contributors by the @authors tag. See the copyright.txt in the 5 * distribution for a full listing of individual contributors. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.jboss.as.quickstarts.wsba.coordinatorcompletion.simple; 18 19 import com.arjuna.wst.BusinessAgreementWithCoordinatorCompletionParticipant; 20 import com.arjuna.wst.FaultedException; 21 import com.arjuna.wst.SystemException; 22 import com.arjuna.wst.WrongStateException; 23 import com.arjuna.wst11.ConfirmCompletedParticipant; 24 import java.io.Serializable; 25 import java.util.HashMap; 26 import java.util.LinkedList; 27 import java.util.List; 28 29 /** 30 * An adapter class that exposes the SetManager as a WS-BA participant using the 'Coordinator Completion' protocol. 31 * <p/> 32 * The Set Service can be invoked multiple times to add many items to the set within a single BA. The service waits for the 33 * coordinator to tell it to complete. This has the advantage that the client can continue calling methods on the service right 34 * up until it calls 'close'. However, any resources held by the service need to be held for this duration, unless the service 35 * decides to autonomously cancel the BA. 36 * 37 * @author Paul Robinson (paul.robinson@redhat.com) 38 */ 39 public class SetParticipantBA implements BusinessAgreementWithCoordinatorCompletionParticipant, ConfirmCompletedParticipant, 40 Serializable { 41 private static final long serialVersionUID = 1L; 42 // The ID of the corresponding transaction 43 private String txID; 44 // A list of values added to the set. These are removed from the set at 45 // compensation time. 46 private List<String> values = new LinkedList<String>(); 47 // table of currently active participants 48 private static HashMap<String, SetParticipantBA> participants = new HashMap<String, SetParticipantBA>(); 49 50 /** 51 * Participant instances are related to business method calls in a one to one manner. 52 * 53 * @param txID The ID of the current Business Activity 54 * @param value the value to remove from the set during compensation 55 */ 56 public SetParticipantBA(String txID, String value) { 57 this.txID = txID; 58 addValue(value); 59 } 60 61 /** 62 * Notify the participant that another value is being added to the set. This is stored in case compensation is required. 63 * 64 * @param value the value being added to the set 65 */ 66 public void addValue(String value) { 67 values.add(value); 68 } 69 70 /** 71 * The transaction has completed successfully. The participant previously informed the coordinator that it was ready to 72 * complete. 73 * 74 * @throws WrongStateException never in this implementation. 75 * @throws SystemException never in this implementation. 76 */ 77 public void close() throws WrongStateException, SystemException { 78 // nothing to do here as the item has already been added to the set 79 System.out 80 .println("[SERVICE] Participant.close (The participant knows that this BA is now finished and can throw away any temporary state)"); 81 removeParticipant(txID); 82 } 83 84 /** 85 * The transaction has canceled, and the participant should undo any work. The participant cannot have informed the 86 * coordinator that it has completed. 87 * 88 * @throws WrongStateException never in this implementation. 89 * @throws SystemException never in this implementation. 90 */ 91 public void cancel() throws WrongStateException, SystemException { 92 System.out.println("[SERVICE] Participant.cancel (The participant should compensate any work done within this BA)"); 93 doCompensate(); 94 removeParticipant(txID); 95 } 96 97 /** 98 * The transaction has cancelled. The participant previously informed the coordinator that it had finished work but could 99 * compensate later if required, and it is now requested to do so. 100 * 101 * @throws WrongStateException never in this implementation. 102 * @throws SystemException if unable to perform the compensating transaction. 103 */ 104 public void compensate() throws FaultedException, WrongStateException, SystemException { 105 System.out.println("[SERVICE] Participant.compensate"); 106 doCompensate(); 107 removeParticipant(txID); 108 } 109 110 public String status() { 111 return null; 112 } 113 114 public void unknown() throws SystemException { 115 removeParticipant(txID); 116 } 117 118 public void error() throws SystemException { 119 System.out.println("[SERVICE] Participant.error"); 120 doCompensate(); 121 removeParticipant(txID); 122 } 123 124 private void doCompensate() { 125 System.out.println("[SERVICE] SetParticipantBA: Carrying out compensation action"); 126 for (String value : values) { 127 MockSetManager.rollback(value); 128 } 129 } 130 131 @Override 132 public void complete() throws WrongStateException, SystemException { 133 System.out 134 .println("[SERVICE] Participant.complete (This tells the participant that the BA completed, but may be compensated later)"); 135 } 136 137 /** 138 * method called to perform commit or rollback of prepared changes to the underlying manager state after the participant 139 * recovery record has been written 140 * 141 * @param confirmed true if the log record has been written and changes should be rolled forward and false if it has not 142 * been written and changes should be rolled back 143 */ 144 public void confirmCompleted(boolean confirmed) { 145 if (confirmed) { 146 System.out 147 .println("[SERVICE] Participant.confirmCompleted('" 148 + confirmed 149 + "') (This tells the participant that compensation information has been logged and that it is safe to commit any changes.)"); 150 MockSetManager.commit(); 151 } else { 152 doCompensate(); 153 } 154 } 155 156 /************************************************************************/ 157 /* tracking active participants */ 158 /************************************************************************/ 159 /** 160 * keep track of a participant 161 * 162 * @param txID the participant's transaction id 163 * @param participant The participant associated with this BA 164 */ 165 public static synchronized void recordParticipant(String txID, SetParticipantBA participant) { 166 participants.put(txID, participant); 167 } 168 169 /** 170 * forget about a participant 171 * 172 * @param txID the participant's transaction id 173 */ 174 public static void removeParticipant(String txID) { 175 participants.remove(txID); 176 } 177 178 /** 179 * lookup a participant 180 * 181 * @param txID the participant's transaction id 182 * @return the participant 183 */ 184 public static synchronized SetParticipantBA getParticipant(String txID) { 185 return participants.get(txID); 186 } 187 }