[exo-jcr-commits] exo-jcr SVN: r3995 - in kernel/trunk/exo.kernel.container/src: main/java/org/exoplatform/container/jmx and 2 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Feb 18 09:19:44 EST 2011


Author: nfilotto
Date: 2011-02-18 09:19:44 -0500 (Fri, 18 Feb 2011)
New Revision: 3995

Modified:
   kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java
   kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/jmx/MX4JComponentAdapter.java
   kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java
   kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/test-exo-container.xml
Log:
EXOJCR-1197: Bug fixed by adding a dependencies resolution context in which we register the dependencies that are currently resolved, this is necessary to resolve cyclic dependencies. The bug was due to the fact that the UserPortalConfigService depends on the OrganizationService and the OrganizationService depends indirectly through a plugin on UserPortalConfigListener, moreover the OrganizationService has a plugin that depends on the NodeHierarchyCreator. If the UserPortalConfigService is started before the NodeHierarchyCreator, we got this exception because to solve the cyclic dependency issue, we have to break the chain of dependencies which makes the OrganizationService starts before the NodeHierarchyCreator.

Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java	2011-02-18 13:38:33 UTC (rev 3994)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java	2011-02-18 14:19:44 UTC (rev 3995)
@@ -78,6 +78,12 @@
    }
 
    static Log log = ExoLogger.getLogger("exo.kernel.container.ExoContainer");
+   
+   /**
+    * Context used to keep in memory the components that are currently being created.
+    * This context is used to prevent cyclic resolution due to component plugins.
+    */
+   private final ThreadLocal<Map<Object, Object>> depResolutionCtx = new ThreadLocal<Map<Object, Object>>();
 
    private Map<String, ComponentLifecyclePlugin> componentLifecylePlugin_ =
       new HashMap<String, ComponentLifecyclePlugin>();
@@ -308,7 +314,7 @@
             }
             else
             {
-               args[i] = getComponentInstanceOfType(parameters[i]);
+               args[i] = getComponentInstanceOfTypeInternal(parameters[i]);
                if (args[i] == null)
                {
                   satisfied = false;
@@ -332,4 +338,59 @@
       ConfigurationManager cm = (ConfigurationManager)getComponentInstanceOfType(ConfigurationManager.class);
       return cm == null ? null : cm.getConfiguration();
    }
+   
+   /**
+    * Add the component corresponding to the given key, to the dependency resolution
+    * context
+    * @param key The key of the component to add to the context
+    * @param component The instance of the component to add to the context
+    */
+   public void addComponentToCtx(Object key, Object component)
+   {
+      Map<Object, Object> map = depResolutionCtx.get();
+      if (map == null)
+      {
+         map = new HashMap<Object, Object>();
+         depResolutionCtx.set(map);
+      }
+      map.put(key, component);
+   }
+   
+   /**
+    * Remove the component corresponding to the given key, from the dependency resolution
+    * context
+    * @param key The key of the component to remove from the context
+    */
+   public void removeComponentFromCtx(Object key)
+   {
+      Map<Object, Object> map = depResolutionCtx.get();
+      if (map != null)
+      {
+         map.remove(key);
+         if (map.isEmpty())
+         {
+            depResolutionCtx.set(null);
+         }
+      }
+   }
+   
+   /**
+    * Try to get the component from the dependency resolution context and if it cannot be found
+    * it will try to get it from the method <code>getComponentInstanceOfType</code>
+    * @param componentType the type of the component to find
+    * @return the instance of the component corresponding to the given component type
+    */
+   private Object getComponentInstanceOfTypeInternal(Class componentType)
+   {
+      Map<Object, Object> map = depResolutionCtx.get();
+      if (map != null)
+      {
+         Object result = map.get(componentType);
+         if (result != null)
+         {
+            return result;
+         }
+      }
+      return getComponentInstanceOfType(componentType);
+   }
 }

Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/jmx/MX4JComponentAdapter.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/jmx/MX4JComponentAdapter.java	2011-02-18 13:38:33 UTC (rev 3994)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/jmx/MX4JComponentAdapter.java	2011-02-18 14:19:44 UTC (rev 3995)
@@ -100,26 +100,27 @@
                // to component plugins
                return instance_;
             }
+            exocontainer.addComponentToCtx(getComponentKey(), instance);
+            if (debug)
+               log.debug("==> create  component : " + instance_);
+            if (component != null && component.getComponentPlugins() != null)
+            {
+               addComponentPlugin(debug, instance, component.getComponentPlugins(), exocontainer);
+            }
+            ExternalComponentPlugins ecplugins = manager.getConfiguration().getExternalComponentPlugins(componentKey);
+            if (ecplugins != null)
+            {
+               addComponentPlugin(debug, instance, ecplugins.getComponentPlugins(), exocontainer);
+            }
+            // check if component implement the ComponentLifecycle
+            if (instance instanceof ComponentLifecycle)
+            {
+               ComponentLifecycle lc = (ComponentLifecycle)instance;
+               lc.initComponent(exocontainer);
+            }
             instance_ = instance;
          }
 
-         if (debug)
-            log.debug("==> create  component : " + instance_);
-         if (component != null && component.getComponentPlugins() != null)
-         {
-            addComponentPlugin(debug, instance_, component.getComponentPlugins(), exocontainer);
-         }
-         ExternalComponentPlugins ecplugins = manager.getConfiguration().getExternalComponentPlugins(componentKey);
-         if (ecplugins != null)
-         {
-            addComponentPlugin(debug, instance_, ecplugins.getComponentPlugins(), exocontainer);
-         }
-         // check if component implement the ComponentLifecycle
-         if (instance_ instanceof ComponentLifecycle)
-         {
-            ComponentLifecycle lc = (ComponentLifecycle)instance_;
-            lc.initComponent(exocontainer);
-         }
       }
       catch (Exception ex)
       {
@@ -132,7 +133,10 @@
          }
          throw new RuntimeException(msg, ex);
       }
-
+      finally
+      {
+         exocontainer.removeComponentFromCtx(getComponentKey());
+      }
       return instance_;
    }
 

Modified: kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java	2011-02-18 13:38:33 UTC (rev 3994)
+++ kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java	2011-02-18 14:19:44 UTC (rev 3995)
@@ -26,6 +26,7 @@
 import org.picocontainer.PicoInitializationException;
 import org.picocontainer.PicoIntrospectionException;
 import org.picocontainer.PicoVisitor;
+import org.picocontainer.Startable;
 import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
 
 import java.net.URL;
@@ -119,6 +120,18 @@
       assertEquals(a, b.a);
    }
    
+   public void testStartOrder()
+   {
+      final RootContainer container = createRootContainer("test-exo-container.xml", "testStartOrder");
+      C0 c0 = (C0)container.getComponentInstanceOfType(C0.class);
+      assertNotNull(c0);
+      C1 c1 = (C1)container.getComponentInstanceOfType(C1.class);
+      assertNotNull(c1);
+      C2 c2 = (C2)container.getComponentInstanceOfType(C2.class);
+      assertNotNull(c2);
+      assertTrue(c1.started);      
+   }   
+   
    public void testCache()
    {
       URL rootURL = getClass().getResource("test-exo-container.xml");
@@ -560,4 +573,101 @@
       {
       }
    }
+   
+   public static class C0 implements Startable
+   {
+      C1 c1;
+      public C0(C1 c1)
+      {
+         this.c1 = c1;
+      }
+
+      /**
+       * @see org.picocontainer.Startable#start()
+       */
+      public void start()
+      {
+      }
+
+      /**
+       * @see org.picocontainer.Startable#stop()
+       */
+      public void stop()
+      {
+      }
+      
+   }
+   
+   public static class C1 implements Startable
+   {
+      public boolean started;
+      
+      P p;
+      
+      /**
+       * @see org.picocontainer.Startable#start()
+       */
+      public void start()
+      {
+         try
+         {
+            p.init();
+            this.started = true;
+         }
+         catch (Exception e)
+         {
+            e.printStackTrace();
+         }
+      }
+
+      /**
+       * @see org.picocontainer.Startable#stop()
+       */
+      public void stop()
+      {         
+      }
+      
+      public void add(P p)
+      {
+         this.p = p;
+      }
+   }
+   public static class P extends BaseComponentPlugin
+   {
+      public C0 c0;
+      public C1 c1;
+      public C2 c2;
+      public P(C0 c0, C1 c1, C2 c2)
+      {
+         this.c0 = c0;
+         this.c1 = c1;
+         this.c2 = c2;
+      }
+      
+      public void init()
+      {
+         if (!c2.started)
+            throw new IllegalStateException("C2 should be started");
+      }
+   }
+   
+   public static class C2 implements Startable
+   {
+      public boolean started;
+      
+      /**
+       * @see org.picocontainer.Startable#start()
+       */
+      public void start()
+      {
+         started = true;
+      }
+
+      /**
+       * @see org.picocontainer.Startable#stop()
+       */
+      public void stop()
+      {         
+      }
+   }   
 }

Modified: kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/test-exo-container.xml
===================================================================
--- kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/test-exo-container.xml	2011-02-18 13:38:33 UTC (rev 3994)
+++ kernel/trunk/exo.kernel.container/src/test/resources/org/exoplatform/container/test-exo-container.xml	2011-02-18 14:19:44 UTC (rev 3995)
@@ -58,4 +58,20 @@
 			</component-plugin>
 		</component-plugins>
 	</component>
+	<component profiles="testStartOrder">
+		<type>org.exoplatform.container.TestExoContainer$C0</type>
+	</component>
+	<component profiles="testStartOrder">
+		<type>org.exoplatform.container.TestExoContainer$C1</type>
+		<component-plugins>
+			<component-plugin>
+				<name>testStartOrder</name>
+				<set-method>add</set-method>
+				<type>org.exoplatform.container.TestExoContainer$P</type>
+			</component-plugin>
+		</component-plugins>
+	</component>
+	<component profiles="testStartOrder">
+		<type>org.exoplatform.container.TestExoContainer$C2</type>
+	</component>
 </configuration>
\ No newline at end of file



More information about the exo-jcr-commits mailing list