KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > service > ServiceXaWrapper


1 /*
2  * $Id: ServiceXaWrapper.java 7284 2006-04-12 18:39:42Z jaz $
3  *
4  * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.service;
26
27 import java.util.Map JavaDoc;
28 import javax.transaction.Status JavaDoc;
29 import javax.transaction.Transaction JavaDoc;
30 import javax.transaction.xa.XAException JavaDoc;
31 import javax.transaction.xa.Xid JavaDoc;
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 /**
40  * ServiceXaWrapper - XA Resource wrapper for running services on commit() or rollback()
41  *
42  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
43  * @version $Rev: 7284 $
44  * @since 3.0
45  */

46 public class ServiceXaWrapper extends GenericXaResource {
47
48     public static final String JavaDoc 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 JavaDoc rollbackService = null;
56     protected String JavaDoc commitService = null;
57     protected String JavaDoc runAsUser = null;
58     protected Map JavaDoc rollbackContext = null;
59     protected Map JavaDoc 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     /**
71      * Sets the service to run on rollback()
72      * @param serviceName Name of service to run
73      * @param context Context to use when running
74      */

75     public void setCommitService(String JavaDoc serviceName, Map JavaDoc context) {
76         this.setCommitService(serviceName, null, context, commitAsync, commitAsyncPersist);
77     }
78
79     /**
80      * Sets the service to run on rollback()
81      * @param serviceName Name of service to run
82      * @param context Context to use when running
83      * @param async override default async behavior
84      */

85     public void setCommitService(String JavaDoc serviceName, Map JavaDoc context, boolean async, boolean persist) {
86         this.setCommitService(serviceName, null, context, async, persist);
87     }
88
89     /**
90      * Sets the service to run on rollback()
91      * @param serviceName Name of service to run
92      * @param runAsUser UserLoginID to run as
93      * @param context Context to use when running
94      * @param async override default async behavior
95      */

96     public void setCommitService(String JavaDoc serviceName, String JavaDoc runAsUser, Map JavaDoc 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     /**
106      * @return The name of the service to run on rollback()
107      */

108     public String JavaDoc getCommitService() {
109         return this.commitService;
110     }
111
112     /**
113      * @return The context used when running the rollback() service
114      */

115     public Map JavaDoc getCommitContext() {
116         return this.commitContext;
117     }
118
119     /**
120      * Sets the service to run on rollback()
121      * @param serviceName Name of service to run
122      * @param context Context to use when running
123      */

124     public void setRollbackService(String JavaDoc serviceName, Map JavaDoc context) {
125         this.setRollbackService(serviceName, context, rollbackAsync, rollbackAsyncPersist);
126     }
127
128     /**
129      * Sets the service to run on rollback()
130      * @param serviceName Name of service to run
131      * @param context Context to use when running
132      * @param async override default async behavior
133      */

134     public void setRollbackService(String JavaDoc serviceName, Map JavaDoc context, boolean async, boolean persist) {
135         this.rollbackService = serviceName;
136         this.rollbackContext = context;
137         this.rollbackAsync = async;
138         this.rollbackAsyncPersist = persist;
139     }
140
141     /**
142      * @return The name of the service to run on rollback()
143      */

144     public String JavaDoc getRollbackService() {
145         return this.rollbackService;
146     }
147
148     /**
149      * @return The context used when running the rollback() service
150      */

151     public Map JavaDoc getRollbackContext() {
152         return this.rollbackContext;
153     }
154
155     public void enlist() throws XAException JavaDoc {
156         super.enlist();
157         Debug.log("Enlisted in transaction : " + this.toString(), module);
158     }
159
160     // -- XAResource Methods
161
/**
162      * @see javax.transaction.xa.XAResource#commit(javax.transaction.xa.Xid xid, boolean onePhase)
163      */

164     public void commit(Xid JavaDoc xid, boolean onePhase) throws XAException JavaDoc {
165         Debug.log("ServiceXaWrapper#commit() : " + onePhase + " / " + xid.toString(), module);
166         // the commit listener
167
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 JavaDoc(XAException.XAER_NOTA);
172         }
173
174         final String JavaDoc service = commitService;
175         final Map JavaDoc context = commitContext;
176         final boolean persist = commitAsyncPersist;
177         final boolean async = commitAsync;
178
179         Thread JavaDoc thread = new Thread JavaDoc() {
180             public void run() {
181                 try {
182                     runService(service, context, persist, (async ? MODE_ASYNC : MODE_SYNC), TYPE_COMMIT);
183                 } catch (XAException JavaDoc e) {
184                     Debug.logError(e, module);
185                 }
186             }
187         };
188         thread.start();
189
190         this.xid = null;
191         this.active = false;
192     }
193
194     /**
195      * @see javax.transaction.xa.XAResource#rollback(javax.transaction.xa.Xid xid)
196      */

197     public void rollback(Xid JavaDoc xid) throws XAException JavaDoc {
198         Debug.log("ServiceXaWrapper#rollback() : " + xid.toString(), module);
199         // the rollback listener
200
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 JavaDoc(XAException.XAER_NOTA);
205         }
206
207         final String JavaDoc service = rollbackService;
208         final Map JavaDoc context = rollbackContext;
209         final boolean persist = rollbackAsyncPersist;
210         final boolean async = rollbackAsync;
211
212         Thread JavaDoc thread = new Thread JavaDoc() {
213             public void run() {
214                 try {
215                     runService(service, context, persist, (async ? MODE_ASYNC : MODE_SYNC), TYPE_ROLLBACK);
216                 } catch (XAException JavaDoc 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 JavaDoc xid) throws XAException JavaDoc {
228         // overriding to log two phase commits
229
Debug.log("ServiceXaWrapper#prepare() : " + xid.toString(), module);
230         int rtn;
231         try {
232             rtn = super.prepare(xid);
233         } catch (XAException JavaDoc 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 JavaDoc service, Map JavaDoc context, boolean persist, int mode, int type) throws XAException JavaDoc {
244         // set the logging prefix
245
String JavaDoc 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 a service exists; run it
256
if (UtilValidate.isNotEmpty(service)) {
257
258             // suspend this transaction
259
Transaction JavaDoc 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                 // suspend the parent tx
271
if (currentTxStatus != Status.STATUS_NO_TRANSACTION) {
272                     parentTx = TransactionUtil.suspend();
273                 }
274
275                 // begin the new tx
276
beganTx = TransactionUtil.begin();
277
278                 // configure and run the service
279
try {
280                     // obtain the model and get the valid context
281
ModelService model = dctx.getModelService(service);
282                     Map JavaDoc thisContext = context;
283                     if (model.validate) {
284                         thisContext = model.makeValid(context, ModelService.IN_PARAM);
285                     }
286
287                     // set the userLogin object
288
thisContext.put("userLogin", ServiceUtil.getUserLogin(dctx, thisContext, runAsUser));
289
290                     // invoke based on mode
291
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 JavaDoc 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                     // async calls are assumed to not effect this TX
311
if (mode != MODE_ASYNC) {
312                         throw new XAException JavaDoc(XAException.XA_RBOTHER);
313                     }
314                 } finally {
315                     // commit the transaction
316
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                 // resume the transaction
326
if (parentTx != null) {
327                     try {
328                         TransactionUtil.resume(parentTx);
329                     } catch (Exception JavaDoc 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