You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2008/08/07 09:50:48 UTC

svn commit: r683531 - in /openejb/trunk/openejb3: api/ejb31-api-experimental/src/main/java/javax/ejb/ container/openejb-core/src/main/java/org/apache/openejb/ container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/ container/openejb-...

Author: dblevins
Date: Thu Aug  7 00:50:47 2008
New Revision: 683531

URL: http://svn.apache.org/viewvc?rev=683531&view=rev
Log:
OPENEJB-840: Singleton @Startup load-on-startup
OPENEJB-841: Singleton @DependsOn load ordering

Added:
    openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/DependsOn.java
    openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Startup.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/rules/CheckDependsOn.java
    openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
    openejb/trunk/openejb3/server/openejb-ejbd/src/test/java/org/apache/openejb/server/ejbd/KeepAilveTest.java
Modified:
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarBuilder.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanInfo.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppValidator.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/JndiEncInfoBuilder.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/VmDeploymentManager.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
    openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/References.java
    openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties
    openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/SingletonContainerTest.java
    openejb/trunk/openejb3/container/openejb-jee/src/main/java/org/apache/openejb/jee/SessionBean.java

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/DependsOn.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/DependsOn.java?rev=683531&view=auto
==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/DependsOn.java (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/DependsOn.java Thu Aug  7 00:50:47 2008
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.ejb;
+
+@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.TYPE})
+@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
+public @interface DependsOn {
+    String[] value();
+}

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Startup.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Startup.java?rev=683531&view=auto
==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Startup.java (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Startup.java Thu Aug  7 00:50:47 2008
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.ejb;
+
+@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.TYPE})
+@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
+public @interface Startup {
+}
\ No newline at end of file

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/DeploymentInfo.java Thu Aug  7 00:50:47 2008
@@ -24,6 +24,7 @@
 import java.util.Collection;
 import java.util.Map;
 import java.util.List;
+import java.util.Set;
 import javax.naming.Context;
 
 public interface DeploymentInfo {
@@ -147,5 +148,9 @@
 
     public <T> T set(Class<T> type, T value);
 
-    public boolean retainIfExeption(Method removeMethod); 
+    public boolean retainIfExeption(Method removeMethod);
+
+    public boolean isLoadOnStartup();
+
+    public Set<String> getDependsOn();
 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Thu Aug  7 00:50:47 2008
@@ -31,6 +31,10 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.TreeMap;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Set;
+import java.util.LinkedHashSet;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
@@ -83,6 +87,8 @@
 import org.apache.openejb.util.Messages;
 import org.apache.openejb.util.OpenEJBErrorHandler;
 import org.apache.openejb.util.SafeToolkit;
+import org.apache.openejb.util.References;
+import org.apache.openejb.util.CircularReferencesException;
 import org.apache.openejb.util.proxy.ProxyFactory;
 import org.apache.openejb.util.proxy.ProxyManager;
 import org.apache.xbean.recipe.ObjectRecipe;
@@ -489,6 +495,8 @@
                 }
             }
 
+            List<DeploymentInfo> allDeployments = new ArrayList<DeploymentInfo>();
+
             // EJB
             EjbJarBuilder ejbJarBuilder = new EjbJarBuilder(props, classLoader);
             for (EjbJarInfo ejbJar : appInfo.ejbJars) {
@@ -544,11 +552,42 @@
                     }
                 }
 
-                // now that everything is configured, deploy to the container
-                ejbJarBuilder.deploy(deployments);
+                allDeployments.addAll(deployments.values());
+            }
+
+            // Sort all the singletons to the back of the list.  We want to make sure
+            // all non-singletons are created first so that if a singleton refers to them
+            // they are available.  We have to do this as @DependsOn only points to other
+            // Singleton beans.  If it listed non-Singlton beans, then we wouldn't need to
+            // pre-sort.
+            Collections.sort(allDeployments, new Comparator<DeploymentInfo>(){
+                public int compare(DeploymentInfo a, DeploymentInfo b) {
+                    int aa = (a.getComponentType() == BeanType.SINGLETON) ? 1 : 0;
+                    int bb = (b.getComponentType() == BeanType.SINGLETON) ? 1 : 0;
+                    return aa - bb;
+                }
+            });
+
+            // Sort all the beans with references to the back of the list.  Beans
+            // without references to ther beans will be deployed first.
+            References.sort(allDeployments, new References.Visitor<DeploymentInfo>(){
+                public String getName(DeploymentInfo t) {
+                    return (String) t.getDeploymentID();
+                }
+
+                public Set<String> getReferences(DeploymentInfo t) {
+                    return t.getDependsOn();
+                }
+            });
 
-                for (EnterpriseBeanInfo beanInfo : ejbJar.enterpriseBeans) {
-                    logger.info("createApplication.createdEjb", beanInfo.ejbDeploymentId, beanInfo.ejbName, beanInfo.containerId);
+            // now that everything is configured, deploy to the container
+            for (DeploymentInfo deployment : allDeployments) {
+                try {
+                    Container container = deployment.getContainer();
+                    container.deploy(deployment);
+                    logger.info("createApplication.createdEjb", deployment.getDeploymentID(), deployment.getEjbName(), container.getContainerID());
+                } catch (Throwable t) {
+                    throw new OpenEJBException("Error deploying '"+deployment.getEjbName()+"'.  Exception: "+t.getClass()+": "+t.getMessage(), t);
                 }
             }
 

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarBuilder.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarBuilder.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarBuilder.java Thu Aug  7 00:50:47 2008
@@ -66,14 +66,5 @@
         }
         return deployments;
     }
-    
-    public void deploy(HashMap<String, DeploymentInfo> deployments) throws OpenEJBException {
-        for (DeploymentInfo deployment : deployments.values()) {
-            try {
-                deployment.getContainer().deploy(deployment);
-            } catch (Throwable t) {
-                throw new OpenEJBException("Error deploying '"+deployment.getEjbName()+"'.  Exception: "+t.getClass()+": "+t.getMessage(), t);
-            }
-        }
-    }
+
 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanBuilder.java Thu Aug  7 00:50:47 2008
@@ -211,6 +211,8 @@
 
         if (ejbType == BeanType.SINGLETON) {
             deployment.setBeanManagedConcurrency("Bean".equalsIgnoreCase(bean.concurrencyType));
+            deployment.getDependsOn().addAll(bean.dependsOn);
+            deployment.setLoadOnStartup(bean.loadOnStartup);
         }
 
         if (ejbType.isEntity()) {

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanInfo.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanInfo.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EnterpriseBeanInfo.java Thu Aug  7 00:50:47 2008
@@ -68,4 +68,6 @@
     public List<JndiNameInfo> jndiNamess = new ArrayList<JndiNameInfo>();
 
     public List<String> jndiNames = new ArrayList<String>();
+    public boolean loadOnStartup;
+    public final List<String> dependsOn = new ArrayList<String>() ;
 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java Thu Aug  7 00:50:47 2008
@@ -121,6 +121,8 @@
 import javax.ejb.Singleton;
 import javax.ejb.ConcurrencyManagement;
 import javax.ejb.ConcurrencyManagementType;
+import javax.ejb.Startup;
+import javax.ejb.DependsOn;
 import javax.interceptor.ExcludeClassInterceptors;
 import javax.interceptor.ExcludeDefaultInterceptors;
 import javax.interceptor.Interceptors;
@@ -151,6 +153,7 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.Collections;
 
 /**
  * @version $Rev$ $Date$
@@ -662,8 +665,8 @@
                 }
             }
             for (FacesConfig facesConfig: webModule.getFacesConfigs()) {
-            	for(FacesManagedBean bean: facesConfig.getManagedBean()){
-            		String managedBeanClass = bean.getManagedBeanClass().trim();
+                for(FacesManagedBean bean: facesConfig.getManagedBean()){
+                    String managedBeanClass = bean.getManagedBeanClass().trim();
                     if (managedBeanClass != null) {
                         try {
                             Class clazz = classLoader.loadClass(managedBeanClass);
@@ -672,7 +675,7 @@
                             throw new OpenEJBException("Unable to load JSF managed bean class: " + managedBeanClass, e);
                         }
                     }
-            	}
+                }
             }
             ClassFinder inheritedClassFinder = createInheritedClassFinder(classes.toArray(new Class<?>[classes.size()]));
 
@@ -871,6 +874,20 @@
                             } else {
                                 checkAttributes(new ConcurrencyAttributeHandler(assemblyDescriptor, ejbName), ejbName, ejbModule, classFinder, "invalidConcurrencyAttribute");
                             }
+
+                            if (!sessionBean.hasLoadOnStartup()){
+                                Startup startup = getInheritableAnnotation(clazz, Startup.class);
+                                sessionBean.setLoadOnStartup(startup != null);
+                            }
+
+                            if (sessionBean.getDependsOn() == null) {
+                                DependsOn dependsOn = getInheritableAnnotation(clazz, DependsOn.class);
+                                if (dependsOn != null) {
+                                    sessionBean.setDependsOn(dependsOn.value());
+                                } else {
+                                    sessionBean.setDependsOn(Collections.EMPTY_LIST);
+                                }
+                            }
                         }
                     }
                 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java Thu Aug  7 00:50:47 2008
@@ -39,6 +39,8 @@
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Messages;
 import org.apache.openejb.util.MakeTxLookup;
+import org.apache.openejb.util.References;
+import org.apache.openejb.util.CircularReferencesException;
 import org.apache.openejb.jee.oejb3.EjbDeployment;
 import org.apache.openejb.jee.jpa.unit.Persistence;
 import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
@@ -69,6 +71,8 @@
 import java.util.Properties;
 import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Set;
+import java.util.LinkedHashSet;
 import java.net.URL;
 import java.io.File;
 import java.io.IOException;
@@ -149,6 +153,7 @@
         // Create the JNDI info builder
         JndiEncInfoBuilder jndiEncInfoBuilder = new JndiEncInfoBuilder(appInfo);
 
+        List<EnterpriseBeanInfo> beans = new ArrayList<EnterpriseBeanInfo>();
         // Build the JNDI tree for each ejb
         for (EjbModule ejbModule : appModule.getEjbModules()) {
 
@@ -157,6 +162,7 @@
             Map<String, EnterpriseBean> beanData = ejbModule.getEjbJar().getEnterpriseBeansByEjbName();
 
             for (EnterpriseBeanInfo beanInfo : ejbJar.enterpriseBeans) {
+                beans.add(beanInfo);
 
                 // Get the ejb-jar.xml object
                 EnterpriseBean enterpriseBean = beanData.get(beanInfo.ejbName);
@@ -165,9 +171,28 @@
                 JndiEncInfo jndi = jndiEncInfoBuilder.build(enterpriseBean, beanInfo.ejbName, ejbJar.moduleId);
 
                 beanInfo.jndiEnc = jndi;
+
+
+                jndiEncInfoBuilder.buildDependsOnRefs(ejbModule, enterpriseBean, beanInfo, ejbJar.moduleId);
             }
         }
 
+        // Check for circular references in Singleton @DependsOn
+        try {
+            References.sort(beans, new References.Visitor<EnterpriseBeanInfo>(){
+                public String getName(EnterpriseBeanInfo bean) {
+                    return bean.ejbDeploymentId;
+                }
+
+                public Set<String> getReferences(EnterpriseBeanInfo bean) {
+                    return new LinkedHashSet<String>(bean.dependsOn);
+                }
+            });
+        } catch (CircularReferencesException e) {
+            List<List> circuits = e.getCircuits();
+
+        }
+
         //
         //  Application Clients
         //

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppValidator.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppValidator.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppValidator.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/AppValidator.java Thu Aug  7 00:50:47 2008
@@ -36,6 +36,7 @@
 import org.apache.openejb.config.rules.CheckCallbacks;
 import org.apache.openejb.config.rules.CheckInjectionTargets;
 import org.apache.openejb.config.rules.CheckPersistenceRefs;
+import org.apache.openejb.config.rules.CheckDependsOn;
 import org.apache.openejb.util.Messages;
 import org.apache.openejb.util.OpenEjbVersion;
 
@@ -98,7 +99,8 @@
                 new CheckCallbacks(),
                 new CheckAssemblyBindings(),
                 new CheckInjectionTargets(),
-                new CheckPersistenceRefs()
+                new CheckPersistenceRefs(),
+                new CheckDependsOn()
         };
         return rules;
     }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java Thu Aug  7 00:50:47 2008
@@ -472,6 +472,9 @@
             bean = new SingletonBeanInfo();
             ConcurrencyType type = s.getConcurrencyType();
             bean.concurrencyType = (type != null) ? type.toString() : ConcurrencyType.CONTAINER.toString();
+            bean.loadOnStartup = s.getLoadOnStartup();
+            // See JndiEncInfoBuilder.buildDependsOnRefs for processing of DependsOn 
+            // bean.dependsOn.addAll(s.getDependsOn());
         } else {
             bean = new StatelessBeanInfo();
         }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/JndiEncInfoBuilder.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/JndiEncInfoBuilder.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/JndiEncInfoBuilder.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/JndiEncInfoBuilder.java Thu Aug  7 00:50:47 2008
@@ -53,6 +53,9 @@
 import org.apache.openejb.jee.ResourceRef;
 import org.apache.openejb.jee.ServiceRef;
 import org.apache.openejb.jee.EjbReference;
+import org.apache.openejb.jee.SessionBean;
+import org.apache.openejb.jee.EnterpriseBean;
+import org.apache.openejb.jee.SessionType;
 import org.apache.openejb.util.LogCategory;
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.util.Messages;
@@ -382,6 +385,65 @@
         return infos;
     }
 
+    public void buildDependsOnRefs(EjbModule module, EnterpriseBean enterpriseBean, EnterpriseBeanInfo beanInfo, String moduleId) throws OpenEJBException {
+        if (!(enterpriseBean instanceof SessionBean)) return;
+
+        SessionBean sessionBean = (SessionBean) enterpriseBean;
+
+        if (sessionBean.getSessionType() != SessionType.SINGLETON) return;
+
+        URI moduleUri = null;
+        if (moduleId != null) {
+            try {
+                moduleUri = new URI(moduleId);
+            } catch (URISyntaxException e) {
+                throw new OpenEJBException("Illegal moduleId " + moduleId, e);
+            }
+        }
+
+        EjbResolver ejbResolver = getEjbResolver(moduleId);
+
+        for (String ejbName : sessionBean.getDependsOn()) {
+            String deploymentId = ejbResolver.resolve(new SimpleRef(ejbName), moduleUri);
+            if (deploymentId != null) {
+                beanInfo.dependsOn.add(deploymentId);
+            }
+        }
+
+    }
+
+
+    private static class SimpleRef implements EjbResolver.Reference {
+        private final String name;
+
+        public SimpleRef(String name) {
+            this.name = name;
+        }
+
+        public String getEjbLink() {
+            return name;
+        }
+
+        public String getHome() {
+            return null;
+        }
+
+        public String getInterface() {
+            return null;
+        }
+
+        public String getMappedName() {
+            return null;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public EjbResolver.Type getRefType() {
+            return EjbResolver.Type.UNKNOWN;
+        }
+    }
     /**
      * The assembler package cannot have a dependency on org.apache.openejb.jee
      * so we simply have a trimmed down copy of the org.apache.openejb.jee.EjbReference interface

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/VmDeploymentManager.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/VmDeploymentManager.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/VmDeploymentManager.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/VmDeploymentManager.java Thu Aug  7 00:50:47 2008
@@ -79,7 +79,7 @@
     private boolean deployerLocal;
 
     public VmDeploymentManager() {
-        String openejbHome = System.getProperty("openejb.home", "target/openejb-3.0.0-SNAPSHOT");
+        String openejbHome = System.getProperty("openejb.home", "target/openejb-3.1-SNAPSHOT");
         File openejbHomeDir = new File(openejbHome);
         if (!openejbHomeDir.exists()) {
             throw new IllegalArgumentException("OpenEJB home dir does not exist: " + openejbHomeDir);

Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/rules/CheckDependsOn.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/rules/CheckDependsOn.java?rev=683531&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/rules/CheckDependsOn.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/config/rules/CheckDependsOn.java Thu Aug  7 00:50:47 2008
@@ -0,0 +1,160 @@
+/**
+ * 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.apache.openejb.config.rules;
+
+import org.apache.openejb.config.AppModule;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.jee.EnterpriseBean;
+import org.apache.openejb.jee.SessionBean;
+import org.apache.openejb.jee.SessionType;
+import org.apache.openejb.util.CircularReferencesException;
+import org.apache.openejb.util.Join;
+import org.apache.openejb.util.LinkResolver;
+import org.apache.openejb.util.References;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class CheckDependsOn extends ValidationBase {
+
+    public void validate(AppModule appModule) {
+        module = appModule;
+
+        LinkResolver<Bean> app = new LinkResolver<Bean>();
+
+        for (EjbModule ejbModule : appModule.getEjbModules()) {
+
+            String moduleId = ejbModule.getModuleId();
+
+            URI moduleUri = null;
+            if (moduleId != null) {
+                try {
+                    moduleUri = new URI(moduleId);
+                } catch (URISyntaxException e) {
+                    return;
+                }
+            }
+
+            Resolver<Bean> resolver = new Resolver(app, new LinkResolver<Bean>());
+
+            for (EnterpriseBean bean : ejbModule.getEjbJar().getEnterpriseBeans()) {
+                Bean b = new Bean(bean, ejbModule, moduleUri, resolver);
+
+                resolver.module.add(ejbModule.getModuleId(), bean.getEjbName(), b);
+
+                resolver.app.add(ejbModule.getModuleId(), bean.getEjbName(), b);
+
+            }
+
+        }
+
+        boolean missingBeans = false;
+        for (Bean bean : app.values()) {
+            EnterpriseBean enterpriseBean = bean.bean;
+
+            if (!(enterpriseBean instanceof SessionBean)) continue;
+
+            SessionBean sessionBean = (SessionBean) enterpriseBean;
+
+            if (sessionBean.getSessionType() != SessionType.SINGLETON) continue;
+
+            for (String ejbName : sessionBean.getDependsOn()) {
+                Bean referee = bean.resolveLink(ejbName);
+                if (referee == null) {
+                    bean.module.getValidation().fail(enterpriseBean.getEjbName(), "dependsOn.noSuchEjb", ejbName);
+                    missingBeans = true;
+                } else {
+                    bean.dependsOn.add(referee);
+                }
+            }
+        }
+
+        if (missingBeans) return;
+
+        try {
+            References.sort(new ArrayList<Bean>(app.values()), new References.Visitor<Bean>() {
+                public String getName(Bean t) {
+                    return t.getId();
+                }
+
+                public Set<String> getReferences(Bean t) {
+                    LinkedHashSet<String> refs = new LinkedHashSet<String>();
+                    for (Bean bean : t.dependsOn) {
+                        refs.add(bean.getId());
+                    }
+                    return refs;
+                }
+            });
+        } catch (CircularReferencesException e) {
+            for (List<Bean> circuit : e.getCircuits()) {
+                List<String> ejbNames = new ArrayList<String>(circuit.size());
+                for (Bean bean : circuit) {
+                    ejbNames.add(bean.bean.getEjbName());
+                }
+                fail("EAR", "dependsOn.circuit", Join.join(" -> ", ejbNames), ejbNames.get(0));
+            }
+        }
+
+    }
+
+    public static class Resolver<T> {
+        private final LinkResolver<T> module;
+        private final LinkResolver<T> app;
+
+        public Resolver(LinkResolver<T> app, LinkResolver<T> module) {
+            this.app = app;
+            this.module = module;
+        }
+
+        public T resolveLink(String link, URI moduleUri) {
+            T value = module.resolveLink(link, moduleUri);
+            if (value != null) return value;
+
+            return app.resolveLink(link, moduleUri);
+        }
+    }
+
+    public static class Bean {
+        private final URI moduleUri;
+        private final EnterpriseBean bean;
+        private final ArrayList<Bean> dependsOn = new ArrayList<Bean>();
+        private final EjbModule module;
+        private final Resolver<Bean> resolver;
+
+        public Bean(EnterpriseBean bean, EjbModule module, URI moduleUri, Resolver<Bean> resolver) {
+            this.bean = bean;
+            this.module = module;
+            this.moduleUri = moduleUri;
+            this.resolver = resolver;
+        }
+
+        public Bean resolveLink(String ejbName) {
+            return resolver.resolveLink(ejbName, moduleUri);
+        }
+
+        public String getId() {
+            return toString();
+        }
+    }
+}

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/CoreDeploymentInfo.java Thu Aug  7 00:50:47 2008
@@ -26,6 +26,7 @@
 import java.util.Set;
 import java.util.ArrayList;
 import java.util.TreeSet;
+import java.util.LinkedHashSet;
 import javax.ejb.EJBHome;
 import javax.ejb.EJBLocalHome;
 import javax.ejb.EJBLocalObject;
@@ -92,6 +93,8 @@
 
     private final List<Method> removeMethods = new ArrayList<Method>();
 
+    private final Set<String> dependsOn = new LinkedHashSet<String>();
+
     private Method ejbTimeout;
     private EjbTimerService ejbTimerService;
 
@@ -133,6 +136,7 @@
     private Index<EntityManagerFactory,Map> extendedEntityManagerFactories;
     private final Map<Class, InterfaceType> interfaces = new HashMap<Class, InterfaceType>();
     private final Map<Class, ExceptionType> exceptions = new HashMap<Class, ExceptionType>();
+    private boolean loadOnStartup;
 
     public Class getInterface(InterfaceType interfaceType) {
         switch(interfaceType){
@@ -1112,4 +1116,16 @@
         this.serviceEndpointInterface = serviceEndpointInterface;
         mapObjectInterface(serviceEndpointInterface);
     }
+
+    public boolean isLoadOnStartup() {
+        return loadOnStartup;
+    }
+
+    public void setLoadOnStartup(boolean loadOnStartup) {
+        this.loadOnStartup = loadOnStartup;
+    }
+
+    public Set<String> getDependsOn() {
+        return dependsOn;
+    }
 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java Thu Aug  7 00:50:47 2008
@@ -116,6 +116,15 @@
         if (timerService != null) {
             timerService.start();
         }
+
+        if (deploymentInfo.isLoadOnStartup()){
+            try {
+                ThreadContext callContext = new ThreadContext(deploymentInfo, null);
+                instanceManager.getInstance(callContext);
+            } catch (OpenEJBException e) {
+                throw new OpenEJBException("Singleton startup failed: "+deploymentInfo.getDeploymentID(), e);
+            }
+        }
     }
 
     public void undeploy(DeploymentInfo info) {

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/References.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/References.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/References.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/References.java Thu Aug  7 00:50:47 2008
@@ -77,17 +77,10 @@
             if (n.refernceCount == 0) {
                 // if the node is totally isolated (no in or out refs),
                 // move it directly to the finished list, so they are first
-
                 if (n.references.size() == 0) {
-
                     sortedNodes.add(n);
-
-
                 } else {
-
-
                     leafNodes.add(n);
-
                 }
             }
         }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/resources/org/apache/openejb/config/rules/Messages.properties Thu Aug  7 00:50:47 2008
@@ -742,3 +742,13 @@
 1.xml.businessLocal.notInterface = The value of <business-local> is not an interface
 2.xml.businessLocal.notInterface = The value of <business-local> is not an interface: {0}
 3.xml.businessLocal.notInterface = The <business-local> element of the ejb-jar.xml must be an interface.  Classes, abstract classes or enums are not allowed.  Either convert {0} to an interface or remove the related <business-local> xml tag from your ejb-jar.xml
+
+# fail(enterpriseBean.getEjbName(), "dependsOn.noSuchEjb", ejbName);
+1.dependsOn.noSuchEjb = Singleton @DependsOn refers to non-existant EJB:
+2.dependsOn.noSuchEjb = Singleton @DependsOn refers to non-existant EJB: {0}
+3.dependsOn.noSuchEjb = The @DependsOn annotation or <depends-on> descriptor data for this Singeton bean lists an EJB "{0}" which does not exist in any of the modules of the ear.
+
+# fail("EAR", "dependsOn.circuit", Join.join(" -> ", ejbNames), ejbNames.get(0));
+1.dependsOn.circuit = Singleton circular dependency detected
+2.dependsOn.circuit = Singleton circular dependency detected: {0}
+3.dependsOn.circuit = A Singleton circular dependency has been detected in the application.  Bean "{1}" refers to one or more other singleton beans via @DependsOn which directly or indirectly refer back to bean "{1}".  This circle must be broken befor the application can be built: {0}

Added: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java?rev=683531&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java Thu Aug  7 00:50:47 2008
@@ -0,0 +1,198 @@
+/**
+ * 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.apache.openejb.core.singleton;
+
+import junit.framework.TestCase;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.SingletonSessionContainerInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.ValidationFailedException;
+import org.apache.openejb.config.ValidationFailure;
+import org.apache.openejb.core.ivm.naming.InitContextFactory;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.SingletonBean;
+import org.apache.openejb.OpenEJBException;
+
+import javax.annotation.PostConstruct;
+import javax.ejb.DependsOn;
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.naming.NamingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.io.IOException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DependsOnTest extends TestCase {
+    private static final String one = "one";
+    private static final String two = "two";
+    private static final String three = "three";
+    private static final String four = "four";
+
+    public void test() throws Exception {
+
+        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());
+
+        Assembler assembler = new Assembler();
+        ConfigurationFactory config = new ConfigurationFactory();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+        // containers
+        assembler.createContainer(config.configureService(SingletonSessionContainerInfo.class));
+
+        actual.clear();
+
+        EjbJar ejbJar = new EjbJar();
+
+        ejbJar.addEnterpriseBean(new SingletonBean(One.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Two.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Three.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Four.class));
+
+        assembler.createApplication(config.configureApplication(ejbJar));
+
+        assertEquals(expected(four, three, two, one), actual);
+    }
+
+    public void testNoSuchEjb() throws Exception {
+
+        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());
+
+        Assembler assembler = new Assembler();
+        ConfigurationFactory config = new ConfigurationFactory();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+        // containers
+        assembler.createContainer(config.configureService(SingletonSessionContainerInfo.class));
+
+
+        EjbJar ejbJar = new EjbJar();
+
+        ejbJar.addEnterpriseBean(new SingletonBean(One.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Two.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Three.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Four.class)).setDependsOn("Five");
+
+        try {
+            config.configureApplication(ejbJar);
+            fail("Validation should have found a circular reference");
+        } catch (ValidationFailedException e) {
+            ValidationFailure[] failures = e.getFailures();
+            assertEquals(1, failures.length);
+            assertEquals("dependsOn.noSuchEjb", failures[0].getMessageKey());
+        }
+    }
+
+    public void testCircuit() throws Exception {
+
+        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());
+
+        Assembler assembler = new Assembler();
+        ConfigurationFactory config = new ConfigurationFactory();
+
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+        // containers
+        assembler.createContainer(config.configureService(SingletonSessionContainerInfo.class));
+
+
+        EjbJar ejbJar = new EjbJar();
+
+        ejbJar.addEnterpriseBean(new SingletonBean(One.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Two.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Three.class));
+        ejbJar.addEnterpriseBean(new SingletonBean(Four.class)).setDependsOn("One");
+
+        try {
+            config.configureApplication(ejbJar);
+            fail("Validation should have found a circular reference");
+        } catch (ValidationFailedException e) {
+            ValidationFailure[] failures = e.getFailures();
+            assertEquals(1, failures.length);
+            assertEquals("dependsOn.circuit", failures[0].getMessageKey());
+        }
+    }
+
+    private List<String> expected(String... strings) {
+        return Arrays.asList(strings);
+    }
+
+    private final static List<String> actual = new ArrayList<String>();
+
+    public static interface Bean {
+
+    }
+
+    @Singleton
+    @Startup
+    @DependsOn("Two")
+    public static class One implements Bean {
+
+        @PostConstruct
+        public void construct() {
+            actual.add(one);
+        }
+    }
+
+    @Singleton
+    @Startup
+    @DependsOn("Three")
+    public static class Two implements Bean {
+
+        @PostConstruct
+        public void construct() {
+            actual.add(two);
+        }
+    }
+
+    @Singleton
+    @Startup
+    @DependsOn("Four")
+    public static class Three implements Bean {
+
+        @PostConstruct
+        public void construct() {
+            actual.add(three);
+        }
+    }
+
+    @Singleton
+    @Startup
+    public static class Four implements Bean {
+
+        @PostConstruct
+        public void construct() {
+            actual.add(four);
+        }
+    }
+
+
+}

Modified: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/SingletonContainerTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/SingletonContainerTest.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/SingletonContainerTest.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/SingletonContainerTest.java Thu Aug  7 00:50:47 2008
@@ -93,11 +93,7 @@
         assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
 
         // containers
-        SingletonSessionContainerInfo singletonContainerInfo = config.configureService(SingletonSessionContainerInfo.class);
-//        singletonContainerInfo.properties.setProperty("TimeOut", "10");
-//        singletonContainerInfo.properties.setProperty("PoolSize", "0");
-//        singletonContainerInfo.properties.setProperty("StrictPooling", "false");
-        assembler.createContainer(singletonContainerInfo);
+        assembler.createContainer(config.configureService(SingletonSessionContainerInfo.class));
 
         // Setup the descriptor information
 

Modified: openejb/trunk/openejb3/container/openejb-jee/src/main/java/org/apache/openejb/jee/SessionBean.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-jee/src/main/java/org/apache/openejb/jee/SessionBean.java?rev=683531&r1=683530&r2=683531&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-jee/src/main/java/org/apache/openejb/jee/SessionBean.java (original)
+++ openejb/trunk/openejb3/container/openejb-jee/src/main/java/org/apache/openejb/jee/SessionBean.java Thu Aug  7 00:50:47 2008
@@ -25,6 +25,7 @@
 import javax.xml.bind.annotation.XmlID;
 import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import java.util.ArrayList;
@@ -32,6 +33,7 @@
 import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.Map;
+import java.util.Arrays;
 
 
 /**
@@ -109,6 +111,7 @@
         "serviceEndpoint",
         "ejbClass",
         "sessionType",
+        "loadOnStartup",
         "timeoutMethod",
         "initMethod",
         "removeMethod",
@@ -129,7 +132,8 @@
         "postActivate",
         "prePassivate",
         "securityRoleRef",
-        "securityIdentity"
+        "securityIdentity",
+        "dependsOn"
         })
 public class SessionBean implements EnterpriseBean, RemoteBean, Session, TimerConsumer {
     @XmlTransient
@@ -200,6 +204,14 @@
     protected List<SecurityRoleRef> securityRoleRef;
     @XmlElement(name = "security-identity")
     protected SecurityIdentity securityIdentity;
+
+    @XmlElement(name = "load-on-startup")
+    protected Boolean loadOnStartup;
+
+    @XmlElementWrapper(name = "depends-on")
+    @XmlElement(name = "ejb-name")
+    protected List<String> dependsOn;
+
     @XmlAttribute
     @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
     @XmlID
@@ -217,7 +229,7 @@
     public String getJndiConsumerName() {
         return ejbName;
     }
-    
+
     @XmlElement(name = "description", required = true)
     public Text[] getDescriptions() {
         return description.toArray();
@@ -645,6 +657,30 @@
         this.securityIdentity = value;
     }
 
+    public List<String> getDependsOn() {
+        return dependsOn;
+    }
+
+    public void setDependsOn(String... ejbNames) {
+        setDependsOn(Arrays.asList(ejbNames));
+    }
+
+    public void setDependsOn(List<String> ejbNames) {
+        this.dependsOn = new ArrayList(ejbNames);
+    }
+
+    public boolean hasLoadOnStartup() {
+        return loadOnStartup != null;
+    }
+
+    public boolean getLoadOnStartup() {
+        return loadOnStartup != null && loadOnStartup;
+    }
+
+    public void setLoadOnStartup(boolean loadOnStartup) {
+        this.loadOnStartup = loadOnStartup;
+    }
+
     public String getId() {
         return id;
     }

Added: openejb/trunk/openejb3/server/openejb-ejbd/src/test/java/org/apache/openejb/server/ejbd/KeepAilveTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-ejbd/src/test/java/org/apache/openejb/server/ejbd/KeepAilveTest.java?rev=683531&view=auto
==============================================================================
--- openejb/trunk/openejb3/server/openejb-ejbd/src/test/java/org/apache/openejb/server/ejbd/KeepAilveTest.java (added)
+++ openejb/trunk/openejb3/server/openejb-ejbd/src/test/java/org/apache/openejb/server/ejbd/KeepAilveTest.java Thu Aug  7 00:50:47 2008
@@ -0,0 +1,211 @@
+/**
+ * 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.apache.openejb.server.ejbd;
+
+import junit.framework.TestCase;
+import junit.framework.Assert;
+
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.openejb.OpenEJB;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatelessBean;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.server.ServicePool;
+import org.apache.openejb.server.ServiceDaemon;
+import org.apache.openejb.core.ServerFederation;
+
+import javax.naming.NamingException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.ejb.Remote;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class KeepAilveTest extends TestCase {
+    public void _testPool() throws Exception {
+        int threads = 2;
+        ThreadPoolExecutor pool = new ThreadPoolExecutor(threads, threads, 120, TimeUnit.SECONDS, new LinkedBlockingQueue());
+
+        Runnable runnable = new Runnable(){
+            public void run() {
+                waitOneSecond();
+            }
+        };
+
+        print(pool);
+
+        for (int i = 0; i < 10 ; i++) {
+            System.out.println("" + i);
+            pool.execute(runnable);
+            print(pool);
+        }
+
+        waitOneSecond();
+
+        for (int i = 0; i < 10 ; i++) {
+            print(pool);
+            waitOneSecond();
+        }
+        print(pool);
+        fail();
+    }
+
+    private void waitOneSecond() {
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void print(ThreadPoolExecutor pool) {
+        System.out.println("==========================================");
+        int activeCount = pool.getActiveCount();
+        System.out.println("activeCount = " + activeCount);
+        int corePoolSize = pool.getCorePoolSize();
+        System.out.println("corePoolSize = " + corePoolSize);
+        int largestPoolSize = pool.getLargestPoolSize();
+        System.out.println("largestPoolSize = " + largestPoolSize);
+        int maximumPoolSize = pool.getMaximumPoolSize();
+        System.out.println("maximumPoolSize = " + maximumPoolSize);
+        int poolSize = pool.getPoolSize();
+        System.out.println("poolSize = " + poolSize);
+        int queueSize = pool.getQueue().size();
+        System.out.println("queueSize = " + queueSize);
+        long taskCount = pool.getTaskCount();
+        System.out.println("taskCount = " + taskCount);
+        System.out.println("==========================================");
+    }
+
+    public void test() throws Exception {
+        
+    }
+    public void _test() throws Exception {
+        EjbServer ejbServer = new EjbServer();
+        KeepAliveServer keepAliveServer = new KeepAliveServer(ejbServer);
+
+        Properties initProps = new Properties();
+        initProps.setProperty("openejb.deployments.classpath.include", "");
+        initProps.setProperty("openejb.deployments.classpath.filter.descriptors", "true");
+        OpenEJB.init(initProps, new ServerFederation());
+        ejbServer.init(new Properties());
+
+        ServicePool pool = new ServicePool(keepAliveServer, "ejbd", 10);
+        ServiceDaemon serviceDaemon = new ServiceDaemon(pool, 0, "localhost");
+        serviceDaemon.start();
+
+        try {
+
+            int port = serviceDaemon.getPort();
+
+            Assembler assembler = SystemInstance.get().getComponent(Assembler.class);
+            ConfigurationFactory config = new ConfigurationFactory();
+
+            EjbJar ejbJar = new EjbJar();
+            ejbJar.addEnterpriseBean(new StatelessBean(EchoBean.class));
+
+            assembler.createApplication(config.configureApplication(ejbJar));
+
+            // good creds
+
+            int threads = 1;
+            CountDownLatch latch = new CountDownLatch(threads);
+
+            for (int i = 0; i < threads; i++) {
+                Client client = new Client(latch, i, port);
+                thread(client, false);
+            }
+
+            assertTrue(latch.await(60, TimeUnit.SECONDS));
+        } finally {
+            serviceDaemon.stop();
+            OpenEJB.destroy();
+        }
+    }
+
+    public static void thread(Runnable runnable, boolean daemon) {
+        Thread thread = new Thread(runnable);
+        thread.setDaemon(daemon);
+        thread.start();
+    }
+
+    public static class Client implements Runnable {
+
+        private final Echo echo;
+        private final CountDownLatch latch;
+        private final int id;
+
+        public Client(CountDownLatch latch, int i, int port) throws NamingException {
+            this.latch = latch;
+            this.id = i;
+
+            Properties props = new Properties();
+            props.put("java.naming.factory.initial", "org.apache.openejb.client.RemoteInitialContextFactory");
+            props.put("java.naming.provider.url", "ejbd://127.0.0.1:" + port +"?"+id);
+            Context context = new InitialContext(props);
+
+            this.echo = (Echo) context.lookup("EchoBeanRemote");
+        }
+
+        public void run() {
+
+            try {
+                int count = 10;
+                for (; count >= 0; count--){
+                    String message = count + " bottles of beer on the wall";
+
+//                    Thread.currentThread().setName("client-"+id+": "+count);
+
+                    String response = echo.echo(message);
+                    Assert.assertEquals(message, reverse(response));
+                    try {
+                        Thread.sleep(5000);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }
+            } finally {
+                latch.countDown();
+            }
+        }
+
+        private Object reverse(String s) {
+            return new StringBuilder(s).reverse().toString();
+        }
+    }
+
+
+    public static class EchoBean implements Echo {
+        public String echo(String s) {
+//            System.out.println(s);
+            return new StringBuilder(s).reverse().toString();
+        }
+    }
+
+    @Remote
+    public static interface Echo {
+        public String echo(String s);
+    }
+}