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") {