Author: lektran Date: Sat Aug 9 09:00:39 2014 New Revision: 1616925 URL: http://svn.apache.org/r1616925 Log: Replace the ServiceXaWrapper with a simpler Synchronization implementation. Helps pave the way for use of alternative transaction management libraries that don't work well with our XA wrapper implementations. Still DebugXaResource to go.
Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java (with props) Modified: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/valuelink/ValueLinkServices.java ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcher.java ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceXaWrapper.java ofbiz/trunk/framework/service/src/org/ofbiz/service/eca/ServiceEcaAction.java Modified: ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/valuelink/ValueLinkServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/valuelink/ValueLinkServices.java?rev=1616925&r1=1616924&r2=1616925&view=diff ============================================================================== --- ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/valuelink/ValueLinkServices.java (original) +++ ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/thirdparty/valuelink/ValueLinkServices.java Sat Aug 9 09:00:39 2014 @@ -24,8 +24,6 @@ import java.util.Locale; import java.util.Map; import java.util.Properties; -import javax.transaction.xa.XAException; - import javolution.util.FastMap; import org.ofbiz.base.util.Debug; @@ -48,7 +46,6 @@ import org.ofbiz.service.GenericServiceE import org.ofbiz.service.LocalDispatcher; import org.ofbiz.service.ModelService; import org.ofbiz.service.ServiceUtil; -import org.ofbiz.service.ServiceXaWrapper; /** * ValueLinkServices - Integration with ValueLink Gift Cards @@ -792,13 +789,11 @@ public class ValueLinkServices { // Activate/Rollback is not supported by valuelink if (!vlInterface.equals("Activate")) { // create the listener - ServiceXaWrapper xaw = new ServiceXaWrapper(dctx); - xaw.setRollbackService("vlTimeOutReversal", context); - //xaw.setCommitService("vlTimeOutReversal", context); Debug.logInfo("Set 704 context : " + context, module); try { - xaw.enlist(); - } catch (XAException e) { + dctx.getDispatcher().addRollbackService("vlTimeOutReversal", context, false); + //dctx.getDispatcher().addCommitService("vlTimeOutReversal", context, false); + } catch (GenericServiceException e) { Debug.logError(e, "Unable to setup 0704 Timeout Reversal", module); } } @@ -1214,14 +1209,10 @@ public class ValueLinkServices { } if (!failure) { - // set the void on rollback wrapper - ServiceXaWrapper xaw = new ServiceXaWrapper(dctx); - activateCtx.put("cardNumber", activateResult.get("cardNumber")); - activateCtx.put("pin", activateResult.get("pin")); - xaw.setRollbackService("voidActivateGiftCard", activateCtx); + // set the void on rollback try { - xaw.enlist(); - } catch (XAException e) { + dispatcher.addRollbackService("voidActivateGiftCard", activateCtx, false); + } catch (GenericServiceException e) { Debug.logError(e, "Unable to setup Activate/Void on error", module); } } Modified: ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java?rev=1616925&r1=1616924&r2=1616925&view=diff ============================================================================== --- ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java (original) +++ ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java Sat Aug 9 09:00:39 2014 @@ -40,7 +40,6 @@ import java.util.Set; import java.util.TreeSet; import javax.mail.internet.MimeMessage; -import javax.transaction.xa.XAException; import javolution.util.FastList; import javolution.util.FastMap; @@ -65,8 +64,8 @@ import org.ofbiz.service.DispatchContext import org.ofbiz.service.GenericServiceException; import org.ofbiz.service.LocalDispatcher; import org.ofbiz.service.ModelService; +import org.ofbiz.service.ServiceSynchronization; import org.ofbiz.service.ServiceUtil; -import org.ofbiz.service.ServiceXaWrapper; import org.ofbiz.service.mail.MimeMessageWrapper; import org.owasp.esapi.errors.EncodingException; @@ -142,23 +141,19 @@ public class CommonServices { } public static Map<String, Object> testRollbackListener(DispatchContext dctx, Map<String, ?> context) { - Locale locale = (Locale) context.get("locale"); - ServiceXaWrapper xar = new ServiceXaWrapper(dctx); - xar.setRollbackService("testScv", context); try { - xar.enlist(); - } catch (XAException e) { + ServiceSynchronization.registerRollbackService(dctx, "testScv", null, context, false, false); + } catch (GenericServiceException e) { Debug.logError(e, module); } + Locale locale = (Locale) context.get("locale"); return ServiceUtil.returnError(UtilProperties.getMessage(resource, "CommonTestRollingBack", locale)); } public static Map<String, Object> testCommitListener(DispatchContext dctx, Map<String, ?> context) { - ServiceXaWrapper xar = new ServiceXaWrapper(dctx); - xar.setCommitService("testScv", context); try { - xar.enlist(); - } catch (XAException e) { + ServiceSynchronization.registerCommitService(dctx, "testScv", null, context, false, false); + } catch (GenericServiceException e) { Debug.logError(e, module); } return ServiceUtil.returnSuccess(); Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java?rev=1616925&r1=1616924&r2=1616925&view=diff ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java (original) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java Sat Aug 9 09:00:39 2014 @@ -22,7 +22,6 @@ import java.util.Date; import java.util.Map; import javax.transaction.Transaction; -import javax.transaction.xa.XAException; import org.ofbiz.service.calendar.RecurrenceRule; import org.ofbiz.entity.Delegator; @@ -117,14 +116,7 @@ public abstract class GenericAbstractDis } public void addRollbackService(String serviceName, Map<String, ? extends Object> context, boolean persist) throws GenericServiceException { - ServiceXaWrapper xa = new ServiceXaWrapper(this.getDispatchContext()); - xa.setRollbackService(serviceName, context, true, persist); - try { - xa.enlist(); - } catch (XAException e) { - Debug.logError(e, module); - throw new GenericServiceException(e.getMessage(), e); - } + ServiceSynchronization.registerRollbackService(this.getDispatchContext(), serviceName, null, context, true, persist); } public void addRollbackService(String serviceName, boolean persist, Object... context) throws GenericServiceException { @@ -132,14 +124,7 @@ public abstract class GenericAbstractDis } public void addCommitService(String serviceName, Map<String, ? extends Object> context, boolean persist) throws GenericServiceException { - ServiceXaWrapper xa = new ServiceXaWrapper(this.getDispatchContext()); - xa.setCommitService(serviceName, context, true, persist); - try { - xa.enlist(); - } catch (XAException e) { - Debug.logError(e, module); - throw new GenericServiceException(e.getMessage(), e); - } + ServiceSynchronization.registerCommitService(this.getDispatchContext(), serviceName, null, context, true, persist); } public void addCommitService(String serviceName, boolean persist, Object... context) throws GenericServiceException { Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcher.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcher.java?rev=1616925&r1=1616924&r2=1616925&view=diff ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcher.java (original) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcher.java Sat Aug 9 09:00:39 2014 @@ -281,7 +281,7 @@ public interface LocalDispatcher { /** - * Adds a rollback service to the current TX using the ServiceXaWrapper + * Adds a rollback service to the current TX using ServiceSynchronization * @param serviceName * @param context * @param persist @@ -291,7 +291,7 @@ public interface LocalDispatcher { public void addRollbackService(String serviceName, boolean persist, Object... context) throws GenericServiceException; /** - * Adds a commit service to the current TX using the ServiceXaWrapper + * Adds a commit service to the current TX using ServiceSynchronization * @param serviceName * @param context * @param persist Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java?rev=1616925&view=auto ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java (added) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java Sat Aug 9 09:00:39 2014 @@ -0,0 +1,167 @@ +package org.ofbiz.service; + +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +import javax.transaction.RollbackException; +import javax.transaction.Status; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.Transaction; + +import javolution.util.FastList; +import javolution.util.FastMap; + +import org.ofbiz.base.util.Debug; +import org.ofbiz.entity.transaction.GenericTransactionException; +import org.ofbiz.entity.transaction.TransactionFactory; +import org.ofbiz.entity.transaction.TransactionUtil; + +/** + * This class is used to execute services when a transaction is either + * committed or rolled back. It should generally be accessed via + * LocalDispatcher's addCommitService and addRollbackService methods + * or by using the service ECA event attribute values global-commit, + * global-rollback or global-commit-post-run + * + */ +public class ServiceSynchronization implements Synchronization { + + public static final String MODULE = ServiceSynchronization.class.getName(); + + private static Map<Transaction, ServiceSynchronization> syncingleton = new WeakHashMap<Transaction, ServiceSynchronization>(); + private List<ServiceExecution> services = FastList.newInstance(); + + public static void registerCommitService(DispatchContext dctx, String serviceName, String runAsUser, Map<String, ? extends Object> context, boolean async, boolean persist) throws GenericServiceException { + ServiceSynchronization sync = ServiceSynchronization.getInstance(); + if (sync != null) { + sync.services.add(new ServiceExecution(dctx, serviceName, runAsUser, context, async, persist, false)); + } + } + + public static void registerRollbackService(DispatchContext dctx, String serviceName, String runAsUser, Map<String, ? extends Object> context, boolean async, boolean persist) throws GenericServiceException { + ServiceSynchronization sync = ServiceSynchronization.getInstance(); + if (sync != null) { + sync.services.add(new ServiceExecution(dctx, serviceName, runAsUser, context, async, persist, true)); + } + } + + protected static ServiceSynchronization getInstance() throws GenericServiceException { + ServiceSynchronization sync = null; + try { + Transaction transaction = TransactionFactory.getTransactionManager().getTransaction(); + synchronized (transaction) { + sync = syncingleton.get(transaction); + if (sync == null) { + sync = new ServiceSynchronization(); + transaction.registerSynchronization(sync); + syncingleton.put(transaction, sync); + } + } + } catch (SystemException e) { + throw new GenericServiceException(e.getMessage(), e); + } catch (IllegalStateException e) { + throw new GenericServiceException(e.getMessage(), e); + } catch (RollbackException e) { + throw new GenericServiceException(e.getMessage(), e); + } + return sync; + } + + @Override + public void afterCompletion(int status) { + for (ServiceExecution serviceExec : this.services) { + serviceExec.runService(status); + } + } + + @Override + public void beforeCompletion() { + + } + + static class ServiceExecution { + protected DispatchContext dctx = null; + protected String serviceName; + protected String runAsUser = null; + protected Map<String, ? extends Object> context = null; + protected boolean rollback = false; + protected boolean persist = true; + protected boolean async = false; + + ServiceExecution(DispatchContext dctx, String serviceName, String runAsUser, Map<String, ? extends Object> context, boolean async, boolean persist, boolean rollback) { + this.dctx = dctx; + this.serviceName = serviceName; + this.runAsUser = runAsUser; + this.context = context; + this.async = async; + this.persist = persist; + this.rollback = rollback; + } + + protected void runService(int status) { + if ((status == Status.STATUS_COMMITTED && !rollback) || (status == Status.STATUS_ROLLEDBACK && rollback)) { + Thread thread = new Thread() { + @Override + public void run() { + String msgPrefix = null; + if (rollback) { + msgPrefix = "[Rollback] "; + } else { + msgPrefix = "[Commit] "; + } + + boolean beganTx; + try { + // begin the new tx + beganTx = TransactionUtil.begin(); + // configure and run the service + try { + // obtain the model and get the valid context + ModelService model = dctx.getModelService(serviceName); + Map<String, Object> thisContext; + if (model.validate) { + thisContext = model.makeValid(context, ModelService.IN_PARAM); + } else { + thisContext = FastMap.newInstance(); + thisContext.putAll(context); + } + + // set the userLogin object + thisContext.put("userLogin", ServiceUtil.getUserLogin(dctx, thisContext, runAsUser)); + if (async) { + if (Debug.infoOn()) Debug.logInfo(msgPrefix + "Invoking [" + serviceName + "] via runAsync", MODULE); + dctx.getDispatcher().runAsync(serviceName, thisContext, persist); + } else { + if (Debug.infoOn()) Debug.logInfo(msgPrefix + "Invoking [" + serviceName + "] via runSyncIgnore", MODULE); + dctx.getDispatcher().runSyncIgnore(serviceName, thisContext); + } + } catch (Throwable t) { + Debug.logError(t, "Problem calling " + msgPrefix + "service : " + serviceName + " / " + context, MODULE); + try { + TransactionUtil.rollback(beganTx, t.getMessage(), t); + } catch (GenericTransactionException e) { + Debug.logError(e, MODULE); + } + + } finally { + // commit the transaction + try { + TransactionUtil.commit(beganTx); + } catch (GenericTransactionException e) { + Debug.logError(e, MODULE); + } + } + } catch (GenericTransactionException e) { + Debug.logError(e, MODULE); + } + + } + }; + thread.start(); + } + } + } + +} Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceSynchronization.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceXaWrapper.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceXaWrapper.java?rev=1616925&r1=1616924&r2=1616925&view=diff ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceXaWrapper.java (original) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceXaWrapper.java Sat Aug 9 09:00:39 2014 @@ -34,7 +34,9 @@ import org.ofbiz.entity.transaction.Tran /** * ServiceXaWrapper - XA Resource wrapper for running services on commit() or rollback() + * @deprecated - Use ServiceSynchronization instead (via LocalDispatcher) */ +@Deprecated public class ServiceXaWrapper extends GenericXaResource { public static final String module = ServiceXaWrapper.class.getName(); Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/eca/ServiceEcaAction.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/eca/ServiceEcaAction.java?rev=1616925&r1=1616924&r2=1616925&view=diff ============================================================================== --- ofbiz/trunk/framework/service/src/org/ofbiz/service/eca/ServiceEcaAction.java (original) +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/eca/ServiceEcaAction.java Sat Aug 9 09:00:39 2014 @@ -22,8 +22,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.transaction.xa.XAException; - import javolution.util.FastMap; import org.ofbiz.base.util.Debug; @@ -33,8 +31,8 @@ import org.ofbiz.service.DispatchContext import org.ofbiz.service.GenericServiceException; import org.ofbiz.service.LocalDispatcher; import org.ofbiz.service.ModelService; +import org.ofbiz.service.ServiceSynchronization; import org.ofbiz.service.ServiceUtil; -import org.ofbiz.service.ServiceXaWrapper; import org.w3c.dom.Element; /** @@ -115,19 +113,12 @@ public class ServiceEcaAction implements } if (eventName.startsWith("global-")) { - // XA resource ECA - ServiceXaWrapper xaw = new ServiceXaWrapper(dctx); if (eventName.equals("global-rollback")) { - xaw.setRollbackService(serviceName, runAsUser, context, "async".equals(serviceMode), persist); // using the actual context so we get updates + ServiceSynchronization.registerRollbackService(dctx, serviceName, runAsUser, context, "async".equals(serviceMode), persist); // using the actual context so we get updates } else if (eventName.equals("global-commit")) { - xaw.setCommitService(serviceName, runAsUser, context, "async".equals(serviceMode), persist); // using the actual context so we get updates + ServiceSynchronization.registerCommitService(dctx, serviceName, runAsUser, context, "async".equals(serviceMode), persist); // using the actual context so we get updates } else if (eventName.equals("global-commit-post-run")) { - xaw.setCommitService(serviceName, runAsUser, context, "async".equals(serviceMode), persist); // using the actual context so we get updates - } - try { - xaw.enlist(); - } catch (XAException e) { - throw new GenericServiceException("Unable to enlist ServiceXaWrapper with transaction", e); + ServiceSynchronization.registerCommitService(dctx, serviceName, runAsUser, context, "async".equals(serviceMode), persist); // using the actual context so we get updates } } else { // standard ECA