From 2e7847c0585fa76e53d954b52d2d45da5b3c0e25 Mon Sep 17 00:00:00 2001 From: Johan Rask Date: Wed, 7 Jul 2010 11:12:16 +0200 Subject: [PATCH 1/2] Added support for springs @PostConstruct and @PreDestroy --- .../main/scala/ActiveObjectFactoryBean.scala | 37 +++++++++++++++---- .../scalablesolutions/akka/spring/Pojo.java | 24 +++++++++++- .../akka/spring/PojoInf.java | 12 +++++- .../scala/ActiveObjectFactoryBeanTest.scala | 4 ++ 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala index 03f0f50df3..e379041322 100644 --- a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala +++ b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala @@ -6,7 +6,8 @@ package se.scalablesolutions.akka.spring import java.beans.PropertyDescriptor import java.lang.reflect.Method - +import javax.annotation.PreDestroy +import javax.annotation.PostConstruct import reflect.BeanProperty import org.springframework.beans.BeanWrapperImpl @@ -82,16 +83,37 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging w if (hasInterface) argumentList += "i" if (hasDispatcher) argumentList += "d" - setProperties(create(argumentList)) + postConstruct( + setProperties( + create(argumentList))) + } /** * Stop the active object if it is a singleton. + * It will call the instance destroy method before + * stopping the active object. */ override def destroyInstance(instance:AnyRef) { + for(method <- instance.getClass.getMethods) { + if(method.isAnnotationPresent(classOf[PreDestroy])) { + method.invoke(instance) + } + } ActiveObject.stop(instance) } - + + private def postConstruct(ref:AnyRef) : AnyRef = { + // Invoke postConstruct method if any + for(method <- ref.getClass.getMethods) { + if(method.isAnnotationPresent(classOf[PostConstruct])) { + method.invoke(ref) + } + } + ref + } + + private def setProperties(ref:AnyRef) : AnyRef = { if(hasSetDependecies) { return ref @@ -119,8 +141,6 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging w throw new AkkaBeansException("Either property@ref or property@value must be set on property element") } } - //un-set so next bean can be managed - hasSetDependecies = false ref } @@ -144,6 +164,8 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging w } } + + private[akka] def createConfig: ActiveObjectConfiguration = { val config = new ActiveObjectConfiguration().timeout(timeout) if (hasRestartCallbacks) config.restartCallbacks(pre, post) @@ -153,10 +175,11 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging w } def aNewInstance[T <: AnyRef](clazz: Class[T]) : T = { var ref = clazz.newInstance().asInstanceOf[T] - setProperties(ref) + postConstruct( + setProperties(ref)) hasSetDependecies = true ref -} + } private[akka] def isRemote = (host != null) && (!host.isEmpty) diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java index 42e1e393e7..3df506a290 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java @@ -2,12 +2,16 @@ package se.scalablesolutions.akka.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; +import javax.annotation.PreDestroy; +import javax.annotation.PostConstruct; public class Pojo implements PojoInf,ApplicationContextAware { private String string; private boolean gotApplicationContext = false; + private boolean preDestroyInvoked = false; + private boolean postConstructInvoked = false; public boolean gotApplicationContext() { return gotApplicationContext; @@ -23,5 +27,23 @@ public class Pojo implements PojoInf,ApplicationContextAware { public String getString() { return string; } - + + @PreDestroy + public void destroy(){ + preDestroyInvoked = true; + } + @PostConstruct + public void create() { + postConstructInvoked = true; + } + + + public boolean isPreDestroyInvoked() { + return preDestroyInvoked; + } + + public boolean isPostConstructInvoked() { + return postConstructInvoked; +} + } diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java index db31841f17..c4e3e55c47 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java @@ -1,8 +1,18 @@ package se.scalablesolutions.akka.spring; +import javax.annotation.PreDestroy; +import javax.annotation.PostConstruct; + public interface PojoInf { public String getString(); public boolean gotApplicationContext(); - + public boolean isPreDestroyInvoked(); + public boolean isPostConstructInvoked(); + + @PreDestroy + public void destroy(); + + @PostConstruct + public void create(); } diff --git a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala index 5055fb6184..6a0b9701f6 100644 --- a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala +++ b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala @@ -72,8 +72,12 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { val pojoInf = ctx.getBean("pojoInf").asInstanceOf[PojoInf]; println("pojoInf = " + pojoInf.getString) + Thread.sleep(200) + assert(pojoInf.isPostConstructInvoked) assert(pojoInf.getString == "akka rocks") assert(pojoInf.gotApplicationContext) + ctx.close + assert(pojoInf.isPreDestroyInvoked) } it("should stop the created active object when scope is singleton and the context is closed") { From 7da92cbd4e3e32eca715eae0d3efc408e8008b1c Mon Sep 17 00:00:00 2001 From: Johan Rask Date: Wed, 7 Jul 2010 13:31:50 +0200 Subject: [PATCH 2/2] removed @PreDestroy functionality --- .../src/main/scala/ActiveObjectFactoryBean.scala | 16 ++++++++-------- .../se/scalablesolutions/akka/spring/Pojo.java | 10 ---------- .../scalablesolutions/akka/spring/PojoInf.java | 4 ---- .../test/scala/ActiveObjectFactoryBeanTest.scala | 2 -- 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala index e379041322..6f62c5a8c4 100644 --- a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala +++ b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala @@ -91,18 +91,18 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging w /** * Stop the active object if it is a singleton. - * It will call the instance destroy method before - * stopping the active object. */ override def destroyInstance(instance:AnyRef) { - for(method <- instance.getClass.getMethods) { - if(method.isAnnotationPresent(classOf[PreDestroy])) { - method.invoke(instance) - } - } ActiveObject.stop(instance) } - + + /** + * Invokes any method annotated with @PostConstruct + * When interfaces are specified, this method is invoked both on the + * target instance and on the active object, so a developer is free do decide + * where the annotation should be. If no interface is specified it is only invoked + * on the active object + */ private def postConstruct(ref:AnyRef) : AnyRef = { // Invoke postConstruct method if any for(method <- ref.getClass.getMethods) { diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java index 3df506a290..04995b75c8 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java @@ -10,7 +10,6 @@ public class Pojo implements PojoInf,ApplicationContextAware { private String string; private boolean gotApplicationContext = false; - private boolean preDestroyInvoked = false; private boolean postConstructInvoked = false; public boolean gotApplicationContext() { @@ -28,19 +27,10 @@ public class Pojo implements PojoInf,ApplicationContextAware { return string; } - @PreDestroy - public void destroy(){ - preDestroyInvoked = true; - } @PostConstruct public void create() { postConstructInvoked = true; } - - - public boolean isPreDestroyInvoked() { - return preDestroyInvoked; - } public boolean isPostConstructInvoked() { return postConstructInvoked; diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java index c4e3e55c47..70d64245db 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java @@ -7,12 +7,8 @@ public interface PojoInf { public String getString(); public boolean gotApplicationContext(); - public boolean isPreDestroyInvoked(); public boolean isPostConstructInvoked(); - @PreDestroy - public void destroy(); - @PostConstruct public void create(); } diff --git a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala index 6a0b9701f6..68dac8e97c 100644 --- a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala +++ b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala @@ -76,8 +76,6 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { assert(pojoInf.isPostConstructInvoked) assert(pojoInf.getString == "akka rocks") assert(pojoInf.gotApplicationContext) - ctx.close - assert(pojoInf.isPreDestroyInvoked) } it("should stop the created active object when scope is singleton and the context is closed") {