From fc9c83396c109dc4d74822b9e8713aaacefc7b1a Mon Sep 17 00:00:00 2001 From: Paul Pacheco Date: Sun, 7 Nov 2010 22:23:32 -0600 Subject: [PATCH] Add a ref="..." attribute to untyped-actor and typed-actor so that akka can use spring created beans --- .../akka/spring/akka-1.0-SNAPSHOT.xsd | 18 +++++++++++-- .../src/main/scala/ActorFactoryBean.scala | 25 ++++++++++++++----- akka-spring/src/main/scala/ActorParser.scala | 3 ++- .../src/main/scala/ActorProperties.scala | 2 ++ .../scala/AkkaSpringConfigurationTags.scala | 1 + .../src/test/resources/typed-actor-config.xml | 8 ++++++ .../test/resources/untyped-actor-config.xml | 5 ++++ .../scala/TypedActorSpringFeatureTest.scala | 8 ++++++ .../scala/UntypedActorSpringFeatureTest.scala | 8 ++++++ 9 files changed, 69 insertions(+), 9 deletions(-) diff --git a/akka-spring/src/main/resources/akka/spring/akka-1.0-SNAPSHOT.xsd b/akka-spring/src/main/resources/akka/spring/akka-1.0-SNAPSHOT.xsd index 1014e7e592..ea438ebc88 100644 --- a/akka-spring/src/main/resources/akka/spring/akka-1.0-SNAPSHOT.xsd +++ b/akka-spring/src/main/resources/akka/spring/akka-1.0-SNAPSHOT.xsd @@ -145,13 +145,20 @@ - + Name of the implementation class. + + + + Bean instance behind the actor + + + @@ -191,13 +198,20 @@ - + Name of the implementation class. + + + + Bean instance behind the actor + + + diff --git a/akka-spring/src/main/scala/ActorFactoryBean.scala b/akka-spring/src/main/scala/ActorFactoryBean.scala index d0fac73596..c5014d6e18 100644 --- a/akka-spring/src/main/scala/ActorFactoryBean.scala +++ b/akka-spring/src/main/scala/ActorFactoryBean.scala @@ -40,6 +40,7 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App @BeanProperty var typed: String = "" @BeanProperty var interface: String = "" @BeanProperty var implementation: String = "" + @BeanProperty var beanRef: String = null @BeanProperty var timeoutStr: String = "" @BeanProperty var transactional: Boolean = false @BeanProperty var host: String = "" @@ -102,10 +103,18 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App private[akka] def createTypedInstance() : AnyRef = { if ((interface eq null) || interface == "") throw new AkkaBeansException( "The 'interface' part of the 'akka:actor' element in the Spring config file can't be null or empty string") - if ((implementation eq null) || implementation == "") throw new AkkaBeansException( - "The 'implementation' part of the 'akka:typed-actor' element in the Spring config file can't be null or empty string") + if (((implementation eq null) || implementation == "") && (beanRef eq null)) throw new AkkaBeansException( + "Either 'implementation' or 'ref' must be specified as attribute of the 'akka:typed-actor' element in the Spring config file ") + + val typedActor: AnyRef = if (beanRef eq null ) { + TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig) + } + else + { + TypedActor.newInstance(interface.toClass, getBeanFactory().getBean(beanRef), createConfig) + } + - val typedActor: AnyRef = TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig) if (isRemote && serverManaged) { val server = RemoteServer.getOrCreateServer(new InetSocketAddress(host, port.toInt)) if (serviceName.isEmpty) { @@ -121,9 +130,13 @@ class ActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with App * Create an UntypedActor. */ private[akka] def createUntypedInstance() : ActorRef = { - if ((implementation eq null) || implementation == "") throw new AkkaBeansException( - "The 'implementation' part of the 'akka:untyped-actor' element in the Spring config file can't be null or empty string") - val actorRef = Actor.actorOf(implementation.toClass) + if (((implementation eq null) || implementation == "") && (beanRef eq null)) throw new AkkaBeansException( + "Either 'implementation' or 'ref' must be specified as attribute of the 'akka:untyped-actor' element in the Spring config file ") + val actorRef = if (beanRef eq null ) + Actor.actorOf(implementation.toClass) + else + Actor.actorOf(getBeanFactory().getBean(beanRef).asInstanceOf[Actor]) + if (timeout > 0) { actorRef.setTimeout(timeout) } diff --git a/akka-spring/src/main/scala/ActorParser.scala b/akka-spring/src/main/scala/ActorParser.scala index 3a0c756f20..7785d469ef 100644 --- a/akka-spring/src/main/scala/ActorParser.scala +++ b/akka-spring/src/main/scala/ActorParser.scala @@ -53,7 +53,8 @@ trait ActorParser extends BeanParser with DispatcherParser { } objectProperties.timeoutStr = element.getAttribute(TIMEOUT) - objectProperties.target = mandatory(element, IMPLEMENTATION) + objectProperties.target = if (element.getAttribute(IMPLEMENTATION).isEmpty) null else element.getAttribute(IMPLEMENTATION) + objectProperties.beanRef = if (element.getAttribute(BEANREF).isEmpty) null else element.getAttribute(BEANREF) objectProperties.transactional = if (element.getAttribute(TRANSACTIONAL).isEmpty) false else element.getAttribute(TRANSACTIONAL).toBoolean if (element.hasAttribute(INTERFACE)) { diff --git a/akka-spring/src/main/scala/ActorProperties.scala b/akka-spring/src/main/scala/ActorProperties.scala index 487c3530da..c403de8da4 100644 --- a/akka-spring/src/main/scala/ActorProperties.scala +++ b/akka-spring/src/main/scala/ActorProperties.scala @@ -15,6 +15,7 @@ import AkkaSpringConfigurationTags._ class ActorProperties { var typed: String = "" var target: String = "" + var beanRef: String = "" var timeoutStr: String = "" var interface: String = "" var transactional: Boolean = false @@ -40,6 +41,7 @@ class ActorProperties { builder.addPropertyValue("serviceName", serviceName) builder.addPropertyValue("timeoutStr", timeoutStr) builder.addPropertyValue(IMPLEMENTATION, target) + builder.addPropertyValue("beanRef", beanRef) builder.addPropertyValue(INTERFACE, interface) builder.addPropertyValue(TRANSACTIONAL, transactional) builder.addPropertyValue(LIFECYCLE, lifecycle) diff --git a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala index 0871797810..67ca06d8fb 100644 --- a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala +++ b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala @@ -43,6 +43,7 @@ object AkkaSpringConfigurationTags { // actor attributes val TIMEOUT = "timeout" val IMPLEMENTATION = "implementation" + val BEANREF = "ref" val INTERFACE = "interface" val TRANSACTIONAL = "transactional" val HOST = "host" diff --git a/akka-spring/src/test/resources/typed-actor-config.xml b/akka-spring/src/test/resources/typed-actor-config.xml index fa0e81eeae..695be2f31d 100644 --- a/akka-spring/src/test/resources/typed-actor-config.xml +++ b/akka-spring/src/test/resources/typed-actor-config.xml @@ -14,6 +14,14 @@ http://scalablesolutions.se/akka/akka-1.0-SNAPSHOT.xsd"> implementation="akka.spring.foo.MyPojo" timeout="1000"/> + + + + + + + + + diff --git a/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala b/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala index faa307db0b..d9f9526b95 100644 --- a/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/TypedActorSpringFeatureTest.scala @@ -81,6 +81,14 @@ class TypedActorSpringFeatureTest extends FeatureSpec with ShouldMatchers with B assert(MyPojo.lastOneWayMessage === "hello 1") } + scenario("get a typed actor of bean") { + val myPojo = getTypedActorFromContext("/typed-actor-config.xml", "simple-typed-actor-of-bean") + assert(myPojo.getFoo() === "foo") + myPojo.oneWay("hello 1") + MyPojo.latch.await + assert(MyPojo.lastOneWayMessage === "hello 1") + } + scenario("FutureTimeoutException when timed out") { val myPojo = getTypedActorFromContext("/typed-actor-config.xml", "simple-typed-actor") evaluating {myPojo.longRunning()} should produce[FutureTimeoutException] diff --git a/akka-spring/src/test/scala/UntypedActorSpringFeatureTest.scala b/akka-spring/src/test/scala/UntypedActorSpringFeatureTest.scala index 3ae3f09b70..b2aaed7c1f 100644 --- a/akka-spring/src/test/scala/UntypedActorSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/UntypedActorSpringFeatureTest.scala @@ -67,6 +67,14 @@ class UntypedActorSpringFeatureTest extends FeatureSpec with ShouldMatchers with assert(myactor.isDefinedAt("some string message")) } + scenario("untyped-actor of provided bean") { + val myactor = getPingActorFromContext("/untyped-actor-config.xml", "simple-untyped-actor-of-bean") + myactor.sendOneWay("Hello") + PingActor.latch.await + assert(PingActor.lastMessage === "Hello") + assert(myactor.isDefinedAt("some string message")) + } + scenario("untyped-actor with timeout") { val myactor = getPingActorFromContext("/untyped-actor-config.xml", "simple-untyped-actor-long-timeout") assert(myactor.getTimeout() === 10000)