You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ja...@apache.org on 2012/07/24 11:16:28 UTC

svn commit: r1364952 - in /ofbiz/trunk: applications/product/src/org/ofbiz/product/config/ applications/product/src/org/ofbiz/shipment/packing/ applications/product/src/org/ofbiz/shipment/verify/ applications/product/src/org/ofbiz/shipment/weightPackag...

Author: jacopoc
Date: Tue Jul 24 09:16:26 2012
New Revision: 1364952

URL: http://svn.apache.org/viewvc?rev=1364952&view=rev
Log:
A rather important refactoring of service related code:
* new factory interface for LocalDispatcher objects
* new factory implementation of GenericDispatcher
* new ServiceContainer container that initializes the factory (based on a configuration parameter)
* moved the getLocalDispatcher method out of GenericDispatcher and refactored (in a thread safe way) into ServiceContainer/GenericDispatcherFactory
* ServiceContainer also maintains the cache of LocalDispatchers that was managed by GenericDispatcher
* added code to ServiceContainer to deregister LocalDispatchers at shutdown: this finally fix the current code that was broken because the thread pool maintained by the JobPoller was never closed because of an issue with LocalDispatchers not being deregistered when not started by the ContextFilter
* change all code to call the ServiceContainer rather than GenericContainer to get a LocalDispatcher: now the implementation is no more directly referenced by calling code

Added:
    ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcherFactory.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceContainer.java
Modified:
    ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/shipment/packing/PackingSession.java
    ofbiz/trunk/applications/product/src/org/ofbiz/shipment/verify/VerifyPickSession.java
    ofbiz/trunk/applications/product/src/org/ofbiz/shipment/weightPackage/WeightPackageSession.java
    ofbiz/trunk/framework/component-load.xml
    ofbiz/trunk/framework/entityext/src/org/ofbiz/entityext/EntityServiceFactory.java
    ofbiz/trunk/framework/service/ofbiz-component.xml
    ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcher.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/jms/AbstractJmsListener.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/job/JobManager.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java
    ofbiz/trunk/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/ServiceStreamHandler.java
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/XmlRpcEventHandler.java
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/webdav/WebDavServlet.java
    ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/guiapp/xui/XuiContainer.java
    ofbiz/trunk/specialpurpose/workflow/src/org/ofbiz/workflow/impl/WfExecutionObjectImpl.java

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigItemContentWrapper.java Tue Jul 24 09:16:26 2012
@@ -41,8 +41,8 @@ import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.model.ModelEntity;
 import org.ofbiz.entity.model.ModelUtil;
 import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 /**
  * Product Config Item Content Worker: gets product content to display
@@ -98,7 +98,7 @@ public class ProductConfigItemContentWra
 
     public LocalDispatcher getDispatcher() {
         if (dispatcher == null) {
-            dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.getDelegator());
+            dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.getDelegator());
         }
         return dispatcher;
     }

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java Tue Jul 24 09:16:26 2012
@@ -39,8 +39,8 @@ import org.ofbiz.entity.DelegatorFactory
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 
 /**
@@ -219,7 +219,7 @@ public class ProductConfigWrapper implem
 
     public LocalDispatcher getDispatcher() {
         if (dispatcher == null) {
-            dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.getDelegator());
+            dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.getDelegator());
         }
         return dispatcher;
     }

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/shipment/packing/PackingSession.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/shipment/packing/PackingSession.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/shipment/packing/PackingSession.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/shipment/packing/PackingSession.java Tue Jul 24 09:16:26 2012
@@ -41,9 +41,9 @@ import org.ofbiz.entity.GenericEntityExc
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.product.product.ProductWorker;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.ServiceUtil;
 
 @SuppressWarnings("serial")
@@ -496,7 +496,7 @@ public class PackingSession implements j
 
     public LocalDispatcher getDispatcher() {
         if (_dispatcher == null) {
-            _dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.getDelegator());
+            _dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.getDelegator());
         }
         return _dispatcher;
     }

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/shipment/verify/VerifyPickSession.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/shipment/verify/VerifyPickSession.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/shipment/verify/VerifyPickSession.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/shipment/verify/VerifyPickSession.java Tue Jul 24 09:16:26 2012
@@ -37,8 +37,8 @@ import org.ofbiz.entity.DelegatorFactory
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.util.EntityUtil;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.ServiceUtil;
 
 @SuppressWarnings("serial")
@@ -71,7 +71,7 @@ public class VerifyPickSession implement
 
     public LocalDispatcher getDispatcher() {
         if (_dispatcher == null) {
-            _dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.getDelegator());
+            _dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.getDelegator());
         }
         return _dispatcher;
     }

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/shipment/weightPackage/WeightPackageSession.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/shipment/weightPackage/WeightPackageSession.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/shipment/weightPackage/WeightPackageSession.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/shipment/weightPackage/WeightPackageSession.java Tue Jul 24 09:16:26 2012
@@ -38,8 +38,8 @@ import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.ServiceUtil;
 
 @SuppressWarnings("serial")
@@ -97,7 +97,7 @@ public class WeightPackageSession implem
 
     public LocalDispatcher getDispatcher() {
         if (_dispatcher == null) {
-            _dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.getDelegator());
+            _dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.getDelegator());
         }
         return _dispatcher;
     }

Modified: ofbiz/trunk/framework/component-load.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/component-load.xml?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/component-load.xml (original)
+++ ofbiz/trunk/framework/component-load.xml Tue Jul 24 09:16:26 2012
@@ -24,13 +24,13 @@ under the License.
     <load-component component-location="geronimo"/>
     <load-component component-location="sql"/>
     <load-component component-location="entity"/>
-    <load-component component-location="catalina"/>
-    <!-- <load-component component-location="jetty"/> -->
     <load-component component-location="security"/>
     <load-component component-location="datafile"/>
     <load-component component-location="minilang"/>
     <load-component component-location="common"/>
     <load-component component-location="service"/>
+    <!-- <load-component component-location="jetty"/> -->
+    <load-component component-location="catalina"/>
     <load-component component-location="entityext"/>
     <load-component component-location="bi"/>
     <load-component component-location="webapp"/>

Modified: ofbiz/trunk/framework/entityext/src/org/ofbiz/entityext/EntityServiceFactory.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entityext/src/org/ofbiz/entityext/EntityServiceFactory.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/entityext/src/org/ofbiz/entityext/EntityServiceFactory.java (original)
+++ ofbiz/trunk/framework/entityext/src/org/ofbiz/entityext/EntityServiceFactory.java Tue Jul 24 09:16:26 2012
@@ -20,8 +20,8 @@ package org.ofbiz.entityext;
 
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 /**
  * EntityEcaUtil
@@ -31,7 +31,7 @@ public class EntityServiceFactory {
     public static final String module = EntityServiceFactory.class.getName();
 
     public static LocalDispatcher getLocalDispatcher(Delegator delegator) {
-        LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher("entity-" + delegator.getDelegatorName(), delegator);
+        LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher("entity-" + delegator.getDelegatorName(), delegator);
         return dispatcher;
     }
 

Modified: ofbiz/trunk/framework/service/ofbiz-component.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/ofbiz-component.xml?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/ofbiz-component.xml (original)
+++ ofbiz/trunk/framework/service/ofbiz-component.xml Tue Jul 24 09:16:26 2012
@@ -44,6 +44,9 @@ under the License.
     <keystore name="rmitrust" type="jks" password="changeit" is-truststore="true"
               is-certstore="false" loader="main" location="config/rmitrust.jks"/>
 
+    <container name="service-container" loaders="main,rmi,pos,install,test" class="org.ofbiz.service.ServiceContainer">
+        <property name="dispatcher-factory" value="org.ofbiz.service.GenericDispatcherFactory"/>
+    </container>
     <!-- RMI Service Dispatcher -->
     <container name="rmi-dispatcher" loaders="rmi" class="org.ofbiz.service.rmi.RmiServiceContainer">
         <property name="bound-name" value="RMIDispatcher"/>

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=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericAbstractDispatcher.java Tue Jul 24 09:16:26 2012
@@ -237,6 +237,7 @@ public abstract class GenericAbstractDis
      * @see org.ofbiz.service.LocalDispatcher#deregister()
      */
     public void deregister() {
+        ServiceContainer.removeFromCache(getName());
         dispatcher.deregister(this);
     }
 

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcher.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcher.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcher.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcher.java Tue Jul 24 09:16:26 2012
@@ -19,9 +19,6 @@
 package org.ofbiz.service;
 
 import java.util.Map;
-import java.util.Set;
-
-import javolution.util.FastMap;
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilValidate;
@@ -35,43 +32,6 @@ public class GenericDispatcher extends G
     public static final String module = GenericDispatcher.class.getName();
 
     protected static boolean ecasDisabled = false;
-    protected static Map<String, LocalDispatcher> dispatcherCache = FastMap.newInstance();
-
-    public static LocalDispatcher getLocalDispatcher(String dispatcherName, Delegator delegator) {
-        if (dispatcherName == null) {
-            dispatcherName = delegator.getDelegatorName();
-            Debug.logWarning("Got a getGenericDispatcher call with a null dispatcherName, assuming default for the name.", module);
-        }
-
-        if (UtilValidate.isNotEmpty(delegator.getDelegatorTenantId())) {
-            dispatcherName += "#" + delegator.getDelegatorTenantId();
-        }
-
-        LocalDispatcher dispatcher = dispatcherCache.get(dispatcherName);
-
-        if (dispatcher == null) {
-            synchronized (GenericDispatcher.class) {
-                // must check if null again as one of the blocked threads can still enter
-                dispatcher = dispatcherCache.get(dispatcherName);
-                if (dispatcher == null) {
-                    if (Debug.infoOn()) Debug.logInfo("Creating new dispatcher [" + dispatcherName + "] (" + Thread.currentThread().getName() + ")", module);
-                    // attempts to retrieve an already registered DispatchContext with the name dispatcherName
-                    dispatcher = ServiceDispatcher.getLocalDispatcher(dispatcherName, delegator);
-                    // if not found then create a new GenericDispatcher object; the constructor will also register a new DispatchContext in the ServiceDispatcher with name "dispatcherName"
-                    if (dispatcher == null) {
-                        dispatcher = new GenericDispatcher(dispatcherName, delegator);
-                    }
-
-                    dispatcherCache.put(dispatcherName, dispatcher);
-                }
-            }
-        }
-        return dispatcher;
-    }
-
-    public static Set<String> getAllDispatcherNames() {
-        return dispatcherCache.keySet();
-    }
 
     protected GenericDispatcher() {}
 

Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java?rev=1364952&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/GenericDispatcherFactory.java Tue Jul 24 09:16:26 2012
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.service;
+
+import org.ofbiz.entity.Delegator;
+
+public class GenericDispatcherFactory implements LocalDispatcherFactory {
+    public LocalDispatcher createLocalDispatcher(String name, Delegator delegator) {
+        // attempts to retrieve an already registered DispatchContext with the name "name"
+        LocalDispatcher dispatcher = ServiceDispatcher.getLocalDispatcher(name, delegator);
+        // if not found then create a new GenericDispatcher object; the constructor will also register a new DispatchContext in the ServiceDispatcher with name "dispatcherName"
+        if (dispatcher == null) {
+            dispatcher = new GenericDispatcher(name, delegator);
+        }
+        return dispatcher;
+    }
+}

Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcherFactory.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcherFactory.java?rev=1364952&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcherFactory.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/LocalDispatcherFactory.java Tue Jul 24 09:16:26 2012
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.service;
+
+import org.ofbiz.entity.Delegator;
+
+public interface LocalDispatcherFactory {
+    public LocalDispatcher createLocalDispatcher(String name, Delegator delegator);
+}

Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceContainer.java?rev=1364952&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceContainer.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceContainer.java Tue Jul 24 09:16:26 2012
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.service;
+
+import org.ofbiz.base.container.Container;
+import org.ofbiz.base.container.ContainerConfig;
+import org.ofbiz.base.container.ContainerException;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.Delegator;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ServiceContainer implements Container {
+    private static final String module = ServiceContainer.class.getName();
+    private static ConcurrentHashMap<String, LocalDispatcher> dispatcherCache = new ConcurrentHashMap<String, LocalDispatcher>();
+    private static LocalDispatcherFactory dispatcherFactory;
+
+    private String name;
+
+    public void init(String[] args, String name, String configFile) throws ContainerException {
+        this.name = name;
+        // initialize the LocalDispatcherFactory
+        ContainerConfig.Container cfg = ContainerConfig.getContainer(name, configFile);
+        ContainerConfig.Container.Property dispatcherFactoryProperty = cfg.getProperty("dispatcher-factory");
+
+        if (dispatcherFactoryProperty == null || UtilValidate.isEmpty(dispatcherFactoryProperty.value)) {
+            throw new ContainerException("Unable to initialize container " + name + ": dispatcher-factory property is not set");
+        }
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        try {
+            Class<?> c = loader.loadClass(dispatcherFactoryProperty.value);
+            dispatcherFactory = (LocalDispatcherFactory) c.newInstance();
+        } catch (Exception e) {
+            throw new ContainerException(e);
+        }
+    }
+
+    public boolean start() throws ContainerException {
+        return true;
+    }
+
+    public void stop() throws ContainerException {
+        Set<String> dispatcherNames = getAllDispatcherNames();
+        for (String dispatcherName: dispatcherNames) {
+            ServiceContainer.deregister(dispatcherName);
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public static LocalDispatcher getLocalDispatcher(String dispatcherName, Delegator delegator) {
+        if (dispatcherName == null) {
+            dispatcherName = delegator.getDelegatorName();
+            Debug.logWarning("Got a getLocalDispatcher call with a null dispatcherName, assuming default for the name.", module);
+        }
+        if (UtilValidate.isNotEmpty(delegator.getDelegatorTenantId())) {
+            dispatcherName += "#" + delegator.getDelegatorTenantId();
+        }
+        LocalDispatcher dispatcher = dispatcherCache.get(dispatcherName);
+        if (dispatcher == null) {
+            if (Debug.infoOn()) Debug.logInfo("Creating new dispatcher [" + dispatcherName + "] (" + Thread.currentThread().getName() + ")", module);
+            dispatcher = dispatcherFactory.createLocalDispatcher(dispatcherName, delegator);
+            dispatcherCache.putIfAbsent(dispatcherName, dispatcher);
+        }
+        return dispatcher;
+    }
+
+    public static void deregister(String dispatcherName) {
+        LocalDispatcher dispatcher = dispatcherCache.get(dispatcherName);
+        if (dispatcher != null) {
+            dispatcher.deregister();
+        }
+    }
+
+    public static LocalDispatcher removeFromCache(String dispatcherName) {
+        if (Debug.infoOn()) Debug.logInfo("Removing from cache dispatcher: " + dispatcherName, module);
+        return dispatcherCache.remove(dispatcherName);
+    }
+
+    public static Set<String> getAllDispatcherNames() {
+        return dispatcherCache.keySet();
+    }
+}

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java Tue Jul 24 09:16:26 2012
@@ -180,7 +180,7 @@ public class ServiceDispatcher {
     public void deregister(LocalDispatcher local) {
         if (Debug.infoOn()) Debug.logInfo("De-Registering dispatcher: " + local.getName(), module);
         localContext.remove(local.getName());
-        if (localContext.size() == 1) { // TODO: this is a tweak that is currently not working (2 contexts are not deregistered)
+        if (localContext.size() == 0) {
             try {
                  this.shutdown();
              } catch (GenericServiceException e) {
@@ -831,8 +831,10 @@ public class ServiceDispatcher {
 
     protected void shutdown() throws GenericServiceException {
         Debug.logImportant("Shutting down the service engine...", module);
-        // shutdown JMS listeners
-        jlf.closeListeners();
+        if (jlf != null) {
+            // shutdown JMS listeners
+            jlf.closeListeners();
+        }
         // shutdown the job scheduler
         jm.shutdown();
     }

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/jms/AbstractJmsListener.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/jms/AbstractJmsListener.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/jms/AbstractJmsListener.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/jms/AbstractJmsListener.java Tue Jul 24 09:16:26 2012
@@ -29,10 +29,10 @@ import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.ObjectType;
 import org.ofbiz.base.util.UtilGenerics;
 import org.ofbiz.entity.serialize.XmlSerializer;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ModelService;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.ServiceDispatcher;
 
 /**
@@ -50,7 +50,7 @@ public abstract class AbstractJmsListene
      * @param serviceDispatcher the service dispatcher
      */
     protected AbstractJmsListener(ServiceDispatcher serviceDispatcher) {
-        this.dispatcher = GenericDispatcher.getLocalDispatcher("JMSDispatcher", serviceDispatcher.getDelegator());
+        this.dispatcher = ServiceContainer.getLocalDispatcher("JMSDispatcher", serviceDispatcher.getDelegator());
     }
 
     /**

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/job/JobManager.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/job/JobManager.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/job/JobManager.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/job/JobManager.java Tue Jul 24 09:16:26 2012
@@ -45,8 +45,8 @@ import org.ofbiz.entity.serialize.XmlSer
 import org.ofbiz.entity.transaction.GenericTransactionException;
 import org.ofbiz.entity.transaction.TransactionUtil;
 import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.calendar.RecurrenceInfo;
 import org.ofbiz.service.calendar.RecurrenceInfoException;
 import org.ofbiz.service.config.ServiceConfigUtil;
@@ -91,7 +91,7 @@ public class JobManager {
 
     /** Returns the LocalDispatcher. */
     public LocalDispatcher getDispatcher() {
-        LocalDispatcher thisDispatcher = GenericDispatcher.getLocalDispatcher(delegator.getDelegatorName(), delegator);
+        LocalDispatcher thisDispatcher = ServiceContainer.getLocalDispatcher(delegator.getDelegatorName(), delegator);
         return thisDispatcher;
     }
 

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/mail/JavaMailContainer.java Tue Jul 24 09:16:26 2012
@@ -49,9 +49,9 @@ import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.ServiceContainer;
 
 public class JavaMailContainer implements Container {
 
@@ -98,7 +98,7 @@ public class JavaMailContainer implement
         this.deleteMail = "true".equals(ContainerConfig.getPropertyValue(cfg, "delete-mail", "false"));
 
         this.delegator = DelegatorFactory.getDelegator(delegatorName);
-        this.dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, delegator);
+        this.dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, delegator);
         this.timerDelay = ContainerConfig.getPropertyValue(cfg, "poll-delay", 300000);
         this.maxSize = ContainerConfig.getPropertyValue(cfg, "maxSize", 1000000); // maximum size in bytes
 

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/rmi/RmiServiceContainer.java Tue Jul 24 09:16:26 2012
@@ -32,8 +32,8 @@ import org.ofbiz.base.container.Containe
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 /**
  * RMI Service Engine Container / Dispatcher
@@ -126,7 +126,7 @@ public class RmiServiceContainer impleme
         Delegator delegator = DelegatorFactory.getDelegator(delegatorProp.value);
 
         // create the LocalDispatcher
-        LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher(name, delegator);
+        LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher(name, delegator);
 
         // create the RemoteDispatcher
         try {

Modified: ofbiz/trunk/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java (original)
+++ ofbiz/trunk/framework/testtools/src/org/ofbiz/testtools/ModelTestSuite.java Tue Jul 24 09:16:26 2012
@@ -38,8 +38,8 @@ import org.ofbiz.entity.DelegatorFactory
 import org.ofbiz.entity.testtools.EntityTestCase;
 import org.ofbiz.minilang.MiniLangException;
 import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.testtools.OFBizTestCase;
 import org.w3c.dom.Element;
 
@@ -71,7 +71,7 @@ public class ModelTestSuite {
         String uniqueSuffix = "-" + RandomStringUtils.randomAlphanumeric(10);
 
         this.delegator = DelegatorFactory.getDelegator(this.originalDelegatorName).makeTestDelegator(this.originalDelegatorName + uniqueSuffix);
-        this.dispatcher = GenericDispatcher.getLocalDispatcher(originalDispatcherName + uniqueSuffix, delegator);
+        this.dispatcher = ServiceContainer.getLocalDispatcher(originalDispatcherName + uniqueSuffix, delegator);
 
         for (Element testCaseElement : UtilXml.childElementList(mainElement, UtilMisc.toSet("test-case", "test-group"))) {
             String caseName = testCaseElement.getAttribute("case-name");

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ContextFilter.java Tue Jul 24 09:16:26 2012
@@ -58,8 +58,8 @@ import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.security.Security;
 import org.ofbiz.security.SecurityConfigurationException;
 import org.ofbiz.security.SecurityFactory;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 /**
  * ContextFilter - Restricts access to raw files and configures servlet objects.
@@ -350,7 +350,7 @@ public class ContextFilter implements Fi
             dispatcherName = delegator.getDelegatorName();
         }
 
-        LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, delegator);
+        LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, delegator);
         if (dispatcher == null) {
             Debug.logError("[ContextFilter.init] ERROR: dispatcher could not be initialized.", module);
         }

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/ServiceStreamHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/ServiceStreamHandler.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/ServiceStreamHandler.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/ServiceStreamHandler.java Tue Jul 24 09:16:26 2012
@@ -34,9 +34,9 @@ import javolution.util.FastMap;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.webapp.control.ConfigXMLReader.Event;
 import org.ofbiz.webapp.control.ConfigXMLReader.RequestMap;
@@ -53,7 +53,7 @@ public class ServiceStreamHandler implem
     public void init(ServletContext context) throws EventHandlerException {
         String delegatorName = context.getInitParameter("entityDelegatorName");
         this.delegator = DelegatorFactory.getDelegator(delegatorName);
-        this.dispatcher = GenericDispatcher.getLocalDispatcher(this.delegator.getDelegatorName(), delegator);
+        this.dispatcher = ServiceContainer.getLocalDispatcher(this.delegator.getDelegatorName(), delegator);
     }
 
     public String invoke(Event event, RequestMap requestMap, HttpServletRequest request, HttpServletResponse response) throws EventHandlerException {

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/XmlRpcEventHandler.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/XmlRpcEventHandler.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/XmlRpcEventHandler.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/event/XmlRpcEventHandler.java Tue Jul 24 09:16:26 2012
@@ -52,10 +52,10 @@ import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ModelService;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.webapp.control.ConfigXMLReader;
 import org.ofbiz.webapp.control.ConfigXMLReader.Event;
@@ -76,7 +76,7 @@ public class XmlRpcEventHandler extends 
     public void init(ServletContext context) throws EventHandlerException {
         String delegatorName = context.getInitParameter("entityDelegatorName");
         this.delegator = DelegatorFactory.getDelegator(delegatorName);
-        this.dispatcher = GenericDispatcher.getLocalDispatcher(delegator.getDelegatorName(), delegator);
+        this.dispatcher = ServiceContainer.getLocalDispatcher(delegator.getDelegatorName(), delegator);
         this.setHandlerMapping(new ServiceRpcHandler());
 
         String extensionsEnabledString = context.getInitParameter("xmlrpc.enabledForExtensions");

Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/webdav/WebDavServlet.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/webdav/WebDavServlet.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/webdav/WebDavServlet.java (original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/webdav/WebDavServlet.java Tue Jul 24 09:16:26 2012
@@ -36,8 +36,8 @@ import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.security.Security;
 import org.ofbiz.security.SecurityFactory;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 
 /** Implements a WebDAV servlet. The servlet simply forwards WebDAV requests
  * to a <code>RequestHandlerFactory</code> instance, whose class is specified
@@ -67,7 +67,7 @@ public class WebDavServlet extends Gener
             String delegatorName = context.getInitParameter("entityDelegatorName");
             this.delegator = DelegatorFactory.getDelegator(delegatorName);
             String dispatcherName = context.getInitParameter("localDispatcherName");
-            this.dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.delegator);
+            this.dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, this.delegator);
             this.security = SecurityFactory.getInstance(this.delegator);
             String factoryClassName = context.getInitParameter("requestHandlerFactoryClass");
             this.handlerFactory = (RequestHandlerFactory) loader.loadClass(factoryClassName).newInstance();

Modified: ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/guiapp/xui/XuiContainer.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/guiapp/xui/XuiContainer.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/guiapp/xui/XuiContainer.java (original)
+++ ofbiz/trunk/specialpurpose/pos/src/org/ofbiz/guiapp/xui/XuiContainer.java Tue Jul 24 09:16:26 2012
@@ -31,9 +31,9 @@ import org.ofbiz.base.container.Containe
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.service.ServiceContainer;
 
 public abstract class XuiContainer implements Container {
 
@@ -68,7 +68,7 @@ public abstract class XuiContainer imple
 
         // get the dispatcher
         String dispatcherName = ContainerConfig.getPropertyValue(cc, "dispatcher-name", "xui-dispatcher");
-        LocalDispatcher dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, delegator);
+        LocalDispatcher dispatcher = ServiceContainer.getLocalDispatcher(dispatcherName, delegator);
 
         // get the pre-defined session ID
         String xuiSessionId = ContainerConfig.getPropertyValue(cc, "xui-session-id", null);

Modified: ofbiz/trunk/specialpurpose/workflow/src/org/ofbiz/workflow/impl/WfExecutionObjectImpl.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/workflow/src/org/ofbiz/workflow/impl/WfExecutionObjectImpl.java?rev=1364952&r1=1364951&r2=1364952&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/workflow/src/org/ofbiz/workflow/impl/WfExecutionObjectImpl.java (original)
+++ ofbiz/trunk/specialpurpose/workflow/src/org/ofbiz/workflow/impl/WfExecutionObjectImpl.java Tue Jul 24 09:16:26 2012
@@ -42,8 +42,8 @@ import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.serialize.SerializeException;
 import org.ofbiz.entity.serialize.XmlSerializer;
 import org.ofbiz.service.DispatchContext;
-import org.ofbiz.service.GenericDispatcher;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceContainer;
 import org.ofbiz.workflow.AlreadySuspended;
 import org.ofbiz.workflow.CannotResume;
 import org.ofbiz.workflow.CannotStop;
@@ -592,7 +592,7 @@ public abstract class WfExecutionObjectI
      * @throws WfException
      */
     protected LocalDispatcher getDispatcher() throws WfException {
-        return GenericDispatcher.getLocalDispatcher(dispatcherName, getDelegator());
+        return ServiceContainer.getLocalDispatcher(dispatcherName, getDelegator());
     }
 
     private Map<String, Object> getContext() throws WfException {