1 25 package org.ofbiz.service; 26 27 import java.util.Map ; 28 import javax.transaction.Status ; 29 import javax.transaction.Transaction ; 30 import javax.transaction.xa.XAException ; 31 import javax.transaction.xa.Xid ; 32 33 import org.ofbiz.base.util.Debug; 34 import org.ofbiz.base.util.UtilValidate; 35 import org.ofbiz.entity.transaction.GenericTransactionException; 36 import org.ofbiz.entity.transaction.GenericXaResource; 37 import org.ofbiz.entity.transaction.TransactionUtil; 38 39 46 public class ServiceXaWrapper extends GenericXaResource { 47 48 public static final String module = ServiceXaWrapper.class.getName(); 49 public static final int TYPE_ROLLBACK = 600; 50 public static final int TYPE_COMMIT = 500; 51 public static final int MODE_ASYNC = 100; 52 public static final int MODE_SYNC = 200; 53 54 protected DispatchContext dctx = null; 55 protected String rollbackService = null; 56 protected String commitService = null; 57 protected String runAsUser = null; 58 protected Map rollbackContext = null; 59 protected Map commitContext = null; 60 protected boolean rollbackAsync = true; 61 protected boolean rollbackAsyncPersist = true; 62 protected boolean commitAsync = false; 63 protected boolean commitAsyncPersist = false; 64 65 protected ServiceXaWrapper() {} 66 public ServiceXaWrapper(DispatchContext dctx) { 67 this.dctx = dctx; 68 } 69 70 75 public void setCommitService(String serviceName, Map context) { 76 this.setCommitService(serviceName, null, context, commitAsync, commitAsyncPersist); 77 } 78 79 85 public void setCommitService(String serviceName, Map context, boolean async, boolean persist) { 86 this.setCommitService(serviceName, null, context, async, persist); 87 } 88 89 96 public void setCommitService(String serviceName, String runAsUser, Map context, boolean async, boolean persist) { 97 this.commitService = serviceName; 98 this.runAsUser = runAsUser; 99 this.commitContext = context; 100 this.commitAsync = async; 101 this.commitAsyncPersist = persist; 102 } 103 104 105 108 public String getCommitService() { 109 return this.commitService; 110 } 111 112 115 public Map getCommitContext() { 116 return this.commitContext; 117 } 118 119 124 public void setRollbackService(String serviceName, Map context) { 125 this.setRollbackService(serviceName, context, rollbackAsync, rollbackAsyncPersist); 126 } 127 128 134 public void setRollbackService(String serviceName, Map context, boolean async, boolean persist) { 135 this.rollbackService = serviceName; 136 this.rollbackContext = context; 137 this.rollbackAsync = async; 138 this.rollbackAsyncPersist = persist; 139 } 140 141 144 public String getRollbackService() { 145 return this.rollbackService; 146 } 147 148 151 public Map getRollbackContext() { 152 return this.rollbackContext; 153 } 154 155 public void enlist() throws XAException { 156 super.enlist(); 157 Debug.log("Enlisted in transaction : " + this.toString(), module); 158 } 159 160 164 public void commit(Xid xid, boolean onePhase) throws XAException { 165 Debug.log("ServiceXaWrapper#commit() : " + onePhase + " / " + xid.toString(), module); 166 if (this.active) { 168 Debug.logWarning("commit() called without end()", module); 169 } 170 if (this.xid == null || !this.xid.equals(xid)) { 171 throw new XAException (XAException.XAER_NOTA); 172 } 173 174 final String service = commitService; 175 final Map context = commitContext; 176 final boolean persist = commitAsyncPersist; 177 final boolean async = commitAsync; 178 179 Thread thread = new Thread () { 180 public void run() { 181 try { 182 runService(service, context, persist, (async ? MODE_ASYNC : MODE_SYNC), TYPE_COMMIT); 183 } catch (XAException e) { 184 Debug.logError(e, module); 185 } 186 } 187 }; 188 thread.start(); 189 190 this.xid = null; 191 this.active = false; 192 } 193 194 197 public void rollback(Xid xid) throws XAException { 198 Debug.log("ServiceXaWrapper#rollback() : " + xid.toString(), module); 199 if (this.active) { 201 Debug.logWarning("rollback() called without end()", module); 202 } 203 if (this.xid == null || !this.xid.equals(xid)) { 204 throw new XAException (XAException.XAER_NOTA); 205 } 206 207 final String service = rollbackService; 208 final Map context = rollbackContext; 209 final boolean persist = rollbackAsyncPersist; 210 final boolean async = rollbackAsync; 211 212 Thread thread = new Thread () { 213 public void run() { 214 try { 215 runService(service, context, persist, (async ? MODE_ASYNC : MODE_SYNC), TYPE_ROLLBACK); 216 } catch (XAException e) { 217 Debug.logError(e, module); 218 } 219 } 220 }; 221 thread.start(); 222 223 this.xid = null; 224 this.active = false; 225 } 226 227 public int prepare(Xid xid) throws XAException { 228 Debug.log("ServiceXaWrapper#prepare() : " + xid.toString(), module); 230 int rtn; 231 try { 232 rtn = super.prepare(xid); 233 } catch (XAException e) { 234 Debug.logError(e, module); 235 throw e; 236 } 237 Debug.log("ServiceXaWrapper#prepare() : " + rtn + " / " + (rtn == XA_OK) , module); 238 return rtn; 239 } 240 241 242 243 protected final void runService(String service, Map context, boolean persist, int mode, int type) throws XAException { 244 String msgPrefix = "[XaWrapper] "; 246 switch (type) { 247 case TYPE_ROLLBACK: 248 msgPrefix = "[Rollback] "; 249 break; 250 case TYPE_COMMIT: 251 msgPrefix = "[Commit] "; 252 break; 253 } 254 255 if (UtilValidate.isNotEmpty(service)) { 257 258 Transaction parentTx = null; 260 boolean beganTx; 261 262 try { 263 int currentTxStatus = Status.STATUS_UNKNOWN; 264 try { 265 currentTxStatus = TransactionUtil.getStatus(); 266 } catch (GenericTransactionException e) { 267 Debug.logWarning(e, module); 268 } 269 270 if (currentTxStatus != Status.STATUS_NO_TRANSACTION) { 272 parentTx = TransactionUtil.suspend(); 273 } 274 275 beganTx = TransactionUtil.begin(); 277 278 try { 280 ModelService model = dctx.getModelService(service); 282 Map thisContext = context; 283 if (model.validate) { 284 thisContext = model.makeValid(context, ModelService.IN_PARAM); 285 } 286 287 thisContext.put("userLogin", ServiceUtil.getUserLogin(dctx, thisContext, runAsUser)); 289 290 switch (mode) { 292 case MODE_ASYNC: 293 Debug.log(msgPrefix + "Invoking [" + service + "] via runAsync", module); 294 dctx.getDispatcher().runAsync(service, thisContext, persist); 295 break; 296 297 case MODE_SYNC: 298 Debug.log(msgPrefix + "Invoking [" + service + "] via runSyncIgnore", module); 299 dctx.getDispatcher().runSyncIgnore(service, thisContext); 300 break; 301 } 302 } catch (Throwable t) { 303 Debug.logError(t, "Problem calling " + msgPrefix + "service : " + service + " / " + context, module); 304 try { 305 TransactionUtil.rollback(beganTx, t.getMessage(), t); 306 } catch (GenericTransactionException e) { 307 Debug.logError(e, module); 308 } 309 310 if (mode != MODE_ASYNC) { 312 throw new XAException (XAException.XA_RBOTHER); 313 } 314 } finally { 315 try { 317 TransactionUtil.commit(beganTx); 318 } catch (GenericTransactionException e) { 319 Debug.logError(e, module); 320 } 321 } 322 } catch (GenericTransactionException e) { 323 Debug.logError(e, module); 324 } finally { 325 if (parentTx != null) { 327 try { 328 TransactionUtil.resume(parentTx); 329 } catch (Exception e) { 330 Debug.logError(e, module); 331 } 332 } 333 } 334 } else { 335 Debug.log("No " + msgPrefix + "service defined; nothing to do", module); 336 } 337 338 this.xid = null; 339 this.active = false; 340 } 341 } 342 | Popular Tags |