diff --git a/akka-core/src/main/scala/actor/ActiveObject.scala b/akka-core/src/main/scala/actor/ActiveObject.scala
index ff103b3e81..a545f9f633 100644
--- a/akka-core/src/main/scala/actor/ActiveObject.scala
+++ b/akka-core/src/main/scala/actor/ActiveObject.scala
@@ -37,6 +37,7 @@ object Annotations {
final class ActiveObjectConfiguration {
private[akka] var _timeout: Long = Actor.TIMEOUT
private[akka] var _restartCallbacks: Option[RestartCallbacks] = None
+ private[akka] var _shutdownCallback: Option[ShutdownCallback] = None
private[akka] var _transactionRequired = false
private[akka] var _host: Option[InetSocketAddress] = None
private[akka] var _messageDispatcher: Option[MessageDispatcher] = None
@@ -51,6 +52,11 @@ final class ActiveObjectConfiguration {
this
}
+ def shutdownCallback(down: String) : ActiveObjectConfiguration = {
+ _shutdownCallback = Some(new ShutdownCallback(down))
+ this
+ }
+
def makeTransactionRequired() : ActiveObjectConfiguration = {
_transactionRequired = true;
this
@@ -153,25 +159,25 @@ object ActiveObject extends Logging {
private[actor] val AW_PROXY_PREFIX = "$$ProxiedByAW".intern
def newInstance[T](target: Class[T], timeout: Long): T =
- newInstance(target, actorOf(new Dispatcher(false, None)), None, timeout)
+ newInstance(target, actorOf(new Dispatcher(false)), None, timeout)
def newInstance[T](target: Class[T]): T =
- newInstance(target, actorOf(new Dispatcher(false, None)), None, Actor.TIMEOUT)
+ newInstance(target, actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long): T =
- newInstance(intf, target, actorOf(new Dispatcher(false, None)), None, timeout)
+ newInstance(intf, target, actorOf(new Dispatcher(false)), None, timeout)
def newInstance[T](intf: Class[T], target: AnyRef): T =
- newInstance(intf, target, actorOf(new Dispatcher(false, None)), None, Actor.TIMEOUT)
+ newInstance(intf, target, actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)
def newRemoteInstance[T](target: Class[T], timeout: Long, hostname: String, port: Int): T =
- newInstance(target, actorOf(new Dispatcher(false, None)), Some(new InetSocketAddress(hostname, port)), timeout)
+ newInstance(target, actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), timeout)
def newRemoteInstance[T](target: Class[T], hostname: String, port: Int): T =
- newInstance(target, actorOf(new Dispatcher(false, None)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)
+ newInstance(target, actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)
def newInstance[T](target: Class[T], config: ActiveObjectConfiguration): T = {
- val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks))
+ val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback))
if (config._messageDispatcher.isDefined) {
actor.dispatcher = config._messageDispatcher.get
}
@@ -179,7 +185,7 @@ object ActiveObject extends Logging {
}
def newInstance[T](intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration): T = {
- val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks))
+ val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback))
if (config._messageDispatcher.isDefined) {
actor.dispatcher = config._messageDispatcher.get
}
@@ -515,8 +521,6 @@ private[akka] sealed case class AspectInit(
def this(target: Class[_], actorRef: ActorRef, timeout: Long) = this(target, actorRef, None, timeout)
}
-// FIXME: add @shutdown callback to ActiveObject in which we get the Aspect through 'Aspects.aspectOf(MyAspect.class, targetInstance)' and shuts down the Dispatcher actor
-
/**
* AspectWerkz Aspect that is turning POJOs into Active Object.
* Is deployed on a 'per-instance' basis.
@@ -671,7 +675,7 @@ object Dispatcher {
* @author Jonas Bonér
*/
private[akka] class Dispatcher(transactionalRequired: Boolean,
- var restartCallbacks: Option[RestartCallbacks],
+ var restartCallbacks: Option[RestartCallbacks] = None,
var shutdownCallback: Option[ShutdownCallback] = None) extends Actor {
import Dispatcher._
@@ -805,12 +809,15 @@ private[akka] class Dispatcher(transactionalRequired: Boolean,
}
override def shutdown = {
- AspectInitRegistry.unregister(target.get);
try {
if (zhutdown.isDefined) {
zhutdown.get.invoke(target.get, ZERO_ITEM_OBJECT_ARRAY: _*)
}
- } catch { case e: InvocationTargetException => throw e.getCause }
+ } catch {
+ case e: InvocationTargetException => throw e.getCause
+ } finally {
+ AspectInitRegistry.unregister(target.get);
+ }
}
override def initTransactionalState = {
diff --git a/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala b/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala
index 406d463324..97b01c12ce 100644
--- a/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala
+++ b/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala
@@ -143,5 +143,13 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
case e: Exception => { /* test passed */ }
}
}
+
+ it("should shutdown non-supervised, non-initialized active object on ActiveObject.stop") {
+ val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated])
+ ActiveObject.stop(obj)
+ assert(!obj._pre)
+ assert(!obj._post)
+ assert(obj._down)
+ }
}
}
\ No newline at end of file
diff --git a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
index 9047b7c588..6eb0ec48fa 100644
--- a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
+++ b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
@@ -105,7 +105,7 @@
-
+
@@ -123,11 +123,23 @@
+
+
+
+
+
+ Shutdown callback method that is called during shut down.
+
+
+
+
+
+
diff --git a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala
index 4f6ea37148..d86567c5a6 100644
--- a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala
+++ b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala
@@ -1,22 +1,24 @@
/**
- * Copyright (C) 2009-2010 Scalable Solutions AB
+ * Copyright (C) 2009-2010 Scalable Solutions AB
*/
package se.scalablesolutions.akka.spring
import java.beans.PropertyDescriptor
-
import java.lang.reflect.Method
+
+import reflect.BeanProperty
+
import org.springframework.beans.BeanWrapperImpl
import org.springframework.beans.BeanWrapper
import org.springframework.beans.BeanUtils
-import org.springframework.util.ReflectionUtils
-import org.springframework.util.StringUtils
import org.springframework.beans.factory.BeanFactory
import org.springframework.beans.factory.config.AbstractFactoryBean
-import se.scalablesolutions.akka.actor.ActiveObject
-import reflect.BeanProperty
-import se.scalablesolutions.akka.config.ScalaConfig.RestartCallbacks
+import org.springframework.util.ReflectionUtils
+import org.springframework.util.StringUtils
+
+import se.scalablesolutions.akka.actor.{ActiveObjectConfiguration, ActiveObject}
+import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks}
import se.scalablesolutions.akka.dispatch.MessageDispatcher
import se.scalablesolutions.akka.util.Logging
@@ -25,6 +27,7 @@ import se.scalablesolutions.akka.util.Logging
*
* @author michaelkober
* @author Johan Rask
+ * @author Martin Krasser
*/
class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging {
import StringReflect._
@@ -36,6 +39,7 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging {
@BeanProperty var transactional: Boolean = false
@BeanProperty var pre: String = ""
@BeanProperty var post: String = ""
+ @BeanProperty var shutdown: String = ""
@BeanProperty var host: String = ""
@BeanProperty var port: Int = _
@BeanProperty var lifecycle: String = ""
@@ -67,15 +71,20 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging {
if (hasInterface) argumentList += "i"
if (hasDispatcher) argumentList += "d"
- setProperties(
- create(argumentList))
-}
+ setProperties(create(argumentList))
+ }
- /**
- * This method manages element by injecting either
- * values () and bean references ()
+ /**
+ * Stop the active object if it is a singleton.
*/
- private def setProperties(ref:AnyRef) : AnyRef = {
+ override def destroy = {
+ if(scope.equals(VAL_SCOPE_SINGLETON)) {
+ ActiveObject.stop(getObject)
+ }
+ super.destroy
+ }
+
+ private def setProperties(ref:AnyRef) : AnyRef = {
log.debug("Processing properties and dependencies for target class %s",target)
val beanWrapper = new BeanWrapperImpl(ref);
for(entry <- property.entryList) {
@@ -97,60 +106,45 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging {
ref
}
-// TODO: check if this works in 2.8 (type inferred to Nothing instead of AnyRef here)
-//
-// private[akka] def create(argList : String) : AnyRef = argList match {
-// case "r" => ActiveObject.newRemoteInstance(target.toClass, timeout, transactional, host, port, callbacks)
-// case "ri" => ActiveObject.newRemoteInstance(interface.toClass, target.toClass, timeout, transactional, host, port, callbacks)
-// case "rd" => ActiveObject.newRemoteInstance(target.toClass, timeout, transactional, dispatcherInstance, host, port, callbacks)
-// case "rid" => ActiveObject.newRemoteInstance(interface.toClass, target.toClass, timeout, transactional, dispatcherInstance, host, port, callbacks)
-// case "i" => ActiveObject.newInstance(interface.toClass, target.toClass, timeout, transactional, callbacks)
-// case "id" => ActiveObject.newInstance(interface.toClass, target.toClass, timeout, transactional, dispatcherInstance, callbacks)
-// case "d" => ActiveObject.newInstance(target.toClass, timeout, transactional, dispatcherInstance, callbacks)
-// case _ => ActiveObject.newInstance(target.toClass, timeout, transactional, callbacks)
-// }
-
private[akka] def create(argList : String) : AnyRef = {
if (argList == "r") {
- ActiveObject.newRemoteInstance(target.toClass, timeout, transactional, host, port, callbacks)
+ ActiveObject.newInstance(target.toClass, createConfig.makeRemote(host, port))
} else if (argList == "ri" ) {
- ActiveObject.newRemoteInstance(interface.toClass, aNewInstance(target.toClass), timeout, transactional, host, port, callbacks)
+ ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.makeRemote(host, port))
} else if (argList == "rd") {
- ActiveObject.newRemoteInstance(target.toClass, timeout, transactional, dispatcherInstance, host, port, callbacks)
+ ActiveObject.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
} else if (argList == "rid") {
- ActiveObject.newRemoteInstance(interface.toClass, aNewInstance(target.toClass), timeout, transactional, dispatcherInstance, host, port, callbacks)
+ ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
} else if (argList == "i") {
- ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), timeout, transactional, callbacks)
+ ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig)
} else if (argList == "id") {
- ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), timeout, transactional, dispatcherInstance, callbacks)
+ ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.dispatcher(dispatcherInstance))
} else if (argList == "d") {
- ActiveObject.newInstance(target.toClass, timeout, transactional, dispatcherInstance, callbacks)
+ ActiveObject.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance))
} else {
- ActiveObject.newInstance(target.toClass, timeout, transactional, callbacks)
+ ActiveObject.newInstance(target.toClass, createConfig)
}
}
- def aNewInstance[T <: AnyRef](clazz: Class[T]) : T = {
- clazz.newInstance().asInstanceOf[T]
- }
+ private[akka] def createConfig: ActiveObjectConfiguration = {
+ val config = new ActiveObjectConfiguration().timeout(timeout)
+ if (hasRestartCallbacks) config.restartCallbacks(pre, post)
+ if (hasShutdownCallback) config.shutdownCallback(shutdown)
+ if (transactional) config.makeTransactionRequired
+ config
+ }
- /**
- * create Option[RestartCallback]
- */
- private def callbacks: Option[RestartCallbacks] = {
- if (hasCallbacks) {
- val callbacks = new RestartCallbacks(pre, post)
- Some(callbacks)
- } else {
- None
- }
+ private[akka] def aNewInstance[T <: AnyRef](clazz: Class[T]) : T = {
+ clazz.newInstance().asInstanceOf[T]
}
private[akka] def isRemote = (host != null) && (!host.isEmpty)
private[akka] def hasInterface = (interface != null) && (!interface.isEmpty)
- private[akka] def hasCallbacks = ((pre != null) && !pre.isEmpty) || ((post != null) && !post.isEmpty)
+ private[akka] def hasRestartCallbacks = ((pre != null) && !pre.isEmpty) || ((post != null) && !post.isEmpty)
+
+ private[akka] def hasShutdownCallback = ((shutdown != null) && !shutdown.isEmpty)
private[akka] def hasDispatcher = (dispatcher != null) && (dispatcher.dispatcherType != null) && (!dispatcher.dispatcherType.isEmpty)
diff --git a/akka-spring/src/main/scala/ActiveObjectParser.scala b/akka-spring/src/main/scala/ActiveObjectParser.scala
index fc6b372720..8838360a44 100644
--- a/akka-spring/src/main/scala/ActiveObjectParser.scala
+++ b/akka-spring/src/main/scala/ActiveObjectParser.scala
@@ -13,6 +13,7 @@ import se.scalablesolutions.akka.actor.IllegalActorStateException
* Parser trait for custom namespace configuration for active-object.
* @author michaelkober
* @author Johan Rask
+ * @author Martin Krasser
*/
trait ActiveObjectParser extends BeanParser with DispatcherParser {
import AkkaSpringConfigurationTags._
@@ -25,7 +26,8 @@ trait ActiveObjectParser extends BeanParser with DispatcherParser {
def parseActiveObject(element: Element): ActiveObjectProperties = {
val objectProperties = new ActiveObjectProperties()
val remoteElement = DomUtils.getChildElementByTagName(element, REMOTE_TAG);
- val callbacksElement = DomUtils.getChildElementByTagName(element, RESTART_CALLBACKS_TAG);
+ val restartCallbacksElement = DomUtils.getChildElementByTagName(element, RESTART_CALLBACKS_TAG);
+ val shutdownCallbackElement = DomUtils.getChildElementByTagName(element, SHUTDOWN_CALLBACK_TAG);
val dispatcherElement = DomUtils.getChildElementByTagName(element, DISPATCHER_TAG)
val propertyEntries = DomUtils.getChildElementsByTagName(element,PROPERTYENTRY_TAG)
@@ -34,14 +36,18 @@ trait ActiveObjectParser extends BeanParser with DispatcherParser {
objectProperties.port = mandatory(remoteElement, PORT).toInt
}
- if (callbacksElement != null) {
- objectProperties.preRestart = callbacksElement.getAttribute(PRE_RESTART)
- objectProperties.postRestart = callbacksElement.getAttribute(POST_RESTART)
+ if (restartCallbacksElement != null) {
+ objectProperties.preRestart = restartCallbacksElement.getAttribute(PRE_RESTART)
+ objectProperties.postRestart = restartCallbacksElement.getAttribute(POST_RESTART)
if ((objectProperties.preRestart.isEmpty) && (objectProperties.preRestart.isEmpty)) {
throw new IllegalActorStateException("At least one of pre or post must be defined.")
}
}
+ if (shutdownCallbackElement != null) {
+ objectProperties.shutdown = shutdownCallbackElement.getAttribute("method")
+ }
+
if (dispatcherElement != null) {
val dispatcherProperties = parseDispatcher(dispatcherElement)
objectProperties.dispatcher = dispatcherProperties
diff --git a/akka-spring/src/main/scala/ActiveObjectProperties.scala b/akka-spring/src/main/scala/ActiveObjectProperties.scala
index ba4828e2f9..0f4b09d559 100644
--- a/akka-spring/src/main/scala/ActiveObjectProperties.scala
+++ b/akka-spring/src/main/scala/ActiveObjectProperties.scala
@@ -10,6 +10,7 @@ import AkkaSpringConfigurationTags._
/**
* Data container for active object configuration data.
* @author michaelkober
+ * @author Martin Krasser
*/
class ActiveObjectProperties {
var target: String = ""
@@ -18,10 +19,11 @@ class ActiveObjectProperties {
var transactional: Boolean = false
var preRestart: String = ""
var postRestart: String = ""
+ var shutdown: String = ""
var host: String = ""
var port: Int = _
var lifecycle: String = ""
- var scope:String = ""
+ var scope:String = VAL_SCOPE_SINGLETON
var dispatcher: DispatcherProperties = _
var propertyEntries = new PropertyEntries()
@@ -35,6 +37,7 @@ class ActiveObjectProperties {
builder.addPropertyValue(PORT, port)
builder.addPropertyValue(PRE_RESTART, preRestart)
builder.addPropertyValue(POST_RESTART, postRestart)
+ builder.addPropertyValue(SHUTDOWN, shutdown)
builder.addPropertyValue(TIMEOUT, timeout)
builder.addPropertyValue(TARGET, target)
builder.addPropertyValue(INTERFACE, interface)
diff --git a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
index 5e927ceba1..80a9f2e8d0 100644
--- a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
+++ b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
@@ -6,6 +6,7 @@ package se.scalablesolutions.akka.spring
/**
* XML configuration tags.
* @author michaelkober
+ * @author Martin Krasser
*/
object AkkaSpringConfigurationTags {
@@ -20,6 +21,7 @@ object AkkaSpringConfigurationTags {
// active-object sub tags
val RESTART_CALLBACKS_TAG = "restart-callbacks"
+ val SHUTDOWN_CALLBACK_TAG = "shutdown-callback"
val REMOTE_TAG = "remote"
// superivision sub tags
@@ -45,6 +47,7 @@ object AkkaSpringConfigurationTags {
val PORT = "port"
val PRE_RESTART = "pre"
val POST_RESTART = "post"
+ val SHUTDOWN = "shutdown"
val LIFECYCLE = "lifecycle"
val SCOPE = "scope"
diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java
index 37953173ec..e8adaa38e7 100644
--- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java
+++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java
@@ -1,9 +1,22 @@
package se.scalablesolutions.akka.spring;
+import se.scalablesolutions.akka.actor.annotation.shutdown;
+
public class SampleBean {
+ public boolean down;
+
+ public SampleBean() {
+ down = false;
+ }
+
public String foo(String s) {
return "hello " + s;
}
-
+
+ @shutdown
+ public void shutdown() {
+ down = true;
+ }
+
}
diff --git a/akka-spring/src/test/resources/appContext.xml b/akka-spring/src/test/resources/appContext.xml
index 5648fa2fdf..bcb1a7f525 100644
--- a/akka-spring/src/test/resources/appContext.xml
+++ b/akka-spring/src/test/resources/appContext.xml
@@ -6,16 +6,19 @@
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.akkasource.org/schema/akka
http://scalablesolutions.se/akka/akka-0.10.xsd">
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala
index d8bb29ed3e..dc48ecc4b1 100644
--- a/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala
+++ b/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala
@@ -54,8 +54,8 @@ class ActiveObjectBeanDefinitionParserTest extends Spec with ShouldMatchers {
val props = parser.parseActiveObject(dom(xml).getDocumentElement);
assert(props != null)
- assert(props.dispatcher.dispatcherType == "thread-based")
-}
+ assert(props.dispatcher.dispatcherType === "thread-based")
+ }
it("should parse remote ActiveObjects configuration") {
val xml =
val props = parser.parseActiveObject(dom(xml).getDocumentElement);
assert(props != null)
- assert(props.host == "com.some.host")
- assert(props.port == 9999)
+ assert(props.host === "com.some.host")
+ assert(props.port === 9999)
}
}
}
diff --git a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala
index f1c11d0eee..9e1c014ce3 100644
--- a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala
+++ b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala
@@ -70,5 +70,21 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers {
val target:ResourceEditor = ctx.getBean("bean").asInstanceOf[ResourceEditor]
assert(target.getSource === "someString")
}
+
+ it("should stop the created active object when scope is singleton and the context is closed") {
+ var ctx = new ClassPathXmlApplicationContext("appContext.xml");
+ val target = ctx.getBean("bean-singleton").asInstanceOf[SampleBean]
+ assert(!target.down)
+ ctx.close
+ assert(target.down)
+ }
+
+ it("should not stop the created active object when scope is prototype and the context is closed") {
+ var ctx = new ClassPathXmlApplicationContext("appContext.xml");
+ val target = ctx.getBean("bean-prototype").asInstanceOf[SampleBean]
+ assert(!target.down)
+ ctx.close
+ assert(!target.down)
+ }
}
}
diff --git a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
index e0344ae4fb..ffc1f7a95d 100644
--- a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
+++ b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
@@ -49,11 +49,21 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
parser.parseSupervisor(createSupervisorElement, builder);
val supervised = builder.getBeanDefinition.getPropertyValues.getPropertyValue("supervised").getValue.asInstanceOf[List[ActiveObjectProperties]]
assert(supervised != null)
- expect(3) { supervised.length }
+ expect(4) { supervised.length }
val iterator = supervised.iterator
- expect("foo.bar.Foo") { iterator.next.target }
- expect("foo.bar.Bar") { iterator.next.target }
- expect("foo.bar.MyPojo") { iterator.next.target }
+ val prop1 = iterator.next
+ val prop2 = iterator.next
+ val prop3 = iterator.next
+ val prop4 = iterator.next
+ expect("foo.bar.Foo") { prop1.target }
+ expect("foo.bar.Bar") { prop2.target }
+ expect("foo.bar.MyPojo") { prop3.target }
+ expect("foo.bar.MyPojo") { prop4.target }
+ expect("preRestart") { prop3.preRestart }
+ expect("postRestart") { prop3.postRestart }
+ expect("shutdown") { prop4.shutdown }
+ expect("permanent") { prop1.lifecycle }
+ expect("temporary") { prop4.lifecycle }
}
it("should throw IllegalArgumentException on missing mandatory attributes") {
@@ -87,6 +97,9 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
+
+
+
dom(xml).getDocumentElement