Add a ref="..." attribute to untyped-actor and typed-actor so that akka can use spring created beans

This commit is contained in:
Paul Pacheco 2010-11-07 22:23:32 -06:00
parent f198b966fd
commit fc9c83396c
9 changed files with 69 additions and 9 deletions

View file

@ -145,13 +145,20 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="implementation" type="xsd:string" use="required">
<xsd:attribute name="implementation" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Name of the implementation class.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Bean instance behind the actor
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
@ -191,13 +198,20 @@
<xsd:element ref="beans:property" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="implementation" type="xsd:string" use="required">
<xsd:attribute name="implementation" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Name of the implementation class.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Bean instance behind the actor
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="timeout" type="xsd:string">
<xsd:annotation>
<xsd:documentation>

View file

@ -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)
}

View file

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

View file

@ -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)

View file

@ -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"

View file

@ -14,6 +14,14 @@ http://scalablesolutions.se/akka/akka-1.0-SNAPSHOT.xsd">
implementation="akka.spring.foo.MyPojo"
timeout="1000"/>
<bean id="myPojoBean" class="akka.spring.foo.MyPojo" scope="prototype"/>
<akka:typed-actor id="simple-typed-actor-of-bean"
interface="akka.spring.foo.IMyPojo"
ref="myPojoBean"
timeout="1000"/>
<akka:typed-actor id="simple-typed-actor-long-timeout"
interface="akka.spring.foo.IMyPojo"
implementation="akka.spring.foo.MyPojo"

View file

@ -12,6 +12,11 @@ http://scalablesolutions.se/akka/akka-1.0-SNAPSHOT.xsd">
<akka:untyped-actor id="simple-untyped-actor"
implementation="akka.spring.foo.PingActor"/>
<bean id="pingActorBean" class="akka.spring.foo.PingActor" scope="prototype"/>
<akka:untyped-actor id="simple-untyped-actor-of-bean"
ref="pingActorBean"/>
<akka:untyped-actor id="simple-untyped-actor-long-timeout"
implementation="akka.spring.foo.PingActor"
timeout="10000"/>

View file

@ -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]

View file

@ -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)