Author: dblevins
Date: Thu Aug 7 17:28:56 2008
New Revision: 683774
URL: http://svn.apache.org/viewvc?rev=683774&view=rev
Log:
OPENEJB-840: Singleton @Startup load-on-startup
OPENEJB-841: Singleton @DependsOn load ordering
Forgot to implement the shutdown (PreDestroy) part. Working now and updated
the test case.
Modified:
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/core/singleton/SingletonContainer.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
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=683774&r1=683773&r2=683774&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 17:28:56 2008
@@ -555,30 +555,7 @@
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();
- }
- });
+ allDeployments = sort(allDeployments);
// now that everything is configured, deploy to the container
for (DeploymentInfo deployment : allDeployments) {
@@ -641,6 +618,33 @@
}
}
+ private static List<DeploymentInfo> sort(List<DeploymentInfo> deployments)
{
+ // 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(deployments, 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.
+ return References.sort(deployments, new
References.Visitor<DeploymentInfo>(){
+ public String getName(DeploymentInfo t) {
+ return (String) t.getDeploymentID();
+ }
+
+ public Set<String> getReferences(DeploymentInfo t) {
+ return t.getDependsOn();
+ }
+ });
+ }
+
public void destroyApplication(String filePath) throws UndeployException,
NoSuchApplicationException {
AppInfo appInfo = deployedApplications.remove(filePath);
if (appInfo == null) {
@@ -675,7 +679,7 @@
}
// get all of the ejb deployments
- List<CoreDeploymentInfo> deployments = new
ArrayList<CoreDeploymentInfo>();
+ List<DeploymentInfo> deployments = new ArrayList<DeploymentInfo>();
for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) {
for (EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) {
String deploymentId = beanInfo.ejbDeploymentId;
@@ -688,6 +692,32 @@
}
}
+ // Just as with startup we need to get things in an
+ // order that respects the singleton @DependsOn information
+ // Theoreticlly if a Singleton depends on something in its
+ // @PostConstruct, it can depend on it in its @PreDestroy.
+ // Therefore we want to make sure that if A dependsOn B,
+ // that we destroy A first then B so that B will still be
+ // usable in the @PreDestroy method of A.
+
+ // Sort them into the original starting order
+ deployments = sort(deployments);
+ // reverse that to get the stopping order
+ Collections.reverse(deployments);
+
+ for (DeploymentInfo deployment : deployments) {
+ String deploymentID = deployment.getDeploymentID() + "";
+ try {
+ Container container = deployment.getContainer();
+ container.undeploy(deployment);
+ deployment.setContainer(null);
+ } catch (Throwable t) {
+ undeployException.getCauses().add(new Exception("bean: " +
deploymentID + ": " + t.getMessage(), t));
+ } finally {
+ ((CoreDeploymentInfo)deployment).setDestroyed(true);
+ }
+ }
+
// get the client ids
List<String> clientIds = new ArrayList<String>();
for (ClientInfo clientInfo : appInfo.clients) {
@@ -695,7 +725,7 @@
}
// Clear out naming for all components first
- for (CoreDeploymentInfo deployment : deployments) {
+ for (DeploymentInfo deployment : deployments) {
String deploymentID = deployment.getDeploymentID() + "";
try {
containerSystem.removeDeploymentInfo(deployment);
@@ -734,18 +764,6 @@
undeployException.getCauses().add(new Exception("Unable to prune
openejb/Deployments and openejb/ejb namespaces, this could cause future
deployments to fail.", e));
}
- for (CoreDeploymentInfo deployment : deployments) {
- String deploymentID = deployment.getDeploymentID() + "";
- try {
- Container container = deployment.getContainer();
- container.undeploy(deployment);
- deployment.setContainer(null);
- } catch (Throwable t) {
- undeployException.getCauses().add(new Exception("bean: " +
deploymentID + ": " + t.getMessage(), t));
- } finally {
- deployment.setDestroyed(true);
- }
- }
deployments.clear();
for (String clientId : clientIds) {
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=683774&r1=683773&r2=683774&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 17:28:56 2008
@@ -120,7 +120,12 @@
if (deploymentInfo.isLoadOnStartup()){
try {
ThreadContext callContext = new ThreadContext(deploymentInfo,
null);
- instanceManager.getInstance(callContext);
+ ThreadContext old = ThreadContext.enter(callContext);
+ try {
+ instanceManager.getInstance(callContext);
+ } finally{
+ ThreadContext.exit(old);
+ }
} catch (OpenEJBException e) {
throw new OpenEJBException("Singleton startup failed:
"+deploymentInfo.getDeploymentID(), e);
}
@@ -132,6 +137,13 @@
}
private void undeploy(CoreDeploymentInfo deploymentInfo) {
+ ThreadContext threadContext = new ThreadContext(deploymentInfo, null);
+ ThreadContext old = ThreadContext.enter(threadContext);
+ try {
+ instanceManager.freeInstance(threadContext);
+ } finally{
+ ThreadContext.exit(old);
+ }
instanceManager.undeploy(deploymentInfo);
EjbTimerService timerService = deploymentInfo.getEjbTimerService();
if (timerService != null) {
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java?rev=683774&r1=683773&r2=683774&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java
Thu Aug 7 17:28:56 2008
@@ -261,12 +261,14 @@
return new SingletonContext(transactionManager, securityService);
}
- // TODO: Call on system shutdown
- private void freeInstance(ThreadContext callContext, Instance instance) {
+ public void freeInstance(ThreadContext callContext) {
+ CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
+ Data data = (Data) deploymentInfo.getContainerData();
+ Instance instance = data.instance;
+
try {
callContext.setCurrentOperation(Operation.PRE_DESTROY);
callContext.setCurrentAllowedStates(SingletonContext.getStates());
- CoreDeploymentInfo deploymentInfo =
callContext.getDeploymentInfo();
Method remove = instance.bean instanceof SessionBean?
deploymentInfo.getCreateMethod(): null;
@@ -275,7 +277,7 @@
interceptorStack.invoke();
} catch (Throwable re) {
- logger.error("The bean instance " + instance + " threw a system
exception:" + re, re);
+ logger.error("Singleton shutdown failed:
"+deploymentInfo.getDeploymentID(), re);
}
}
Modified:
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=683774&r1=683773&r2=683774&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/singleton/DependsOnTest.java
Thu Aug 7 17:28:56 2008
@@ -22,6 +22,7 @@
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.assembler.classic.AppInfo;
import org.apache.openejb.config.ConfigurationFactory;
import org.apache.openejb.config.ValidationFailedException;
import org.apache.openejb.config.ValidationFailure;
@@ -31,6 +32,7 @@
import org.apache.openejb.OpenEJBException;
import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import javax.ejb.DependsOn;
import javax.ejb.Singleton;
import javax.ejb.Startup;
@@ -67,14 +69,24 @@
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(One.class));
ejbJar.addEnterpriseBean(new SingletonBean(Four.class));
+ ejbJar.addEnterpriseBean(new SingletonBean(Three.class));
+ // startup and trigger @PostConstruct
assembler.createApplication(config.configureApplication(ejbJar));
assertEquals(expected(four, three, two, one), actual);
+
+ actual.clear();
+
+ // startup and trigger @PreDestroy
+ for (AppInfo appInfo : assembler.getDeployedApplications()) {
+ assembler.destroyApplication(appInfo.jarPath);
+ }
+
+ assertEquals(expected(one, two, three, four), actual);
}
public void testNoSuchEjb() throws Exception {
@@ -157,7 +169,8 @@
public static class One implements Bean {
@PostConstruct
- public void construct() {
+ @PreDestroy
+ public void callback() {
actual.add(one);
}
}
@@ -168,7 +181,8 @@
public static class Two implements Bean {
@PostConstruct
- public void construct() {
+ @PreDestroy
+ public void callback() {
actual.add(two);
}
}
@@ -179,7 +193,8 @@
public static class Three implements Bean {
@PostConstruct
- public void construct() {
+ @PreDestroy
+ public void callback() {
actual.add(three);
}
}
@@ -189,7 +204,8 @@
public static class Four implements Bean {
@PostConstruct
- public void construct() {
+ @PreDestroy
+ public void callback() {
actual.add(four);
}
}