Added TypedActor and TypedTransactor base classes.

Renamed ActiveObject factory object to TypedActor.
Improved network protocol for TypedActor.
Remote TypedActors now identified by UUID.
This commit is contained in:
Jonas Bonér 2010-07-26 18:47:25 +02:00
parent 20464a3d20
commit e48572f32e
84 changed files with 2278 additions and 1445 deletions

View file

@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<name>Akka Active Object Tests in Java</name> <name>Akka TypedActor Tests in Java</name>
<artifactId>akka-active-object-test</artifactId> <artifactId>akka-active-object-test</artifactId>
<groupId>se.scalablesolutions.akka</groupId> <groupId>se.scalablesolutions.akka</groupId>
<version>0.9</version> <version>0.9</version>

View file

@ -10,14 +10,14 @@ import com.google.inject.Scopes;
import junit.framework.TestCase; import junit.framework.TestCase;
import se.scalablesolutions.akka.config.Config; import se.scalablesolutions.akka.config.Config;
import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import se.scalablesolutions.akka.config.TypedActorConfigurator;
import static se.scalablesolutions.akka.config.JavaConfig.*; import static se.scalablesolutions.akka.config.JavaConfig.*;
import se.scalablesolutions.akka.dispatch.*; import se.scalablesolutions.akka.dispatch.*;
public class ActiveObjectGuiceConfiguratorTest extends TestCase { public class TypedActorGuiceConfiguratorTest extends TestCase {
static String messageLog = ""; static String messageLog = "";
final private ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); final private TypedActorConfigurator conf = new TypedActorConfigurator();
protected void setUp() { protected void setUp() {
Config.config(); Config.config();
@ -46,7 +46,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
} }
public void testGuiceActiveObjectInjection() { public void testGuiceTypedActorInjection() {
messageLog = ""; messageLog = "";
Foo foo = conf.getInstance(Foo.class); Foo foo = conf.getInstance(Foo.class);
Bar bar = conf.getInstance(Bar.class); Bar bar = conf.getInstance(Bar.class);
@ -69,7 +69,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
} }
} }
public void testActiveObjectInvocation() throws InterruptedException { public void testTypedActorInvocation() throws InterruptedException {
messageLog = ""; messageLog = "";
Foo foo = conf.getInstance(Foo.class); Foo foo = conf.getInstance(Foo.class);
messageLog += foo.foo("foo "); messageLog += foo.foo("foo ");
@ -79,7 +79,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
assertEquals("foo return_foo before_bar ", messageLog); assertEquals("foo return_foo before_bar ", messageLog);
} }
public void testActiveObjectInvocationsInvocation() throws InterruptedException { public void testTypedActorInvocationsInvocation() throws InterruptedException {
messageLog = ""; messageLog = "";
Foo foo = conf.getInstance(Foo.class); Foo foo = conf.getInstance(Foo.class);
Bar bar = conf.getInstance(Bar.class); Bar bar = conf.getInstance(Bar.class);

View file

@ -10,7 +10,7 @@ public class AllTest extends TestCase {
suite.addTestSuite(InMemoryStateTest.class); suite.addTestSuite(InMemoryStateTest.class);
suite.addTestSuite(InMemNestedStateTest.class); suite.addTestSuite(InMemNestedStateTest.class);
suite.addTestSuite(RemoteInMemoryStateTest.class); suite.addTestSuite(RemoteInMemoryStateTest.class);
suite.addTestSuite(ActiveObjectGuiceConfiguratorTest.class); suite.addTestSuite(TypedActorGuiceConfiguratorTest.class);
return suite; return suite;
} }

View file

@ -6,7 +6,7 @@ package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.config.*; import se.scalablesolutions.akka.config.*;
import se.scalablesolutions.akka.config.Config; import se.scalablesolutions.akka.config.Config;
import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import se.scalablesolutions.akka.config.TypedActorConfigurator;
import static se.scalablesolutions.akka.config.JavaConfig.*; import static se.scalablesolutions.akka.config.JavaConfig.*;
import se.scalablesolutions.akka.actor.*; import se.scalablesolutions.akka.actor.*;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -14,7 +14,7 @@ import junit.framework.TestCase;
public class InMemNestedStateTest extends TestCase { public class InMemNestedStateTest extends TestCase {
static String messageLog = ""; static String messageLog = "";
final private ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); final private TypedActorConfigurator conf = new TypedActorConfigurator();
public InMemNestedStateTest() { public InMemNestedStateTest() {
conf.configure( conf.configure(

View file

@ -8,7 +8,7 @@ import junit.framework.TestCase;
import se.scalablesolutions.akka.config.Config; import se.scalablesolutions.akka.config.Config;
import se.scalablesolutions.akka.config.*; import se.scalablesolutions.akka.config.*;
import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import se.scalablesolutions.akka.config.TypedActorConfigurator;
import static se.scalablesolutions.akka.config.JavaConfig.*; import static se.scalablesolutions.akka.config.JavaConfig.*;
@ -17,7 +17,7 @@ import se.scalablesolutions.akka.actor.*;
public class InMemoryStateTest extends TestCase { public class InMemoryStateTest extends TestCase {
static String messageLog = ""; static String messageLog = "";
final private ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); final private TypedActorConfigurator conf = new TypedActorConfigurator();
public InMemoryStateTest() { public InMemoryStateTest() {
Config.config(); Config.config();

View file

@ -1,7 +1,7 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
import static se.scalablesolutions.akka.actor.ActiveObject.link; import static se.scalablesolutions.akka.actor.TypedActor.link;
import static se.scalablesolutions.akka.actor.ActiveObject.newInstance; import static se.scalablesolutions.akka.actor.TypedActor.newInstance;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -15,7 +15,7 @@ import junit.framework.TestCase;
* @author johanrask * @author johanrask
* *
*/ */
public class MiscActiveObjectTest extends TestCase { public class MiscTypedActorTest extends TestCase {
/** /**

View file

@ -5,8 +5,8 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.config.Config; import se.scalablesolutions.akka.config.Config;
import se.scalablesolutions.akka.actor.ActiveObject; import se.scalablesolutions.akka.actor.TypedActor;
import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import se.scalablesolutions.akka.config.TypedActorConfigurator;
import se.scalablesolutions.akka.remote.RemoteNode; import se.scalablesolutions.akka.remote.RemoteNode;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -23,14 +23,14 @@ public class RemoteInMemoryStateTest extends TestCase {
try { Thread.currentThread().sleep(1000); } catch (Exception e) {} try { Thread.currentThread().sleep(1000); } catch (Exception e) {}
Config.config(); Config.config();
} }
final ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); final TypedActorConfigurator conf = new TypedActorConfigurator();
protected void tearDown() { protected void tearDown() {
conf.stop(); conf.stop();
} }
public void testMapShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { public void testMapShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 1000, "localhost", 9999); InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 1000, "localhost", 9999);
stateful.init(); stateful.init();
stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired
@ -38,10 +38,10 @@ public class RemoteInMemoryStateTest extends TestCase {
} }
public void testMapShouldRollbackStateForStatefulServerInCaseOfFailure() { public void testMapShouldRollbackStateForStatefulServerInCaseOfFailure() {
InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999);
stateful.init(); stateful.init();
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
InMemFailer failer = ActiveObject.newRemoteInstance(InMemFailer.class, 1000, "localhost", 9999); //conf.getInstance(InMemFailer.class); InMemFailer failer = TypedActor.newRemoteInstance(InMemFailer.class, 1000, "localhost", 9999); //conf.getInstance(InMemFailer.class);
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method
fail("should have thrown an exception"); fail("should have thrown an exception");
@ -51,7 +51,7 @@ public class RemoteInMemoryStateTest extends TestCase {
} }
public void testVectorShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { public void testVectorShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999);
stateful.init(); stateful.init();
stateful.setVectorState("init"); // set init state stateful.setVectorState("init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired
@ -59,10 +59,10 @@ public class RemoteInMemoryStateTest extends TestCase {
} }
public void testVectorShouldRollbackStateForStatefulServerInCaseOfFailure() { public void testVectorShouldRollbackStateForStatefulServerInCaseOfFailure() {
InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999);
stateful.init(); stateful.init();
stateful.setVectorState("init"); // set init state stateful.setVectorState("init"); // set init state
InMemFailer failer = ActiveObject.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class); InMemFailer failer = TypedActor.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class);
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method
fail("should have thrown an exception"); fail("should have thrown an exception");
@ -72,7 +72,7 @@ public class RemoteInMemoryStateTest extends TestCase {
} }
public void testRefShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { public void testRefShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999);
stateful.init(); stateful.init();
stateful.setRefState("init"); // set init state stateful.setRefState("init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired
@ -80,10 +80,10 @@ public class RemoteInMemoryStateTest extends TestCase {
} }
public void testRefShouldRollbackStateForStatefulServerInCaseOfFailure() { public void testRefShouldRollbackStateForStatefulServerInCaseOfFailure() {
InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999);
stateful.init(); stateful.init();
stateful.setRefState("init"); // set init state stateful.setRefState("init"); // set init state
InMemFailer failer = ActiveObject.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class); InMemFailer failer = TypedActor.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class);
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method
fail("should have thrown an exception"); fail("should have thrown an exception");

View file

@ -1 +1 @@
class=se.scalablesolutions.akka.camel.component.ActiveObjectComponent class=se.scalablesolutions.akka.camel.component.TypedActorComponent

View file

@ -9,7 +9,7 @@ import java.util.Map
import org.apache.camel.{ProducerTemplate, CamelContext} import org.apache.camel.{ProducerTemplate, CamelContext}
import org.apache.camel.impl.DefaultCamelContext import org.apache.camel.impl.DefaultCamelContext
import se.scalablesolutions.akka.camel.component.ActiveObjectComponent import se.scalablesolutions.akka.camel.component.TypedActorComponent
import se.scalablesolutions.akka.util.Logging import se.scalablesolutions.akka.util.Logging
/** /**
@ -29,13 +29,13 @@ trait CamelContextLifecycle extends Logging {
private var _started = false private var _started = false
/** /**
* Camel component for accessing active objects. * Camel component for accessing typed actors.
*/ */
private[camel] var activeObjectComponent: ActiveObjectComponent = _ private[camel] var activeObjectComponent: TypedActorComponent = _
/** /**
* Registry in which active objects are TEMPORARILY registered during * Registry in which typed actors are TEMPORARILY registered during
* creation of Camel routes to active objects. * creation of Camel routes to typed actors.
*/ */
private[camel] var activeObjectRegistry: Map[String, AnyRef] = _ private[camel] var activeObjectRegistry: Map[String, AnyRef] = _
@ -93,15 +93,15 @@ trait CamelContextLifecycle extends Logging {
* CamelContext stream-caching is enabled. If applications want to disable stream- * CamelContext stream-caching is enabled. If applications want to disable stream-
* caching they can do so after this method returned and prior to calling start. * caching they can do so after this method returned and prior to calling start.
* This method also registers a new * This method also registers a new
* {@link se.scalablesolutions.akka.camel.component.ActiveObjectComponent} at * {@link se.scalablesolutions.akka.camel.component.TypedActorComponent} at
* <code>context</code> under a name defined by ActiveObjectComponent.InternalSchema. * <code>context</code> under a name defined by TypedActorComponent.InternalSchema.
*/ */
def init(context: CamelContext) { def init(context: CamelContext) {
this.activeObjectComponent = new ActiveObjectComponent this.activeObjectComponent = new TypedActorComponent
this.activeObjectRegistry = activeObjectComponent.activeObjectRegistry this.activeObjectRegistry = activeObjectComponent.activeObjectRegistry
this.context = context this.context = context
this.context.setStreamCaching(true) this.context.setStreamCaching(true)
this.context.addComponent(ActiveObjectComponent.InternalSchema, activeObjectComponent) this.context.addComponent(TypedActorComponent.InternalSchema, activeObjectComponent)
this.template = context.createProducerTemplate this.template = context.createProducerTemplate
_initialized = true _initialized = true
log.info("Camel context initialized") log.info("Camel context initialized")

View file

@ -10,7 +10,7 @@ import se.scalablesolutions.akka.actor.{AspectInitRegistry, ActorRegistry}
import se.scalablesolutions.akka.util.{Bootable, Logging} import se.scalablesolutions.akka.util.{Bootable, Logging}
/** /**
* Used by applications (and the Kernel) to publish consumer actors and active objects via * Used by applications (and the Kernel) to publish consumer actors and typed actors via
* Camel endpoints and to manage the life cycle of a a global CamelContext which can be * Camel endpoints and to manage the life cycle of a a global CamelContext which can be
* accessed via <code>se.scalablesolutions.akka.camel.CamelContextManager.context</code>. * accessed via <code>se.scalablesolutions.akka.camel.CamelContextManager.context</code>.
* *
@ -33,8 +33,8 @@ trait CamelService extends Bootable with Logging {
* Starts the CamelService. Any started actor that is a consumer actor will be (asynchronously) * Starts the CamelService. Any started actor that is a consumer actor will be (asynchronously)
* published as Camel endpoint. Consumer actors that are started after this method returned will * published as Camel endpoint. Consumer actors that are started after this method returned will
* be published as well. Actor publishing is done asynchronously. A started (loaded) CamelService * be published as well. Actor publishing is done asynchronously. A started (loaded) CamelService
* also publishes <code>@consume</code> annotated methods of active objects that have been created * also publishes <code>@consume</code> annotated methods of typed actors that have been created
* with <code>ActiveObject.newInstance(..)</code> (and <code>ActiveObject.newInstance(..)</code> * with <code>TypedActor.newInstance(..)</code> (and <code>TypedActor.newInstance(..)</code>
* on a remote node). * on a remote node).
*/ */
abstract override def onLoad = { abstract override def onLoad = {
@ -44,7 +44,7 @@ trait CamelService extends Bootable with Logging {
if (!initialized) init if (!initialized) init
if (!started) start if (!started) start
// start actor that exposes consumer actors and active objects via Camel endpoints // start actor that exposes consumer actors and typed actors via Camel endpoints
consumerPublisher.start consumerPublisher.start
// init publishRequestor so that buffered and future events are delivered to consumerPublisher // init publishRequestor so that buffered and future events are delivered to consumerPublisher

View file

@ -13,7 +13,7 @@ import org.apache.camel.builder.RouteBuilder
import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor._
import se.scalablesolutions.akka.actor.annotation.consume import se.scalablesolutions.akka.actor.annotation.consume
import se.scalablesolutions.akka.camel.component.ActiveObjectComponent import se.scalablesolutions.akka.camel.component.TypedActorComponent
import se.scalablesolutions.akka.util.Logging import se.scalablesolutions.akka.util.Logging
/** /**
@ -37,7 +37,7 @@ private[camel] object ConsumerPublisher extends Logging {
} }
/** /**
* Creates a route to an active object method. * Creates a route to an typed actor method.
*/ */
def handleConsumerMethodRegistered(event: ConsumerMethodRegistered) { def handleConsumerMethodRegistered(event: ConsumerMethodRegistered) {
val targetMethod = event.method.getName val targetMethod = event.method.getName
@ -62,7 +62,7 @@ private[camel] object ConsumerPublisher extends Logging {
} }
/** /**
* Actor that publishes consumer actors and active object methods at Camel endpoints. * Actor that publishes consumer actors and typed actor methods at Camel endpoints.
* The Camel context used for publishing is CamelContextManager.context. This actor * The Camel context used for publishing is CamelContextManager.context. This actor
* accepts messages of type * accepts messages of type
* se.scalablesolutions.akka.camel.ConsumerRegistered, * se.scalablesolutions.akka.camel.ConsumerRegistered,
@ -111,10 +111,10 @@ private[camel] case class SetExpectedRegistrationCount(num: Int)
private[camel] case class SetExpectedUnregistrationCount(num: Int) private[camel] case class SetExpectedUnregistrationCount(num: Int)
/** /**
* Defines an abstract route to a target which is either an actor or an active object method.. * Defines an abstract route to a target which is either an actor or an typed actor method..
* *
* @param endpointUri endpoint URI of the consumer actor or active object method. * @param endpointUri endpoint URI of the consumer actor or typed actor method.
* @param id actor identifier or active object identifier (registry key). * @param id actor identifier or typed actor identifier (registry key).
* *
* @author Martin Krasser * @author Martin Krasser
*/ */
@ -149,20 +149,20 @@ private[camel] class ConsumerActorRoute(endpointUri: String, uuid: String, block
} }
/** /**
* Defines the route to an active object method.. * Defines the route to an typed actor method..
* *
* @param endpointUri endpoint URI of the consumer actor method * @param endpointUri endpoint URI of the consumer actor method
* @param id active object identifier * @param id typed actor identifier
* @param method name of the method to invoke. * @param method name of the method to invoke.
* *
* @author Martin Krasser * @author Martin Krasser
*/ */
private[camel] class ConsumerMethodRoute(val endpointUri: String, id: String, method: String) extends ConsumerRoute(endpointUri, id) { private[camel] class ConsumerMethodRoute(val endpointUri: String, id: String, method: String) extends ConsumerRoute(endpointUri, id) {
protected override def targetUri = "%s:%s?method=%s" format (ActiveObjectComponent.InternalSchema, id, method) protected override def targetUri = "%s:%s?method=%s" format (TypedActorComponent.InternalSchema, id, method)
} }
/** /**
* A registration listener that triggers publication of consumer actors and active object * A registration listener that triggers publication of consumer actors and typed actor
* methods as well as un-publication of consumer actors. This actor needs to be initialized * methods as well as un-publication of consumer actors. This actor needs to be initialized
* with a <code>PublishRequestorInit</code> command message for obtaining a reference to * with a <code>PublishRequestorInit</code> command message for obtaining a reference to
* a <code>publisher</code> actor. Before initialization it buffers all outbound messages * a <code>publisher</code> actor. Before initialization it buffers all outbound messages
@ -209,7 +209,7 @@ private[camel] class PublishRequestor extends Actor {
/** /**
* Command message to initialize a PublishRequestor to use <code>consumerPublisher</code> * Command message to initialize a PublishRequestor to use <code>consumerPublisher</code>
* for publishing actors or active object methods. * for publishing actors or typed actor methods.
*/ */
private[camel] case class PublishRequestorInit(consumerPublisher: ActorRef) private[camel] case class PublishRequestorInit(consumerPublisher: ActorRef)
@ -244,13 +244,13 @@ private[camel] case class ConsumerRegistered(actorRef: ActorRef, uri: String, uu
private[camel] case class ConsumerUnregistered(actorRef: ActorRef, uri: String, uuid: String) extends ConsumerEvent private[camel] case class ConsumerUnregistered(actorRef: ActorRef, uri: String, uuid: String) extends ConsumerEvent
/** /**
* Event indicating that an active object proxy has been created for a POJO. For each * Event indicating that an typed actor proxy has been created for a POJO. For each
* <code>@consume</code> annotated POJO method a separate instance of this class is * <code>@consume</code> annotated POJO method a separate instance of this class is
* created. * created.
* *
* @param activeObject active object (proxy). * @param activeObject typed actor (proxy).
* @param init * @param init
* @param uri endpoint URI of the active object method * @param uri endpoint URI of the typed actor method
* @param method method to be published. * @param method method to be published.
* *
* @author Martin Krasser * @author Martin Krasser
@ -258,13 +258,13 @@ private[camel] case class ConsumerUnregistered(actorRef: ActorRef, uri: String,
private[camel] case class ConsumerMethodRegistered(activeObject: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent private[camel] case class ConsumerMethodRegistered(activeObject: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent
/** /**
* Event indicating that an active object has been stopped. For each * Event indicating that an typed actor has been stopped. For each
* <code>@consume</code> annotated POJO method a separate instance of this class is * <code>@consume</code> annotated POJO method a separate instance of this class is
* created. * created.
* *
* @param activeObject active object (proxy). * @param activeObject typed actor (proxy).
* @param init * @param init
* @param uri endpoint URI of the active object method * @param uri endpoint URI of the typed actor method
* @param method method to be un-published. * @param method method to be un-published.
* *
* @author Martin Krasser * @author Martin Krasser
@ -308,14 +308,14 @@ private[camel] object ConsumerMethod {
/** /**
* Applies a function <code>f</code> to each consumer method of <code>activeObject</code> and * Applies a function <code>f</code> to each consumer method of <code>activeObject</code> and
* returns the function results as a list. A consumer method is one that is annotated with * returns the function results as a list. A consumer method is one that is annotated with
* <code>@consume</code>. If <code>activeObject</code> is a proxy for a remote active object * <code>@consume</code>. If <code>activeObject</code> is a proxy for a remote typed actor
* <code>f</code> is never called and <code>Nil</code> is returned. * <code>f</code> is never called and <code>Nil</code> is returned.
*/ */
def forConsumer[T](activeObject: AnyRef, init: AspectInit)(f: Method => T): List[T] = { def forConsumer[T](activeObject: AnyRef, init: AspectInit)(f: Method => T): List[T] = {
// TODO: support consumer annotation inheritance // TODO: support consumer annotation inheritance
// - visit overridden methods in superclasses // - visit overridden methods in superclasses
// - visit implemented method declarations in interfaces // - visit implemented method declarations in interfaces
if (init.remoteAddress.isDefined) Nil // let remote node publish active object methods on endpoints if (init.remoteAddress.isDefined) Nil // let remote node publish typed actor methods on endpoints
else for (m <- activeObject.getClass.getMethods.toList; if (m.isAnnotationPresent(classOf[consume]))) else for (m <- activeObject.getClass.getMethods.toList; if (m.isAnnotationPresent(classOf[consume])))
yield f(m) yield f(m)
} }
@ -326,8 +326,8 @@ private[camel] object ConsumerMethod {
*/ */
private[camel] object ConsumerMethodRegistered { private[camel] object ConsumerMethodRegistered {
/** /**
* Creates a list of ConsumerMethodRegistered event messages for an active object or an empty * Creates a list of ConsumerMethodRegistered event messages for an typed actor or an empty
* list if the active object is a proxy for an remote active object or the active object doesn't * list if the typed actor is a proxy for an remote typed actor or the typed actor doesn't
* have any <code>@consume</code> annotated methods. * have any <code>@consume</code> annotated methods.
*/ */
def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodRegistered] = { def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodRegistered] = {
@ -342,8 +342,8 @@ private[camel] object ConsumerMethodRegistered {
*/ */
private[camel] object ConsumerMethodUnregistered { private[camel] object ConsumerMethodUnregistered {
/** /**
* Creates a list of ConsumerMethodUnregistered event messages for an active object or an empty * Creates a list of ConsumerMethodUnregistered event messages for an typed actor or an empty
* list if the active object is a proxy for an remote active object or the active object doesn't * list if the typed actor is a proxy for an remote typed actor or the typed actor doesn't
* have any <code>@consume</code> annotated methods. * have any <code>@consume</code> annotated methods.
*/ */
def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodUnregistered] = { def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodUnregistered] = {

View file

@ -12,31 +12,31 @@ import org.apache.camel.component.bean._
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
object ActiveObjectComponent { object TypedActorComponent {
/** /**
* Default schema name for active object endpoint URIs. * Default schema name for typed actor endpoint URIs.
*/ */
val InternalSchema = "active-object-internal" val InternalSchema = "active-object-internal"
} }
/** /**
* Camel component for exchanging messages with active objects. This component * Camel component for exchanging messages with typed actors. This component
* tries to obtain the active object from the <code>activeObjectRegistry</code> * tries to obtain the typed actor from the <code>activeObjectRegistry</code>
* first. If it's not there it tries to obtain it from the CamelContext's registry. * first. If it's not there it tries to obtain it from the CamelContext's registry.
* *
* @see org.apache.camel.component.bean.BeanComponent * @see org.apache.camel.component.bean.BeanComponent
* *
* @author Martin Krasser * @author Martin Krasser
*/ */
class ActiveObjectComponent extends BeanComponent { class TypedActorComponent extends BeanComponent {
val activeObjectRegistry = new ConcurrentHashMap[String, AnyRef] val activeObjectRegistry = new ConcurrentHashMap[String, AnyRef]
/** /**
* Creates a {@link org.apache.camel.component.bean.BeanEndpoint} with a custom * Creates a {@link org.apache.camel.component.bean.BeanEndpoint} with a custom
* bean holder that uses <code>activeObjectRegistry</code> for getting access to * bean holder that uses <code>activeObjectRegistry</code> for getting access to
* active objects (beans). * typed actors (beans).
* *
* @see se.scalablesolutions.akka.camel.component.ActiveObjectHolder * @see se.scalablesolutions.akka.camel.component.TypedActorHolder
*/ */
override def createEndpoint(uri: String, remaining: String, parameters: Map[String, AnyRef]) = { override def createEndpoint(uri: String, remaining: String, parameters: Map[String, AnyRef]) = {
val endpoint = new BeanEndpoint(uri, this) val endpoint = new BeanEndpoint(uri, this)
@ -47,26 +47,26 @@ class ActiveObjectComponent extends BeanComponent {
} }
private def createBeanHolder(beanName: String) = private def createBeanHolder(beanName: String) =
new ActiveObjectHolder(activeObjectRegistry, getCamelContext, beanName).createCacheHolder new TypedActorHolder(activeObjectRegistry, getCamelContext, beanName).createCacheHolder
} }
/** /**
* {@link org.apache.camel.component.bean.BeanHolder} implementation that uses a custom * {@link org.apache.camel.component.bean.BeanHolder} implementation that uses a custom
* registry for getting access to active objects. * registry for getting access to typed actors.
* *
* @author Martin Krasser * @author Martin Krasser
*/ */
class ActiveObjectHolder(activeObjectRegistry: Map[String, AnyRef], context: CamelContext, name: String) class TypedActorHolder(activeObjectRegistry: Map[String, AnyRef], context: CamelContext, name: String)
extends RegistryBean(context, name) { extends RegistryBean(context, name) {
/** /**
* Returns an {@link se.scalablesolutions.akka.camel.component.ActiveObjectInfo} instance. * Returns an {@link se.scalablesolutions.akka.camel.component.TypedActorInfo} instance.
*/ */
override def getBeanInfo: BeanInfo = override def getBeanInfo: BeanInfo =
new ActiveObjectInfo(getContext, getBean.getClass, getParameterMappingStrategy) new TypedActorInfo(getContext, getBean.getClass, getParameterMappingStrategy)
/** /**
* Obtains an active object from <code>activeObjectRegistry</code>. * Obtains an typed actor from <code>activeObjectRegistry</code>.
*/ */
override def getBean: AnyRef = { override def getBean: AnyRef = {
val bean = activeObjectRegistry.get(getName) val bean = activeObjectRegistry.get(getName)
@ -75,11 +75,11 @@ class ActiveObjectHolder(activeObjectRegistry: Map[String, AnyRef], context: Cam
} }
/** /**
* Provides active object meta information. * Provides typed actor meta information.
* *
* @author Martin Krasser * @author Martin Krasser
*/ */
class ActiveObjectInfo(context: CamelContext, clazz: Class[_], strategy: ParameterMappingStrategy) class TypedActorInfo(context: CamelContext, clazz: Class[_], strategy: ParameterMappingStrategy)
extends BeanInfo(context, clazz, strategy) { extends BeanInfo(context, clazz, strategy) {
/** /**

View file

@ -9,7 +9,7 @@ public class PojoRemote {
@consume("direct:remote-active-object") @consume("direct:remote-active-object")
public String foo(String s) { public String foo(String s) {
return String.format("remote active object: %s", s); return String.format("remote typed actor: %s", s);
} }
} }

View file

@ -7,7 +7,7 @@ import org.apache.camel.builder.RouteBuilder
import org.scalatest.{GivenWhenThen, BeforeAndAfterAll, FeatureSpec} import org.scalatest.{GivenWhenThen, BeforeAndAfterAll, FeatureSpec}
import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.Actor._
import se.scalablesolutions.akka.actor.{ActiveObject, Actor, ActorRegistry} import se.scalablesolutions.akka.actor.{TypedActor, Actor, ActorRegistry}
class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with GivenWhenThen { class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with GivenWhenThen {
import CamelServiceFeatureTest._ import CamelServiceFeatureTest._
@ -116,13 +116,13 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi
} }
} }
feature("Publish active object methods in the global CamelContext") { feature("Publish typed actor methods in the global CamelContext") {
scenario("access active object methods via Camel direct-endpoints") { scenario("access typed actor methods via Camel direct-endpoints") {
given("an active object registered after CamelService startup") given("an typed actor registered after CamelService startup")
var latch = service.expectEndpointActivationCount(3) var latch = service.expectEndpointActivationCount(3)
val obj = ActiveObject.newInstance(classOf[PojoBase]) val obj = TypedActor.newInstance(classOf[PojoBase])
assert(latch.await(5000, TimeUnit.MILLISECONDS)) assert(latch.await(5000, TimeUnit.MILLISECONDS))
when("requests are sent to published methods") when("requests are sent to published methods")
@ -137,23 +137,23 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi
// cleanup to avoid conflicts with next test (i.e. avoid multiple consumers on direct-endpoints) // cleanup to avoid conflicts with next test (i.e. avoid multiple consumers on direct-endpoints)
latch = service.expectEndpointDeactivationCount(3) latch = service.expectEndpointDeactivationCount(3)
ActiveObject.stop(obj) TypedActor.stop(obj)
assert(latch.await(5000, TimeUnit.MILLISECONDS)) assert(latch.await(5000, TimeUnit.MILLISECONDS))
} }
} }
feature("Unpublish active object method from the global CamelContext") { feature("Unpublish typed actor method from the global CamelContext") {
scenario("access to unregistered active object method via Camel direct-endpoint fails") { scenario("access to unregistered typed actor method via Camel direct-endpoint fails") {
given("an active object registered after CamelService startup") given("an typed actor registered after CamelService startup")
var latch = service.expectEndpointActivationCount(3) var latch = service.expectEndpointActivationCount(3)
val obj = ActiveObject.newInstance(classOf[PojoBase]) val obj = TypedActor.newInstance(classOf[PojoBase])
assert(latch.await(5000, TimeUnit.MILLISECONDS)) assert(latch.await(5000, TimeUnit.MILLISECONDS))
when("the active object is stopped") when("the typed actor is stopped")
latch = service.expectEndpointDeactivationCount(3) latch = service.expectEndpointDeactivationCount(3)
ActiveObject.stop(obj) TypedActor.stop(obj)
assert(latch.await(5000, TimeUnit.MILLISECONDS)) assert(latch.await(5000, TimeUnit.MILLISECONDS))
then("the associated endpoints aren't accessible any more") then("the associated endpoints aren't accessible any more")

View file

@ -4,7 +4,7 @@ import java.net.InetSocketAddress
import org.scalatest.junit.JUnitSuite import org.scalatest.junit.JUnitSuite
import se.scalablesolutions.akka.actor.{AspectInit, ActiveObject} import se.scalablesolutions.akka.actor.{AspectInit, TypedActor}
import se.scalablesolutions.akka.camel.ConsumerMethodRegistered._ import se.scalablesolutions.akka.camel.ConsumerMethodRegistered._
import org.junit.{AfterClass, Test} import org.junit.{AfterClass, Test}
@ -44,14 +44,14 @@ class ConsumerMethodRegisteredTest extends JUnitSuite {
} }
object ConsumerMethodRegisteredTest { object ConsumerMethodRegisteredTest {
val activePojoBase = ActiveObject.newInstance(classOf[PojoBase]) val activePojoBase = TypedActor.newInstance(classOf[PojoBase])
val activePojoSub = ActiveObject.newInstance(classOf[PojoSub]) val activePojoSub = TypedActor.newInstance(classOf[PojoSub])
val activePojoIntf = ActiveObject.newInstance(classOf[PojoIntf], new PojoImpl) val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], new PojoImpl)
@AfterClass @AfterClass
def afterClass = { def afterClass = {
ActiveObject.stop(activePojoBase) TypedActor.stop(activePojoBase)
ActiveObject.stop(activePojoSub) TypedActor.stop(activePojoSub)
ActiveObject.stop(activePojoIntf) TypedActor.stop(activePojoIntf)
} }
} }

View file

@ -32,7 +32,7 @@ class PublishRequestorTest extends JUnitSuite {
} }
@Test def shouldReceiveConsumerMethodRegisteredEvent = { @Test def shouldReceiveConsumerMethodRegisteredEvent = {
val obj = ActiveObject.newInstance(classOf[PojoSingle]) val obj = TypedActor.newInstance(classOf[PojoSingle])
val init = AspectInit(classOf[PojoSingle], null, None, 1000) val init = AspectInit(classOf[PojoSingle], null, None, 1000)
val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get
requestor ! AspectInitRegistered(obj, init) requestor ! AspectInitRegistered(obj, init)
@ -45,7 +45,7 @@ class PublishRequestorTest extends JUnitSuite {
} }
@Test def shouldReceiveConsumerMethodUnregisteredEvent = { @Test def shouldReceiveConsumerMethodUnregisteredEvent = {
val obj = ActiveObject.newInstance(classOf[PojoSingle]) val obj = TypedActor.newInstance(classOf[PojoSingle])
val init = AspectInit(classOf[PojoSingle], null, None, 1000) val init = AspectInit(classOf[PojoSingle], null, None, 1000)
val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get
requestor ! AspectInitUnregistered(obj, init) requestor ! AspectInitUnregistered(obj, init)

View file

@ -5,7 +5,7 @@ import java.util.concurrent.{CountDownLatch, TimeUnit}
import org.scalatest.{GivenWhenThen, BeforeAndAfterAll, FeatureSpec} import org.scalatest.{GivenWhenThen, BeforeAndAfterAll, FeatureSpec}
import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.Actor._
import se.scalablesolutions.akka.actor.{ActiveObject, ActorRegistry, RemoteActor} import se.scalablesolutions.akka.actor.{TypedActor, ActorRegistry, RemoteActor}
import se.scalablesolutions.akka.remote.{RemoteClient, RemoteServer} import se.scalablesolutions.akka.remote.{RemoteClient, RemoteServer}
/** /**
@ -55,10 +55,10 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh
} }
} }
feature("Client-initiated remote consumer active object") { feature("Client-initiated remote consumer typed actor") {
scenario("access published remote consumer method") { scenario("access published remote consumer method") {
given("a client-initiated remote consumer active object") given("a client-initiated remote consumer typed actor")
val consumer = ActiveObject.newRemoteInstance(classOf[PojoRemote], host, port) val consumer = TypedActor.newRemoteInstance(classOf[PojoRemote], host, port)
when("remote consumer publication is triggered") when("remote consumer publication is triggered")
var latch = service.expectEndpointActivationCount(1) var latch = service.expectEndpointActivationCount(1)
@ -67,7 +67,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh
then("the published method is accessible via its endpoint URI") then("the published method is accessible via its endpoint URI")
val response = CamelContextManager.template.requestBody("direct:remote-active-object", "test") val response = CamelContextManager.template.requestBody("direct:remote-active-object", "test")
assert(response === "remote active object: test") assert(response === "remote typed actor: test")
} }
} }
} }

View file

@ -4,7 +4,7 @@ import org.scalatest.{BeforeAndAfterEach, BeforeAndAfterAll, FeatureSpec}
import org.apache.camel.builder.RouteBuilder import org.apache.camel.builder.RouteBuilder
import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.Actor._
import se.scalablesolutions.akka.actor.{ActorRegistry, ActiveObject} import se.scalablesolutions.akka.actor.{ActorRegistry, TypedActor}
import se.scalablesolutions.akka.camel._ import se.scalablesolutions.akka.camel._
import org.apache.camel.impl.{DefaultCamelContext, SimpleRegistry} import org.apache.camel.impl.{DefaultCamelContext, SimpleRegistry}
import org.apache.camel.{ResolveEndpointFailedException, ExchangePattern, Exchange, Processor} import org.apache.camel.{ResolveEndpointFailedException, ExchangePattern, Exchange, Processor}
@ -12,14 +12,14 @@ import org.apache.camel.{ResolveEndpointFailedException, ExchangePattern, Exchan
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach { class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach {
import ActiveObjectComponentFeatureTest._ import TypedActorComponentFeatureTest._
import CamelContextManager.template import CamelContextManager.template
override protected def beforeAll = { override protected def beforeAll = {
val activePojo = ActiveObject.newInstance(classOf[Pojo]) // not a consumer val activePojo = TypedActor.newInstance(classOf[Pojo]) // not a consumer
val activePojoBase = ActiveObject.newInstance(classOf[PojoBase]) val activePojoBase = TypedActor.newInstance(classOf[PojoBase])
val activePojoIntf = ActiveObject.newInstance(classOf[PojoIntf], new PojoImpl) val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], new PojoImpl)
val registry = new SimpleRegistry val registry = new SimpleRegistry
registry.put("pojo", activePojo) registry.put("pojo", activePojo)
@ -37,8 +37,8 @@ class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAl
ActorRegistry.shutdownAll ActorRegistry.shutdownAll
} }
feature("Communicate with an active object from a Camel application using active object endpoint URIs") { feature("Communicate with an typed actor from a Camel application using typed actor endpoint URIs") {
import ActiveObjectComponent.InternalSchema import TypedActorComponent.InternalSchema
import ExchangePattern._ import ExchangePattern._
scenario("in-out exchange with proxy created from interface and method returning String") { scenario("in-out exchange with proxy created from interface and method returning String") {
@ -81,14 +81,14 @@ class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAl
} }
} }
feature("Communicate with an active object from a Camel application from a custom Camel route") { feature("Communicate with an typed actor from a Camel application from a custom Camel route") {
scenario("in-out exchange with externally registered active object") { scenario("in-out exchange with externally registered typed actor") {
val result = template.requestBody("direct:test", "test") val result = template.requestBody("direct:test", "test")
assert(result === "foo: test") assert(result === "foo: test")
} }
scenario("in-out exchange with internally registered active object not possible") { scenario("in-out exchange with internally registered typed actor not possible") {
intercept[ResolveEndpointFailedException] { intercept[ResolveEndpointFailedException] {
template.requestBodyAndHeader("active-object:intf?method=m2", "x", "test", "y") template.requestBodyAndHeader("active-object:intf?method=m2", "x", "test", "y")
} }
@ -96,7 +96,7 @@ class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAl
} }
} }
object ActiveObjectComponentFeatureTest { object TypedActorComponentFeatureTest {
class CustomRouteBuilder extends RouteBuilder { class CustomRouteBuilder extends RouteBuilder {
def configure = { def configure = {
from("direct:test").to("active-object:pojo?method=foo") from("direct:test").to("active-object:pojo?method=foo")

View file

@ -13,10 +13,10 @@ import com.google.inject.Singleton;
/** /**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
public class ActiveObjectGuiceModule extends AbstractModule { public class TypedActorGuiceModule extends AbstractModule {
private final List<DependencyBinding> bindings; private final List<DependencyBinding> bindings;
public ActiveObjectGuiceModule(final List<DependencyBinding> bindings) { public TypedActorGuiceModule(final List<DependencyBinding> bindings) {
this.bindings = bindings; this.bindings = bindings;
} }

View file

@ -52,21 +52,35 @@ message MessageProtocol {
optional bytes messageManifest = 3; optional bytes messageManifest = 3;
} }
/**
* Defines the actor info.
*/
message ActorInfoProtocol {
required string uuid = 1;
required string target = 2;
required uint64 timeout = 3;
required ActorType actorType = 4;
optional TypedActorInfoProtocol typedActorInfo = 5;
}
/**
* Defines the typed actor extra info.
*/
message TypedActorInfoProtocol {
required string interface = 1;
required string method = 2;
}
/** /**
* Defines a remote message request. * Defines a remote message request.
*/ */
message RemoteRequestProtocol { message RemoteRequestProtocol {
required uint64 id = 1; required uint64 id = 1;
required MessageProtocol message = 2; required MessageProtocol message = 2;
optional string method = 3; required ActorInfoProtocol actorInfo = 3;
required string target = 4; required bool isOneWay = 4;
required string uuid = 5; optional string supervisorUuid = 5;
required uint64 timeout = 6; optional RemoteActorRefProtocol sender = 6;
optional string supervisorUuid = 7;
required bool isActor = 8;
required bool isOneWay = 9;
required bool isEscaped = 10;
optional RemoteActorRefProtocol sender = 11;
} }
/** /**
@ -81,6 +95,15 @@ message RemoteReplyProtocol {
required bool isSuccessful = 6; required bool isSuccessful = 6;
} }
/**
* Defines the actor type.
*/
enum ActorType {
SCALA_ACTOR = 1;
JAVA_ACTOR = 2;
TYPED_ACTOR = 3;
}
/** /**
* Defines the serialization scheme used to serialize the message and/or Actor instance. * Defines the serialization scheme used to serialize the message and/or Actor instance.
*/ */
@ -117,6 +140,8 @@ message LifeCycleProtocol {
required LifeCycleType lifeCycle = 1; required LifeCycleType lifeCycle = 1;
optional string preRestart = 2; optional string preRestart = 2;
optional string postRestart = 3; optional string postRestart = 3;
optional string init = 4;
optional string shutdown = 5;
} }
/** /**

View file

@ -1,7 +1,7 @@
<aspectwerkz> <aspectwerkz>
<system id="akka"> <system id="akka">
<package name="se.scalablesolutions.akka.actor"> <package name="se.scalablesolutions.akka.actor">
<aspect class="ActiveObjectAspect" /> <aspect class="TypedActorAspect" />
</package> </package>
</system> </system>
</aspectwerkz> </aspectwerkz>

View file

@ -291,15 +291,15 @@ trait ActorRef extends TransactionManagement {
def !!(message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Option[Any] = { def !!(message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Option[Any] = {
if (isRunning) { if (isRunning) {
val future = postMessageToMailboxAndCreateFutureResultWithTimeout[Any](message, timeout, sender, None) val future = postMessageToMailboxAndCreateFutureResultWithTimeout[Any](message, timeout, sender, None)
val isActiveObject = message.isInstanceOf[Invocation] val isTypedActor = message.isInstanceOf[Invocation]
if (isActiveObject && message.asInstanceOf[Invocation].isVoid) { if (isTypedActor && message.asInstanceOf[Invocation].isVoid) {
future.asInstanceOf[CompletableFuture[Option[_]]].completeWithResult(None) future.asInstanceOf[CompletableFuture[Option[_]]].completeWithResult(None)
} }
try { try {
future.await future.await
} catch { } catch {
case e: FutureTimeoutException => case e: FutureTimeoutException =>
if (isActiveObject) throw e if (isTypedActor) throw e
else None else None
} }
if (future.exception.isDefined) throw future.exception.get._2 if (future.exception.isDefined) throw future.exception.get._2
@ -347,7 +347,7 @@ trait ActorRef extends TransactionManagement {
"\n\tNo sender in scope, can't reply. " + "\n\tNo sender in scope, can't reply. " +
"\n\tYou have probably: " + "\n\tYou have probably: " +
"\n\t\t1. Sent a message to an Actor from an instance that is NOT an Actor." + "\n\t\t1. Sent a message to an Actor from an instance that is NOT an Actor." +
"\n\t\t2. Invoked a method on an Active Object from an instance NOT an Active Object." + "\n\t\t2. Invoked a method on an TypedActor from an instance NOT an TypedActor." +
"\n\tElse you might want to use 'reply_?' which returns Boolean(true) if succes and Boolean(false) if no sender in scope") "\n\tElse you might want to use 'reply_?' which returns Boolean(true) if succes and Boolean(false) if no sender in scope")
/** /**

View file

@ -122,7 +122,8 @@ object ActorSerialization {
private def fromBinaryToLocalActorRef[T <: Actor](bytes: Array[Byte], format: Format[T]): ActorRef = private def fromBinaryToLocalActorRef[T <: Actor](bytes: Array[Byte], format: Format[T]): ActorRef =
fromProtobufToLocalActorRef(SerializedActorRefProtocol.newBuilder.mergeFrom(bytes).build, format, None) fromProtobufToLocalActorRef(SerializedActorRefProtocol.newBuilder.mergeFrom(bytes).build, format, None)
private def fromProtobufToLocalActorRef[T <: Actor](protocol: SerializedActorRefProtocol, format: Format[T], loader: Option[ClassLoader]): ActorRef = { private def fromProtobufToLocalActorRef[T <: Actor](
protocol: SerializedActorRefProtocol, format: Format[T], loader: Option[ClassLoader]): ActorRef = {
Actor.log.debug("Deserializing SerializedActorRefProtocol to LocalActorRef:\n" + protocol) Actor.log.debug("Deserializing SerializedActorRefProtocol to LocalActorRef:\n" + protocol)
val serializer = val serializer =
@ -225,26 +226,30 @@ object RemoteActorSerialization {
.build .build
} }
def createRemoteRequestProtocolBuilder(ar: ActorRef, def createRemoteRequestProtocolBuilder(actorRef: ActorRef, message: Any, isOneWay: Boolean, senderOption: Option[ActorRef]):
message: Any, isOneWay: Boolean, senderOption: Option[ActorRef]): RemoteRequestProtocol.Builder = { RemoteRequestProtocol.Builder = {
import ar._ import actorRef._
val protocol = RemoteRequestProtocol.newBuilder
.setId(RemoteRequestProtocolIdFactory.nextId) val actorInfo = ActorInfoProtocol.newBuilder
.setMessage(MessageSerializer.serialize(message)) .setUuid(uuid)
.setTarget(actorClassName) .setTarget(actorClassName)
.setTimeout(timeout) .setTimeout(timeout)
.setUuid(uuid) .setActorType(ActorType.SCALA_ACTOR)
.setIsActor(true) .build
val request = RemoteRequestProtocol.newBuilder
.setId(RemoteRequestProtocolIdFactory.nextId)
.setMessage(MessageSerializer.serialize(message))
.setActorInfo(actorInfo)
.setIsOneWay(isOneWay) .setIsOneWay(isOneWay)
.setIsEscaped(false)
val id = registerSupervisorAsRemoteActor val id = registerSupervisorAsRemoteActor
if (id.isDefined) protocol.setSupervisorUuid(id.get) if (id.isDefined) request.setSupervisorUuid(id.get)
senderOption.foreach { sender => senderOption.foreach { sender =>
RemoteServer.getOrCreateServer(sender.homeAddress).register(sender.uuid, sender) RemoteServer.getOrCreateServer(sender.homeAddress).register(sender.uuid, sender)
protocol.setSender(toRemoteActorRefProtocol(sender)) request.setSender(toRemoteActorRefProtocol(sender))
} }
protocol request
} }
} }

View file

@ -6,12 +6,13 @@ package se.scalablesolutions.akka.actor
import Actor._ import Actor._
import se.scalablesolutions.akka.config.FaultHandlingStrategy import se.scalablesolutions.akka.config.FaultHandlingStrategy
import se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteRequestProtocol import se.scalablesolutions.akka.remote.protocol.RemoteProtocol._
import se.scalablesolutions.akka.remote.{MessageSerializer, RemoteClient, RemoteRequestProtocolIdFactory} import se.scalablesolutions.akka.remote.{MessageSerializer, RemoteClient, RemoteRequestProtocolIdFactory}
import se.scalablesolutions.akka.dispatch.{MessageDispatcher, Future, CompletableFuture} import se.scalablesolutions.akka.dispatch.{MessageDispatcher, Future, CompletableFuture}
import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.config.ScalaConfig._
import se.scalablesolutions.akka.serialization.Serializer import se.scalablesolutions.akka.serialization.Serializer
import se.scalablesolutions.akka.util._ import se.scalablesolutions.akka.util._
import se.scalablesolutions.akka.actor.annotation._
import org.codehaus.aspectwerkz.joinpoint.{MethodRtti, JoinPoint} import org.codehaus.aspectwerkz.joinpoint.{MethodRtti, JoinPoint}
import org.codehaus.aspectwerkz.proxy.Proxy import org.codehaus.aspectwerkz.proxy.Proxy
@ -20,21 +21,111 @@ import org.codehaus.aspectwerkz.annotation.{Aspect, Around}
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.lang.reflect.{InvocationTargetException, Method} import java.lang.reflect.{InvocationTargetException, Method}
object Annotations { import scala.reflect.BeanProperty
import se.scalablesolutions.akka.actor.annotation._
val transactionrequired = classOf[transactionrequired] /**
val prerestart = classOf[prerestart] * FIXME: document TypedActor
val postrestart = classOf[postrestart] *
val shutdown = classOf[shutdown] * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
val inittransactionalstate = classOf[inittransactionalstate] */
abstract class TypedActor extends Logging {
/**
* Holds RTTI (runtime type information) for the TypedActor, f.e. current 'sender'
* reference, the 'senderFuture' reference etc.
* <p/>
* This class does not contain static information but is updated by the runtime system
* at runtime.
* <p/>
* Here is an example of usage (in Java):
* <pre>
* class PingImpl exends TypedActor implements Ping {
* public void hit(int count) {
* Pong pong = (Pong) getContext().getSender();
* pong.hit(count++)
* }
* }
* </pre>
*/
@BeanProperty protected var context: TypedActorContext = _
/**
* The uuid for the typed actor.
*/
@BeanProperty @volatile var uuid = UUID.newUuid.toString
/**
* Identifier for actor, does not have to be a unique one. Default is the 'uuid'.
* <p/>
* This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote
* actor in RemoteServer etc.But also as the identifier for persistence, which means
* that you can use a custom name to be able to retrieve the "correct" persisted state
* upon restart, remote restart etc.
* <p/>
* This property can be set to a custom ID.
*/
@BeanProperty @volatile protected var id: String = uuid
/**
* Defines the default timeout for '!!' and '!!!' invocations,
* e.g. the timeout for the future returned by the call to '!!' and '!!!'.
* <p/>
* This property can be set to a custom timeout.
*/
@BeanProperty @volatile protected var timeout: Long = Actor.TIMEOUT
/**
* User overridable callback.
* <p/>
* Is called when an Actor is started by invoking 'actor.start'.
*/
def init {}
/**
* User overridable callback.
* <p/>
* Is called when 'actor.stop' is invoked.
*/
def shutdown {}
/**
* User overridable callback.
* <p/>
* Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated.
*/
def preRestart(reason: Throwable) {}
/**
* User overridable callback.
* <p/>
* Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash.
*/
def postRestart(reason: Throwable) {}
/**
* User overridable callback.
* <p/>
* Is called during initialization. Can be used to initialize transactional state. Will be invoked within a transaction.
*/
def initTransactionalState {}
} }
/** /**
* Configuration factory for Active Objects. * FIXME: document TypedTransactor
* *
* FIXDOC: document ActiveObjectConfiguration * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
final class ActiveObjectConfiguration { @transactionrequired
abstract class TypedTransactor extends TypedActor
/**
* Configuration factory for TypedActors.
*
* FIXDOC: document TypedActorConfiguration
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
final class TypedActorConfiguration {
private[akka] var _timeout: Long = Actor.TIMEOUT private[akka] var _timeout: Long = Actor.TIMEOUT
private[akka] var _restartCallbacks: Option[RestartCallbacks] = None private[akka] var _restartCallbacks: Option[RestartCallbacks] = None
private[akka] var _shutdownCallback: Option[ShutdownCallback] = None private[akka] var _shutdownCallback: Option[ShutdownCallback] = None
@ -43,57 +134,49 @@ final class ActiveObjectConfiguration {
private[akka] var _messageDispatcher: Option[MessageDispatcher] = None private[akka] var _messageDispatcher: Option[MessageDispatcher] = None
def timeout = _timeout def timeout = _timeout
def timeout(timeout: Duration) : ActiveObjectConfiguration = { def timeout(timeout: Duration) : TypedActorConfiguration = {
_timeout = timeout.toMillis _timeout = timeout.toMillis
this this
} }
def restartCallbacks(pre: String, post: String) : ActiveObjectConfiguration = { def restartCallbacks(pre: String, post: String) : TypedActorConfiguration = {
_restartCallbacks = Some(new RestartCallbacks(pre, post)) _restartCallbacks = Some(new RestartCallbacks(pre, post))
this this
} }
def shutdownCallback(down: String) : ActiveObjectConfiguration = { def shutdownCallback(down: String) : TypedActorConfiguration = {
_shutdownCallback = Some(new ShutdownCallback(down)) _shutdownCallback = Some(new ShutdownCallback(down))
this this
} }
def makeTransactionRequired() : ActiveObjectConfiguration = { def makeTransactionRequired() : TypedActorConfiguration = {
_transactionRequired = true; _transactionRequired = true;
this this
} }
def makeRemote(hostname: String, port: Int) : ActiveObjectConfiguration = { def makeRemote(hostname: String, port: Int) : TypedActorConfiguration = {
_host = Some(new InetSocketAddress(hostname, port)) _host = Some(new InetSocketAddress(hostname, port))
this this
} }
def dispatcher(messageDispatcher: MessageDispatcher) : ActiveObjectConfiguration = { def dispatcher(messageDispatcher: MessageDispatcher) : TypedActorConfiguration = {
_messageDispatcher = Some(messageDispatcher) _messageDispatcher = Some(messageDispatcher)
this this
} }
} }
/** /**
* Holds RTTI (runtime type information) for the Active Object, f.e. current 'sender' * Holds RTTI (runtime type information) for the TypedActor, f.e. current 'sender'
* reference, the 'senderFuture' reference etc. * reference, the 'senderFuture' reference etc.
* <p/> * <p/>
* In order to make use of this context you have to create a member field in your
* Active Object that has the type 'ActiveObjectContext', then an instance will
* be injected for you to use.
* <p/>
* This class does not contain static information but is updated by the runtime system * This class does not contain static information but is updated by the runtime system
* at runtime. * at runtime.
* <p/> * <p/>
* Here is an example of usage: * Here is an example of usage (from Java):
* <pre> * <pre>
* class Ping { * class PingImpl exends TypedActor implements Ping {
* // This context will be injected, holds RTTI (runtime type information)
* // for the current message send
* private ActiveObjectContext context = null;
*
* public void hit(int count) { * public void hit(int count) {
* Pong pong = (Pong) context.getSender(); * Pong pong = (Pong) getContext().getSender();
* pong.hit(count++) * pong.hit(count++)
* } * }
* } * }
@ -101,12 +184,12 @@ final class ActiveObjectConfiguration {
* *
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
final class ActiveObjectContext { final class TypedActorContext {
private[akka] var _sender: AnyRef = _ private[akka] var _sender: AnyRef = _
private[akka] var _senderFuture: CompletableFuture[Any] = _ private[akka] var _senderFuture: CompletableFuture[Any] = _
/** /**
* Returns the current sender Active Object reference. * Returns the current sender reference.
* Scala style getter. * Scala style getter.
*/ */
def sender: AnyRef = { def sender: AnyRef = {
@ -115,7 +198,7 @@ final class ActiveObjectContext {
} }
/** /**
* Returns the current sender Active Object reference. * Returns the current sender reference.
* Java style getter. * Java style getter.
*/ */
def getSender: AnyRef = { def getSender: AnyRef = {
@ -124,13 +207,13 @@ final class ActiveObjectContext {
} }
/** /**
* Returns the current sender future Active Object reference. * Returns the current sender future TypedActor reference.
* Scala style getter. * Scala style getter.
*/ */
def senderFuture: Option[CompletableFuture[Any]] = if (_senderFuture eq null) None else Some(_senderFuture) def senderFuture: Option[CompletableFuture[Any]] = if (_senderFuture eq null) None else Some(_senderFuture)
/** /**
* Returns the current sender future Active Object reference. * Returns the current sender future TypedActor reference.
* Java style getter. * Java style getter.
* This method returns 'null' if the sender future is not available. * This method returns 'null' if the sender future is not available.
*/ */
@ -138,249 +221,63 @@ final class ActiveObjectContext {
} }
/** /**
* Internal helper class to help pass the contextual information between threads. * Factory class for creating TypedActors out of plain POJOs and/or POJOs with interfaces.
* *
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
private[akka] object ActiveObjectContext { object TypedActor extends Logging {
import scala.util.DynamicVariable
private[actor] val sender = new DynamicVariable[AnyRef](null)
private[actor] val senderFuture = new DynamicVariable[CompletableFuture[Any]](null)
}
/**
* Factory class for creating Active Objects out of plain POJOs and/or POJOs with interfaces.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object ActiveObject extends Logging {
import Actor.actorOf import Actor.actorOf
val AKKA_CAMEL_ROUTING_SCHEME = "akka" val AKKA_CAMEL_ROUTING_SCHEME = "akka".intern
private[actor] val AW_PROXY_PREFIX = "$$ProxiedByAW".intern private[actor] val AW_PROXY_PREFIX = "$$ProxiedByAW".intern
def newInstance[T](target: Class[T], timeout: Long): T = def newInstance[T](intfClass: Class[T], targetClass: Class[_], timeout: Long): T = {
newInstance(target, actorOf(new Dispatcher(false)), None, timeout) newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, timeout)
}
def newInstance[T](target: Class[T]): T = def newInstance[T](intfClass: Class[T], targetClass: Class[_]): T = {
newInstance(target, actorOf(new Dispatcher(false)), None, Actor.TIMEOUT) newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)
}
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long): T = def newRemoteInstance[T](intfClass: Class[T], targetClass: Class[_], timeout: Long, hostname: String, port: Int): T = {
newInstance(intf, target, actorOf(new Dispatcher(false)), None, timeout) newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), timeout)
}
def newInstance[T](intf: Class[T], target: AnyRef): T = def newRemoteInstance[T](intfClass: Class[T], targetClass: Class[_], hostname: String, port: Int): T = {
newInstance(intf, target, actorOf(new Dispatcher(false)), None, Actor.TIMEOUT) newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)
}
def newRemoteInstance[T](target: Class[T], timeout: Long, hostname: String, port: Int): T = def newInstance[T](intfClass: Class[T], targetClass: Class[_], config: TypedActorConfiguration): T = {
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)), 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, config._shutdownCallback)) val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback))
if (config._messageDispatcher.isDefined) { if (config._messageDispatcher.isDefined) actor.dispatcher = config._messageDispatcher.get
actor.dispatcher = config._messageDispatcher.get newInstance(intfClass, newTypedActor(targetClass), actor, config._host, config.timeout)
}
newInstance(target, actor, config._host, config.timeout)
} }
def newInstance[T](intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration): T = { private[akka] def newInstance[T](intfClass: Class[T], targetInstance: TypedActor, actorRef: ActorRef,
val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback)) remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
if (config._messageDispatcher.isDefined) { val context = injectTypedActorContext(targetInstance)
actor.dispatcher = config._messageDispatcher.get val proxy = Proxy.newInstance(Array(intfClass), Array(targetInstance), true, false)
} actorRef.actor.asInstanceOf[Dispatcher].initialize(targetInstance.getClass, targetInstance, context)
newInstance(intf, target, actor, config._host, config.timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(target, actorOf(new Dispatcher(false, restartCallbacks)), None, timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(intf, target, actorOf(new Dispatcher(false, restartCallbacks)), None, timeout)
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean): T =
newInstance(target, actorOf(new Dispatcher(transactionRequired, None)), None, timeout)
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), None, timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean): T =
newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, None)), None, timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), None, timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, hostname: String, port: Int): T =
newInstance(intf, target, actorOf(new Dispatcher(false, None)), Some(new InetSocketAddress(hostname, port)), timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(intf, target, actorOf(new Dispatcher(false, restartCallbacks)), Some(new InetSocketAddress(hostname, port)), timeout)
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, hostname: String, port: Int): T =
newInstance(target, actorOf(new Dispatcher(transactionRequired, None)), Some(new InetSocketAddress(hostname, port)), timeout)
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), Some(new InetSocketAddress(hostname, port)), timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, hostname: String, port: Int): T =
newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, None)), Some(new InetSocketAddress(hostname, port)), timeout)
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T =
newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), Some(new InetSocketAddress(hostname, port)), timeout)
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher): T = {
val actor = actorOf(new Dispatcher(false, None))
actor.dispatcher = dispatcher
newInstance(target, actor, None, timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(false, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(target, actor, None, timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher): T = {
val actor = actorOf(new Dispatcher(false, None))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, None, timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long,
dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(false, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, None, timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher): T = {
val actor = actorOf(new Dispatcher(transactionRequired, None))
actor.dispatcher = dispatcher
newInstance(target, actor, None, timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean,
dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(target, actor, None, timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher): T = {
val actor = actorOf(new Dispatcher(transactionRequired, None))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, None, timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean,
dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, None, timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
val actor = actorOf(new Dispatcher(false, None))
actor.dispatcher = dispatcher
newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher,
hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(false, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
val actor = actorOf(new Dispatcher(false, None))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher,
hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(false, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean,
dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
val actor = actorOf(new Dispatcher(transactionRequired, None))
actor.dispatcher = dispatcher
newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher,
hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean,
dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
val actor = actorOf(new Dispatcher(transactionRequired, None))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
@deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean,
dispatcher: MessageDispatcher, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
actor.dispatcher = dispatcher
newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
}
private[akka] def newInstance[T](target: Class[T], actorRef: ActorRef, remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
val proxy = Proxy.newInstance(target, true, false)
val context = injectActiveObjectContext(proxy)
actorRef.actor.asInstanceOf[Dispatcher].initialize(target, proxy, context)
actorRef.timeout = timeout actorRef.timeout = timeout
if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get) if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get)
AspectInitRegistry.register(proxy, AspectInit(target, actorRef, remoteAddress, timeout)) AspectInitRegistry.register(proxy, AspectInit(intfClass, targetInstance, actorRef, remoteAddress, timeout))
actorRef.start actorRef.start
proxy.asInstanceOf[T] proxy.asInstanceOf[T]
} }
private[akka] def newInstance[T](intf: Class[T], target: AnyRef, actorRef: ActorRef, // NOTE: currently not used - but keep it around
remoteAddress: Option[InetSocketAddress], timeout: Long): T = { private[akka] def newInstance[T <: TypedActor](
val context = injectActiveObjectContext(target) targetClass: Class[T], actorRef: ActorRef, remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
val proxy = Proxy.newInstance(Array(intf), Array(target), true, false) val proxy = {
actorRef.actor.asInstanceOf[Dispatcher].initialize(target.getClass, target, context) val instance = Proxy.newInstance(targetClass, true, false)
if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor]
else throw new IllegalActorStateException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'")
}
val context = injectTypedActorContext(proxy)
actorRef.actor.asInstanceOf[Dispatcher].initialize(targetClass, proxy, context)
actorRef.timeout = timeout actorRef.timeout = timeout
if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get) if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get)
AspectInitRegistry.register(proxy, AspectInit(intf, actorRef, remoteAddress, timeout)) AspectInitRegistry.register(proxy, AspectInit(targetClass, proxy, actorRef, remoteAddress, timeout))
actorRef.start actorRef.start
proxy.asInstanceOf[T] proxy.asInstanceOf[T]
} }
@ -391,120 +288,150 @@ object ActiveObject extends Logging {
} }
/** /**
* Get the underlying dispatcher actor for the given active object. * Get the underlying dispatcher actor for the given typed actor.
*/ */
def actorFor(obj: AnyRef): Option[ActorRef] = def actorFor(obj: AnyRef): Option[ActorRef] =
ActorRegistry.actorsFor(classOf[Dispatcher]).find(a => a.actor.asInstanceOf[Dispatcher].target == Some(obj)) ActorRegistry.actorsFor(classOf[Dispatcher]).find(a => a.actor.asInstanceOf[Dispatcher].target == Some(obj))
/** /**
* Links an other active object to this active object. * Links an other typed actor to this typed actor.
* @param supervisor the supervisor active object * @param supervisor the supervisor typed actor
* @param supervised the active object to link * @param supervised the typed actor to link
*/ */
def link(supervisor: AnyRef, supervised: AnyRef) = { def link(supervisor: AnyRef, supervised: AnyRef) = {
val supervisorActor = actorFor(supervisor).getOrElse( val supervisorActor = actorFor(supervisor).getOrElse(
throw new IllegalActorStateException("Can't link when the supervisor is not an active object")) throw new IllegalActorStateException("Can't link when the supervisor is not an typed actor"))
val supervisedActor = actorFor(supervised).getOrElse( val supervisedActor = actorFor(supervised).getOrElse(
throw new IllegalActorStateException("Can't link when the supervised is not an active object")) throw new IllegalActorStateException("Can't link when the supervised is not an typed actor"))
supervisorActor.link(supervisedActor) supervisorActor.link(supervisedActor)
} }
/** /**
* Links an other active object to this active object and sets the fault handling for the supervisor. * Links an other typed actor to this typed actor and sets the fault handling for the supervisor.
* @param supervisor the supervisor active object * @param supervisor the supervisor typed actor
* @param supervised the active object to link * @param supervised the typed actor to link
* @param handler fault handling strategy * @param handler fault handling strategy
* @param trapExceptions array of exceptions that should be handled by the supervisor * @param trapExceptions array of exceptions that should be handled by the supervisor
*/ */
def link(supervisor: AnyRef, supervised: AnyRef, handler: FaultHandlingStrategy, trapExceptions: Array[Class[_ <: Throwable]]) = { def link(supervisor: AnyRef, supervised: AnyRef,
handler: FaultHandlingStrategy, trapExceptions: Array[Class[_ <: Throwable]]) = {
val supervisorActor = actorFor(supervisor).getOrElse( val supervisorActor = actorFor(supervisor).getOrElse(
throw new IllegalActorStateException("Can't link when the supervisor is not an active object")) throw new IllegalActorStateException("Can't link when the supervisor is not an typed actor"))
val supervisedActor = actorFor(supervised).getOrElse( val supervisedActor = actorFor(supervised).getOrElse(
throw new IllegalActorStateException("Can't link when the supervised is not an active object")) throw new IllegalActorStateException("Can't link when the supervised is not an typed actor"))
supervisorActor.trapExit = trapExceptions.toList supervisorActor.trapExit = trapExceptions.toList
supervisorActor.faultHandler = Some(handler) supervisorActor.faultHandler = Some(handler)
supervisorActor.link(supervisedActor) supervisorActor.link(supervisedActor)
} }
/** /**
* Unlink the supervised active object from the supervisor. * Unlink the supervised typed actor from the supervisor.
* @param supervisor the supervisor active object * @param supervisor the supervisor typed actor
* @param supervised the active object to unlink * @param supervised the typed actor to unlink
*/ */
def unlink(supervisor: AnyRef, supervised: AnyRef) = { def unlink(supervisor: AnyRef, supervised: AnyRef) = {
val supervisorActor = actorFor(supervisor).getOrElse( val supervisorActor = actorFor(supervisor).getOrElse(
throw new IllegalActorStateException("Can't unlink when the supervisor is not an active object")) throw new IllegalActorStateException("Can't unlink when the supervisor is not an typed actor"))
val supervisedActor = actorFor(supervised).getOrElse( val supervisedActor = actorFor(supervised).getOrElse(
throw new IllegalActorStateException("Can't unlink when the supervised is not an active object")) throw new IllegalActorStateException("Can't unlink when the supervised is not an typed actor"))
supervisorActor.unlink(supervisedActor) supervisorActor.unlink(supervisedActor)
} }
/** /**
* Sets the trap exit for the given supervisor active object. * Sets the trap exit for the given supervisor typed actor.
* @param supervisor the supervisor active object * @param supervisor the supervisor typed actor
* @param trapExceptions array of exceptions that should be handled by the supervisor * @param trapExceptions array of exceptions that should be handled by the supervisor
*/ */
def trapExit(supervisor: AnyRef, trapExceptions: Array[Class[_ <: Throwable]]) = { def trapExit(supervisor: AnyRef, trapExceptions: Array[Class[_ <: Throwable]]) = {
val supervisorActor = actorFor(supervisor).getOrElse( val supervisorActor = actorFor(supervisor).getOrElse(
throw new IllegalActorStateException("Can't set trap exceptions when the supervisor is not an active object")) throw new IllegalActorStateException("Can't set trap exceptions when the supervisor is not an typed actor"))
supervisorActor.trapExit = trapExceptions.toList supervisorActor.trapExit = trapExceptions.toList
this this
} }
/** /**
* Sets the fault handling strategy for the given supervisor active object. * Sets the fault handling strategy for the given supervisor typed actor.
* @param supervisor the supervisor active object * @param supervisor the supervisor typed actor
* @param handler fault handling strategy * @param handler fault handling strategy
*/ */
def faultHandler(supervisor: AnyRef, handler: FaultHandlingStrategy) = { def faultHandler(supervisor: AnyRef, handler: FaultHandlingStrategy) = {
val supervisorActor = actorFor(supervisor).getOrElse( val supervisorActor = actorFor(supervisor).getOrElse(
throw new IllegalActorStateException("Can't set fault handler when the supervisor is not an active object")) throw new IllegalActorStateException("Can't set fault handler when the supervisor is not an typed actor"))
supervisorActor.faultHandler = Some(handler) supervisorActor.faultHandler = Some(handler)
this this
} }
private def injectActiveObjectContext(activeObject: AnyRef): Option[ActiveObjectContext] = { private def injectTypedActorContext(activeObject: AnyRef): Option[TypedActorContext] = {
def injectActiveObjectContext0(activeObject: AnyRef, clazz: Class[_]): Option[ActiveObjectContext] = { def injectTypedActorContext0(activeObject: AnyRef, clazz: Class[_]): Option[TypedActorContext] = {
val contextField = clazz.getDeclaredFields.toList.find(_.getType == classOf[ActiveObjectContext]) val contextField = clazz.getDeclaredFields.toList.find(_.getType == classOf[TypedActorContext])
if (contextField.isDefined) { if (contextField.isDefined) {
contextField.get.setAccessible(true) contextField.get.setAccessible(true)
val context = new ActiveObjectContext val context = new TypedActorContext
contextField.get.set(activeObject, context) contextField.get.set(activeObject, context)
Some(context) Some(context)
} else { } else {
val parent = clazz.getSuperclass val parent = clazz.getSuperclass
if (parent != null) injectActiveObjectContext0(activeObject, parent) if (parent != null) injectTypedActorContext0(activeObject, parent)
else { else {
log.ifTrace("Can't set 'ActiveObjectContext' for ActiveObject [" + log.ifTrace("Can't set 'TypedActorContext' for TypedActor [" +
activeObject.getClass.getName + activeObject.getClass.getName +
"] since no field of this type could be found.") "] since no field of this type could be found.")
None None
} }
} }
} }
injectActiveObjectContext0(activeObject, activeObject.getClass) injectTypedActorContext0(activeObject, activeObject.getClass)
}
private[akka] def newTypedActor(targetClass: Class[_]): TypedActor = {
val instance = targetClass.newInstance
if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor]
else throw new IllegalArgumentException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'")
} }
private[akka] def supervise(restartStrategy: RestartStrategy, components: List[Supervise]): Supervisor = private[akka] def supervise(restartStrategy: RestartStrategy, components: List[Supervise]): Supervisor =
Supervisor(SupervisorConfig(restartStrategy, components)) Supervisor(SupervisorConfig(restartStrategy, components))
} }
/**
* Internal helper class to help pass the contextual information between threads.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
private[akka] object TypedActorContext {
import scala.util.DynamicVariable
private[actor] val sender = new DynamicVariable[AnyRef](null)
private[actor] val senderFuture = new DynamicVariable[CompletableFuture[Any]](null)
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
object Annotations {
val transactionrequired = classOf[transactionrequired]
val prerestart = classOf[prerestart]
val postrestart = classOf[postrestart]
val shutdown = classOf[shutdown]
val inittransactionalstate = classOf[inittransactionalstate]
}
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
private[akka] object AspectInitRegistry extends ListenerManagement { private[akka] object AspectInitRegistry extends ListenerManagement {
private val initializations = new java.util.concurrent.ConcurrentHashMap[AnyRef, AspectInit] private val initializations = new java.util.concurrent.ConcurrentHashMap[AnyRef, AspectInit]
def initFor(target: AnyRef) = { def initFor(proxy: AnyRef) = initializations.get(proxy)
initializations.get(target)
}
def register(target: AnyRef, init: AspectInit) = { def register(proxy: AnyRef, init: AspectInit) = {
val res = initializations.put(target, init) val res = initializations.put(proxy, init)
foreachListener(_ ! AspectInitRegistered(target, init)) foreachListener(_ ! AspectInitRegistered(proxy, init))
res res
} }
def unregister(target: AnyRef) = { def unregister(proxy: AnyRef) = {
val res = initializations.remove(target) val res = initializations.remove(proxy)
foreachListener(_ ! AspectInitUnregistered(target, res)) foreachListener(_ ! AspectInitUnregistered(proxy, res))
res res
} }
} }
@ -513,40 +440,50 @@ private[akka] sealed trait AspectInitRegistryEvent
private[akka] case class AspectInitRegistered(proxy: AnyRef, init: AspectInit) extends AspectInitRegistryEvent private[akka] case class AspectInitRegistered(proxy: AnyRef, init: AspectInit) extends AspectInitRegistryEvent
private[akka] case class AspectInitUnregistered(proxy: AnyRef, init: AspectInit) extends AspectInitRegistryEvent private[akka] case class AspectInitUnregistered(proxy: AnyRef, init: AspectInit) extends AspectInitRegistryEvent
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
private[akka] sealed case class AspectInit( private[akka] sealed case class AspectInit(
val target: Class[_], val interfaceClass: Class[_],
val targetInstance: TypedActor,
val actorRef: ActorRef, val actorRef: ActorRef,
val remoteAddress: Option[InetSocketAddress], val remoteAddress: Option[InetSocketAddress],
val timeout: Long) { val timeout: Long) {
def this(target: Class[_], actorRef: ActorRef, timeout: Long) = this(target, actorRef, None, timeout) def this(interfaceClass: Class[_], targetInstance: TypedActor, actorRef: ActorRef, timeout: Long) =
this(interfaceClass, targetInstance, actorRef, None, timeout)
} }
/** /**
* AspectWerkz Aspect that is turning POJOs into Active Object. * AspectWerkz Aspect that is turning POJO into TypedActor.
* Is deployed on a 'per-instance' basis. * <p/>
* Is deployed on a 'perInstance' basis with the pointcut 'execution(* *.*(..))',
* e.g. all methods on the instance.
* *
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
@Aspect("perInstance") @Aspect("perInstance")
private[akka] sealed class ActiveObjectAspect { private[akka] sealed class TypedActorAspect {
@volatile private var isInitialized = false @volatile private var isInitialized = false
@volatile private var isStopped = false @volatile private var isStopped = false
private var target: Class[_] = _ private var interfaceClass: Class[_] = _
private var targetInstance: TypedActor = _
private var actorRef: ActorRef = _ private var actorRef: ActorRef = _
private var remoteAddress: Option[InetSocketAddress] = _ private var remoteAddress: Option[InetSocketAddress] = _
private var timeout: Long = _ private var timeout: Long = _
@volatile private var instance: AnyRef = _ private var uuid: String = _
@volatile private var instance: TypedActor = _
@Around("execution(* *.*(..))") @Around("execution(* *.*(..))")
def invoke(joinPoint: JoinPoint): AnyRef = { def invoke(joinPoint: JoinPoint): AnyRef = {
if (!isInitialized) { if (!isInitialized) {
val init = AspectInitRegistry.initFor(joinPoint.getThis) val init = AspectInitRegistry.initFor(joinPoint.getThis)
target = init.target interfaceClass = init.interfaceClass
targetInstance = init.targetInstance
uuid = targetInstance.uuid
actorRef = init.actorRef actorRef = init.actorRef
remoteAddress = init.remoteAddress remoteAddress = init.remoteAddress
timeout = init.timeout timeout = init.timeout
isInitialized = true isInitialized = true
} }
dispatch(joinPoint) dispatch(joinPoint)
} }
@ -559,15 +496,17 @@ private[akka] sealed class ActiveObjectAspect {
private def localDispatch(joinPoint: JoinPoint): AnyRef = { private def localDispatch(joinPoint: JoinPoint): AnyRef = {
val rtti = joinPoint.getRtti.asInstanceOf[MethodRtti] val rtti = joinPoint.getRtti.asInstanceOf[MethodRtti]
val isOneWay = isVoid(rtti) val isOneWay = isVoid(rtti)
val sender = ActiveObjectContext.sender.value val sender = TypedActorContext.sender.value
val senderFuture = ActiveObjectContext.senderFuture.value val senderFuture = TypedActorContext.senderFuture.value
if (!actorRef.isRunning && !isStopped) { if (!actorRef.isRunning && !isStopped) {
isStopped = true isStopped = true
joinPoint.proceed joinPoint.proceed
} else if (isOneWay) { } else if (isOneWay) {
actorRef ! Invocation(joinPoint, true, true, sender, senderFuture) actorRef ! Invocation(joinPoint, true, true, sender, senderFuture)
null.asInstanceOf[AnyRef] null.asInstanceOf[AnyRef]
} else { } else {
val result = (actorRef !! (Invocation(joinPoint, false, isOneWay, sender, senderFuture), timeout)).as[AnyRef] val result = (actorRef !! (Invocation(joinPoint, false, isOneWay, sender, senderFuture), timeout)).as[AnyRef]
if (result.isDefined) result.get if (result.isDefined) result.get
@ -579,20 +518,32 @@ private[akka] sealed class ActiveObjectAspect {
val rtti = joinPoint.getRtti.asInstanceOf[MethodRtti] val rtti = joinPoint.getRtti.asInstanceOf[MethodRtti]
val isOneWay = isVoid(rtti) val isOneWay = isVoid(rtti)
val (message: Array[AnyRef], isEscaped) = escapeArguments(rtti.getParameterValues) val (message: Array[AnyRef], isEscaped) = escapeArguments(rtti.getParameterValues)
val typedActorInfo = TypedActorInfoProtocol.newBuilder
.setInterface(interfaceClass.getName)
.setMethod(rtti.getMethod.getName)
.build
val actorInfo = ActorInfoProtocol.newBuilder
.setUuid(uuid)
.setTarget(targetInstance.getClass.getName)
.setTimeout(timeout)
.setActorType(ActorType.TYPED_ACTOR)
.build
val requestBuilder = RemoteRequestProtocol.newBuilder val requestBuilder = RemoteRequestProtocol.newBuilder
.setId(RemoteRequestProtocolIdFactory.nextId) .setId(RemoteRequestProtocolIdFactory.nextId)
.setMessage(MessageSerializer.serialize(message)) .setMessage(MessageSerializer.serialize(message))
.setMethod(rtti.getMethod.getName) .setActorInfo(actorInfo)
.setTarget(target.getName)
.setUuid(actorRef.uuid)
.setTimeout(timeout)
.setIsActor(false)
.setIsOneWay(isOneWay) .setIsOneWay(isOneWay)
.setIsEscaped(false)
val id = actorRef.registerSupervisorAsRemoteActor val id = actorRef.registerSupervisorAsRemoteActor
if (id.isDefined) requestBuilder.setSupervisorUuid(id.get) if (id.isDefined) requestBuilder.setSupervisorUuid(id.get)
val remoteMessage = requestBuilder.build val remoteMessage = requestBuilder.build
val future = RemoteClient.clientFor(remoteAddress.get).send(remoteMessage, None) val future = RemoteClient.clientFor(remoteAddress.get).send(remoteMessage, None)
if (isOneWay) null // for void methods if (isOneWay) null // for void methods
else { else {
if (future.isDefined) { if (future.isDefined) {
@ -616,9 +567,9 @@ private[akka] sealed class ActiveObjectAspect {
var isEscaped = false var isEscaped = false
val escapedArgs = for (arg <- args) yield { val escapedArgs = for (arg <- args) yield {
val clazz = arg.getClass val clazz = arg.getClass
if (clazz.getName.contains(ActiveObject.AW_PROXY_PREFIX)) { if (clazz.getName.contains(TypedActor.AW_PROXY_PREFIX)) {
isEscaped = true isEscaped = true
ActiveObject.AW_PROXY_PREFIX + clazz.getSuperclass.getName TypedActor.AW_PROXY_PREFIX + clazz.getSuperclass.getName
} else arg } else arg
} }
(escapedArgs, isEscaped) (escapedArgs, isEscaped)
@ -685,20 +636,21 @@ private[akka] class Dispatcher(transactionalRequired: Boolean,
private var preRestart: Option[Method] = None private var preRestart: Option[Method] = None
private var postRestart: Option[Method] = None private var postRestart: Option[Method] = None
private var initTxState: Option[Method] = None private var initTxState: Option[Method] = None
private var context: Option[ActiveObjectContext] = None private var context: Option[TypedActorContext] = None
private var targetClass:Class[_] = _ private var targetClass: Class[_] = _
def this(transactionalRequired: Boolean) = this(transactionalRequired,None) def this(transactionalRequired: Boolean) = this(transactionalRequired,None)
private[actor] def initialize(targetClass: Class[_], targetInstance: AnyRef, ctx: Option[ActiveObjectContext]) = { private[actor] def initialize(targetClass: Class[_], proxy: AnyRef, ctx: Option[TypedActorContext]) = {
if (transactionalRequired || targetClass.isAnnotationPresent(Annotations.transactionrequired)) if (transactionalRequired || targetClass.isAnnotationPresent(Annotations.transactionrequired))
self.makeTransactionRequired self.makeTransactionRequired
self.id = targetClass.getName self.id = targetClass.getName
this.targetClass = targetClass this.targetClass = targetClass
target = Some(targetInstance) target = Some(proxy)
context = ctx context = ctx
val methods = targetInstance.getClass.getDeclaredMethods.toList val proxyClass = proxy.getClass
val methods = proxyClass.getDeclaredMethods.toList
if (self.lifeCycle.isEmpty) self.lifeCycle = Some(LifeCycle(Permanent)) if (self.lifeCycle.isEmpty) self.lifeCycle = Some(LifeCycle(Permanent))
@ -707,12 +659,12 @@ private[akka] class Dispatcher(transactionalRequired: Boolean,
case None => {} case None => {}
case Some(RestartCallbacks(pre, post)) => case Some(RestartCallbacks(pre, post)) =>
preRestart = Some(try { preRestart = Some(try {
targetInstance.getClass.getDeclaredMethod(pre, ZERO_ITEM_CLASS_ARRAY: _*) proxyClass.getDeclaredMethod(pre, ZERO_ITEM_CLASS_ARRAY: _*)
} catch { case e => throw new IllegalActorStateException( } catch { case e => throw new IllegalActorStateException(
"Could not find pre restart method [" + pre + "] \nin [" + "Could not find pre restart method [" + pre + "] \nin [" +
targetClass.getName + "]. \nIt must have a zero argument definition.") }) targetClass.getName + "]. \nIt must have a zero argument definition.") })
postRestart = Some(try { postRestart = Some(try {
targetInstance.getClass.getDeclaredMethod(post, ZERO_ITEM_CLASS_ARRAY: _*) proxyClass.getDeclaredMethod(post, ZERO_ITEM_CLASS_ARRAY: _*)
} catch { case e => throw new IllegalActorStateException( } catch { case e => throw new IllegalActorStateException(
"Could not find post restart method [" + post + "] \nin [" + "Could not find post restart method [" + post + "] \nin [" +
targetClass.getName + "]. \nIt must have a zero argument definition.") }) targetClass.getName + "]. \nIt must have a zero argument definition.") })
@ -722,7 +674,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean,
case None => {} case None => {}
case Some(ShutdownCallback(down)) => case Some(ShutdownCallback(down)) =>
zhutdown = Some(try { zhutdown = Some(try {
targetInstance.getClass.getDeclaredMethod(down, ZERO_ITEM_CLASS_ARRAY: _*) proxyClass.getDeclaredMethod(down, ZERO_ITEM_CLASS_ARRAY: _*)
} catch { case e => throw new IllegalStateException( } catch { case e => throw new IllegalStateException(
"Could not find shutdown method [" + down + "] \nin [" + "Could not find shutdown method [" + down + "] \nin [" +
targetClass.getName + "]. \nIt must have a zero argument definition.") }) targetClass.getName + "]. \nIt must have a zero argument definition.") })
@ -760,13 +712,13 @@ private[akka] class Dispatcher(transactionalRequired: Boolean,
def receive = { def receive = {
case invocation @ Invocation(joinPoint, isOneWay, _, sender, senderFuture) => case invocation @ Invocation(joinPoint, isOneWay, _, sender, senderFuture) =>
ActiveObject.log.ifTrace("Invoking active object with message:\n" + invocation) TypedActor.log.ifTrace("Invoking typed actor with message:\n" + invocation)
context.foreach { ctx => context.foreach { ctx =>
if (sender ne null) ctx._sender = sender if (sender ne null) ctx._sender = sender
if (senderFuture ne null) ctx._senderFuture = senderFuture if (senderFuture ne null) ctx._senderFuture = senderFuture
} }
ActiveObjectContext.sender.value = joinPoint.getThis // set next sender TypedActorContext.sender.value = joinPoint.getThis // set next sender
self.senderFuture.foreach(ActiveObjectContext.senderFuture.value = _) self.senderFuture.foreach(TypedActorContext.senderFuture.value = _)
if (Actor.SERIALIZE_MESSAGES) serializeArguments(joinPoint) if (Actor.SERIALIZE_MESSAGES) serializeArguments(joinPoint)
if (isOneWay) joinPoint.proceed if (isOneWay) joinPoint.proceed
else self.reply(joinPoint.proceed) else self.reply(joinPoint.proceed)
@ -843,7 +795,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean,
!arg.isInstanceOf[java.lang.Character]) { !arg.isInstanceOf[java.lang.Character]) {
hasMutableArgument = true hasMutableArgument = true
} }
if (arg.getClass.getName.contains(ActiveObject.AW_PROXY_PREFIX)) unserializable = true if (arg.getClass.getName.contains(TypedActor.AW_PROXY_PREFIX)) unserializable = true
} }
if (!unserializable && hasMutableArgument) { if (!unserializable && hasMutableArgument) {
val copyOfArgs = Serializer.Java.deepClone(args) val copyOfArgs = Serializer.Java.deepClone(args)

View file

@ -5,7 +5,7 @@
package se.scalablesolutions.akka.config package se.scalablesolutions.akka.config
/* /*
import se.scalablesolutions.akka.kernel.{ActiveObject, ActiveObjectProxy} import se.scalablesolutions.akka.kernel.{TypedActor, TypedActorProxy}
import com.google.inject.{AbstractModule} import com.google.inject.{AbstractModule}
import java.util.{List => JList, ArrayList} import java.util.{List => JList, ArrayList}
import scala.reflect.BeanProperty import scala.reflect.BeanProperty
@ -55,6 +55,6 @@ class Component(@BeanProperty val intf: Class[_],
@BeanProperty val target: Class[_], @BeanProperty val target: Class[_],
@BeanProperty val lifeCycle: LifeCycle, @BeanProperty val lifeCycle: LifeCycle,
@BeanProperty val timeout: Int) extends Server { @BeanProperty val timeout: Int) extends Server {
def newWorker(proxy: ActiveObjectProxy) = se.scalablesolutions.akka.kernel.Supervise(proxy.server, lifeCycle.transform) def newWorker(proxy: TypedActorProxy) = se.scalablesolutions.akka.kernel.Supervise(proxy.server, lifeCycle.transform)
} }
*/ */

View file

@ -6,14 +6,14 @@ package se.scalablesolutions.akka.config
import ScalaConfig.{RestartStrategy, Component} import ScalaConfig.{RestartStrategy, Component}
private[akka] trait ActiveObjectConfiguratorBase { private[akka] trait TypedActorConfiguratorBase {
def getExternalDependency[T](clazz: Class[T]): T def getExternalDependency[T](clazz: Class[T]): T
def configure(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectConfiguratorBase def configure(restartStrategy: RestartStrategy, components: List[Component]): TypedActorConfiguratorBase
def inject: ActiveObjectConfiguratorBase def inject: TypedActorConfiguratorBase
def supervise: ActiveObjectConfiguratorBase def supervise: TypedActorConfiguratorBase
def reset def reset

View file

@ -12,54 +12,55 @@ import java.util.{ArrayList}
import com.google.inject._ import com.google.inject._
/** /**
* Configurator for the Active Objects. Used to do declarative configuration of supervision. * Configurator for the TypedActors. Used to do declarative configuration of supervision.
* It also does dependency injection with and into Active Objects using dependency injection * It also does dependency injection with and into TypedActors using dependency injection
* frameworks such as Google Guice or Spring. * frameworks such as Google Guice or Spring.
* <p/> * <p/>
* If you don't want declarative configuration then you should use the <code>ActiveObject</code> * If you don't want declarative configuration then you should use the <code>TypedActor</code>
* factory methods. * factory methods.
* *
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
class ActiveObjectConfigurator { class TypedActorConfigurator {
import scala.collection.JavaConversions._ import scala.collection.JavaConversions._
// TODO: make pluggable once we have f.e a SpringConfigurator // TODO: make pluggable once we have f.e a SpringConfigurator
private val INSTANCE = new ActiveObjectGuiceConfigurator private val INSTANCE = new TypedActorGuiceConfigurator
/** /**
* Returns the a list with all active objects that has been put under supervision for the class specified. * Returns the a list with all typed actors that has been put under supervision for the class specified.
* *
* @param clazz the class for the active object * @param clazz the class for the typed actor
* @return a list with all the active objects for the class * @return a list with all the typed actors for the class
*/ */
def getInstances[T](clazz: Class[T]): JList[T] = INSTANCE.getInstance(clazz).foldLeft(new ArrayList[T]){ (l, i) => l add i ; l } def getInstances[T](clazz: Class[T]): JList[T] =
INSTANCE.getInstance(clazz).foldLeft(new ArrayList[T]){ (l, i) => l add i ; l }
/** /**
* Returns the first item in a list of all active objects that has been put under supervision for the class specified. * Returns the first item in a list of all typed actors that has been put under supervision for the class specified.
* *
* @param clazz the class for the active object * @param clazz the class for the typed actor
* @return the active object for the class * @return the typed actor for the class
*/ */
def getInstance[T](clazz: Class[T]): T = INSTANCE.getInstance(clazz).head def getInstance[T](clazz: Class[T]): T = INSTANCE.getInstance(clazz).head
def configure(restartStrategy: RestartStrategy, components: Array[Component]): ActiveObjectConfigurator = { def configure(restartStrategy: RestartStrategy, components: Array[Component]): TypedActorConfigurator = {
INSTANCE.configure( INSTANCE.configure(
restartStrategy.transform, restartStrategy.transform,
components.toList.asInstanceOf[scala.List[Component]].map(_.transform)) components.toList.asInstanceOf[scala.List[Component]].map(_.transform))
this this
} }
def inject: ActiveObjectConfigurator = { def inject: TypedActorConfigurator = {
INSTANCE.inject INSTANCE.inject
this this
} }
def supervise: ActiveObjectConfigurator = { def supervise: TypedActorConfigurator = {
INSTANCE.supervise INSTANCE.supervise
this this
} }
def addExternalGuiceModule(module: Module): ActiveObjectConfigurator = { def addExternalGuiceModule(module: Module): TypedActorConfigurator = {
INSTANCE.addExternalGuiceModule(module) INSTANCE.addExternalGuiceModule(module)
this this
} }

View file

@ -7,7 +7,7 @@ package se.scalablesolutions.akka.config
import com.google.inject._ import com.google.inject._
import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.config.ScalaConfig._
import se.scalablesolutions.akka.actor.{Supervisor, ActiveObject, Dispatcher, ActorRef, Actor, IllegalActorStateException} import se.scalablesolutions.akka.actor.{Supervisor, TypedActor, Dispatcher, ActorRef, Actor, IllegalActorStateException}
import se.scalablesolutions.akka.remote.RemoteServer import se.scalablesolutions.akka.remote.RemoteServer
import se.scalablesolutions.akka.util.Logging import se.scalablesolutions.akka.util.Logging
@ -17,12 +17,12 @@ import java.net.InetSocketAddress
import java.lang.reflect.Method import java.lang.reflect.Method
/** /**
* This is an class for internal usage. Instead use the <code>se.scalablesolutions.akka.config.ActiveObjectConfigurator</code> * This is an class for internal usage. Instead use the <code>se.scalablesolutions.akka.config.TypedActorConfigurator</code>
* class for creating ActiveObjects. * class for creating TypedActors.
* *
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfiguratorBase with Logging { private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBase with Logging {
private var injector: Injector = _ private var injector: Injector = _
private var supervisor: Option[Supervisor] = None private var supervisor: Option[Supervisor] = None
private var restartStrategy: RestartStrategy = _ private var restartStrategy: RestartStrategy = _
@ -37,11 +37,11 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
/** /**
* Returns the active abject that has been put under supervision for the class specified. * Returns the active abject that has been put under supervision for the class specified.
* *
* @param clazz the class for the active object * @param clazz the class for the typed actor
* @return the active objects for the class * @return the typed actors for the class
*/ */
def getInstance[T](clazz: Class[T]): List[T] = synchronized { def getInstance[T](clazz: Class[T]): List[T] = synchronized {
log.debug("Retrieving active object [%s]", clazz.getName) log.debug("Retrieving typed actor [%s]", clazz.getName)
if (injector eq null) throw new IllegalActorStateException( if (injector eq null) throw new IllegalActorStateException(
"inject() and/or supervise() must be called before invoking getInstance(clazz)") "inject() and/or supervise() must be called before invoking getInstance(clazz)")
val (proxy, targetInstance, component) = val (proxy, targetInstance, component) =
@ -67,7 +67,7 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
} }
override def configure(restartStrategy: RestartStrategy, components: List[Component]): override def configure(restartStrategy: RestartStrategy, components: List[Component]):
ActiveObjectConfiguratorBase = synchronized { TypedActorConfiguratorBase = synchronized {
this.restartStrategy = restartStrategy this.restartStrategy = restartStrategy
this.components = components.toArray.toList.asInstanceOf[List[Component]] this.components = components.toArray.toList.asInstanceOf[List[Component]]
bindings = for (component <- this.components) yield { bindings = for (component <- this.components) yield {
@ -76,12 +76,14 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
} }
val deps = new java.util.ArrayList[DependencyBinding](bindings.size) val deps = new java.util.ArrayList[DependencyBinding](bindings.size)
for (b <- bindings) deps.add(b) for (b <- bindings) deps.add(b)
modules.add(new ActiveObjectGuiceModule(deps)) modules.add(new TypedActorGuiceModule(deps))
this this
} }
private def newSubclassingProxy(component: Component): DependencyBinding = { private def newSubclassingProxy(component: Component): DependencyBinding = {
val targetClass = component.target val targetClass =
if (component.target.isInstanceOf[Class[_ <: TypedActor]]) component.target.asInstanceOf[Class[_ <: TypedActor]]
else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor")
val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired, val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired,
component.lifeCycle.restartCallbacks, component.lifeCycle.restartCallbacks,
component.lifeCycle.shutdownCallback)) component.lifeCycle.shutdownCallback))
@ -90,8 +92,8 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
if (component.remoteAddress.isDefined) if (component.remoteAddress.isDefined)
Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port))
else None else None
val proxy = ActiveObject.newInstance(targetClass, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] val proxy = TypedActor.newInstance(targetClass, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef]
remoteAddress.foreach(address => RemoteServer.registerActiveObject(address, targetClass.getName, proxy)) remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy))
supervised ::= Supervise(actorRef, component.lifeCycle) supervised ::= Supervise(actorRef, component.lifeCycle)
activeObjectRegistry.put(targetClass, (proxy, proxy, component)) activeObjectRegistry.put(targetClass, (proxy, proxy, component))
new DependencyBinding(targetClass, proxy) new DependencyBinding(targetClass, proxy)
@ -99,7 +101,12 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
private def newDelegatingProxy(component: Component): DependencyBinding = { private def newDelegatingProxy(component: Component): DependencyBinding = {
val targetClass = component.intf.get val targetClass = component.intf.get
val targetInstance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry val instance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry
val targetInstance =
if (instance.isInstanceOf[TypedActor]) component.target.asInstanceOf[TypedActor]
else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor")
if (!component.target.isInstanceOf[TypedActor]) throw new IllegalArgumentException(
"TypedActor [" + component.target + "] must be a subclass of TypedActor")
component.target.getConstructor(Array[Class[_]](): _*).setAccessible(true) component.target.getConstructor(Array[Class[_]](): _*).setAccessible(true)
val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired, val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired,
component.lifeCycle.restartCallbacks, component.lifeCycle.restartCallbacks,
@ -109,23 +116,23 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
if (component.remoteAddress.isDefined) if (component.remoteAddress.isDefined)
Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port))
else None else None
val proxy = ActiveObject.newInstance( val proxy = TypedActor.newInstance(
targetClass, targetInstance, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] targetClass, targetInstance, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef]
remoteAddress.foreach(address => RemoteServer.registerActiveObject(address, targetClass.getName, proxy)) remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy))
supervised ::= Supervise(actorRef, component.lifeCycle) supervised ::= Supervise(actorRef, component.lifeCycle)
activeObjectRegistry.put(targetClass, (proxy, targetInstance, component)) activeObjectRegistry.put(targetClass, (proxy, targetInstance, component))
new DependencyBinding(targetClass, proxy) new DependencyBinding(targetClass, proxy)
} }
override def inject: ActiveObjectConfiguratorBase = synchronized { override def inject: TypedActorConfiguratorBase = synchronized {
if (injector ne null) throw new IllegalActorStateException("inject() has already been called on this configurator") if (injector ne null) throw new IllegalActorStateException("inject() has already been called on this configurator")
injector = Guice.createInjector(modules) injector = Guice.createInjector(modules)
this this
} }
override def supervise: ActiveObjectConfiguratorBase = synchronized { override def supervise: TypedActorConfiguratorBase = synchronized {
if (injector eq null) inject if (injector eq null) inject
supervisor = Some(ActiveObject.supervise(restartStrategy, supervised)) supervisor = Some(TypedActor.supervise(restartStrategy, supervised))
this this
} }
@ -141,7 +148,7 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat
* }}) * }})
* </pre> * </pre>
*/ */
def addExternalGuiceModule(module: Module): ActiveObjectConfiguratorBase = synchronized { def addExternalGuiceModule(module: Module): TypedActorConfiguratorBase = synchronized {
modules.add(module) modules.add(module)
this this
} }

View file

@ -137,7 +137,7 @@ object RemoteClient extends Logging {
actorsFor(RemoteServer.Address(hostname, port)) += uuid actorsFor(RemoteServer.Address(hostname, port)) += uuid
} }
// TODO: add RemoteClient.unregister for ActiveObject, but first need a @shutdown callback // TODO: add RemoteClient.unregister for TypedActor, but first need a @shutdown callback
private[akka] def unregister(hostname: String, port: Int, uuid: String) = synchronized { private[akka] def unregister(hostname: String, port: Int, uuid: String) = synchronized {
val set = actorsFor(RemoteServer.Address(hostname, port)) val set = actorsFor(RemoteServer.Address(hostname, port))
set -= uuid set -= uuid
@ -217,7 +217,7 @@ class RemoteClient private[akka] (val hostname: String, val port: Int, loader: O
} else { } else {
futures.synchronized { futures.synchronized {
val futureResult = if (senderFuture.isDefined) senderFuture.get val futureResult = if (senderFuture.isDefined) senderFuture.get
else new DefaultCompletableFuture[T](request.getTimeout) else new DefaultCompletableFuture[T](request.getActorInfo.getTimeout)
futures.put(request.getId, futureResult) futures.put(request.getId, futureResult)
connection.getChannel.write(request) connection.getChannel.write(request)
Some(futureResult) Some(futureResult)
@ -230,11 +230,13 @@ class RemoteClient private[akka] (val hostname: String, val port: Int, loader: O
} }
private[akka] def registerSupervisorForActor(actorRef: ActorRef) = private[akka] def registerSupervisorForActor(actorRef: ActorRef) =
if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException("Can't register supervisor for " + actorRef + " since it is not under supervision") if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException(
"Can't register supervisor for " + actorRef + " since it is not under supervision")
else supervisors.putIfAbsent(actorRef.supervisor.get.uuid, actorRef) else supervisors.putIfAbsent(actorRef.supervisor.get.uuid, actorRef)
private[akka] def deregisterSupervisorForActor(actorRef: ActorRef) = private[akka] def deregisterSupervisorForActor(actorRef: ActorRef) =
if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException("Can't unregister supervisor for " + actorRef + " since it is not under supervision") if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException(
"Can't unregister supervisor for " + actorRef + " since it is not under supervision")
else supervisors.remove(actorRef.supervisor.get.uuid) else supervisors.remove(actorRef.supervisor.get.uuid)
} }

View file

@ -55,7 +55,7 @@ object RemoteNode extends RemoteServer
/** /**
* For internal use only. * For internal use only.
* Holds configuration variables, remote actors, remote active objects and remote servers. * Holds configuration variables, remote actors, remote typed actors and remote servers.
* *
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
@ -104,7 +104,7 @@ object RemoteServer {
actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).actors.put(uuid, actor) actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).actors.put(uuid, actor)
} }
private[akka] def registerActiveObject(address: InetSocketAddress, name: String, activeObject: AnyRef) = guard.withWriteGuard { private[akka] def registerTypedActor(address: InetSocketAddress, name: String, activeObject: AnyRef) = guard.withWriteGuard {
actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).activeObjects.put(name, activeObject) actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).activeObjects.put(name, activeObject)
} }
@ -228,7 +228,7 @@ class RemoteServer extends Logging {
} }
} }
// TODO: register active object in RemoteServer as well // TODO: register typed actor in RemoteServer as well
/** /**
* Register Remote Actor by the Actor's 'id' field. It starts the Actor if it is not started already. * Register Remote Actor by the Actor's 'id' field. It starts the Actor if it is not started already.
@ -360,139 +360,88 @@ class RemoteServerHandler(
private def handleRemoteRequestProtocol(request: RemoteRequestProtocol, channel: Channel) = { private def handleRemoteRequestProtocol(request: RemoteRequestProtocol, channel: Channel) = {
log.debug("Received RemoteRequestProtocol[\n%s]", request.toString) log.debug("Received RemoteRequestProtocol[\n%s]", request.toString)
if (request.getIsActor) dispatchToActor(request, channel) val actorType = request.getActorInfo.getActorType
else dispatchToActiveObject(request, channel) if (actorType == ActorType.SCALA_ACTOR) dispatchToActor(request, channel)
else if (actorType == ActorType.JAVA_ACTOR) throw new IllegalActorStateException("ActorType JAVA_ACTOR is currently not supported")
else if (actorType == ActorType.TYPED_ACTOR) dispatchToTypedActor(request, channel)
else throw new IllegalActorStateException("Unknown ActorType [" + actorType + "]")
} }
private def dispatchToActor(request: RemoteRequestProtocol, channel: Channel) = { private def dispatchToActor(request: RemoteRequestProtocol, channel: Channel) = {
log.debug("Dispatching to remote actor [%s:%s]", request.getTarget, request.getUuid) val actorInfo = request.getActorInfo
val actorRef = createActor(request.getTarget, request.getUuid, request.getTimeout) log.debug("Dispatching to remote actor [%s:%s]", actorInfo.getTarget, actorInfo.getUuid)
val actorRef = createActor(actorInfo)
actorRef.start actorRef.start
val message = MessageSerializer.deserialize(request.getMessage) val message = MessageSerializer.deserialize(request.getMessage)
val sender = val sender =
if (request.hasSender) Some(RemoteActorSerialization.fromProtobufToRemoteActorRef(request.getSender, applicationLoader)) if (request.hasSender) Some(RemoteActorSerialization.fromProtobufToRemoteActorRef(request.getSender, applicationLoader))
else None else None
if (request.getIsOneWay) actorRef.!(message)(sender) if (request.getIsOneWay) actorRef.!(message)(sender)
else { else {
try { try {
val resultOrNone = (actorRef.!!(message)(sender)).as[AnyRef] val resultOrNone = (actorRef.!!(message)(sender)).as[AnyRef]
val result = if (resultOrNone.isDefined) resultOrNone.get else null val result = if (resultOrNone.isDefined) resultOrNone.get else null
log.debug("Returning result from actor invocation [%s]", result) log.debug("Returning result from actor invocation [%s]", result)
val replyBuilder = RemoteReplyProtocol.newBuilder val replyBuilder = RemoteReplyProtocol.newBuilder
.setId(request.getId) .setId(request.getId)
.setMessage(MessageSerializer.serialize(result)) .setMessage(MessageSerializer.serialize(result))
.setIsSuccessful(true) .setIsSuccessful(true)
.setIsActor(true) .setIsActor(true)
if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid)
val replyMessage = replyBuilder.build channel.write(replyBuilder.build)
channel.write(replyMessage)
} catch { } catch {
case e: Throwable => case e: Throwable => channel.write(createErrorReplyMessage(e, request, true))
log.error(e, "Could not invoke remote actor [%s]", request.getTarget)
val replyBuilder = RemoteReplyProtocol.newBuilder
.setId(request.getId)
.setException(ExceptionProtocol.newBuilder.setClassname(e.getClass.getName).setMessage(e.getMessage).build)
.setIsSuccessful(false)
.setIsActor(true)
if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid)
val replyMessage = replyBuilder.build
channel.write(replyMessage)
} }
} }
} }
private def dispatchToActiveObject(request: RemoteRequestProtocol, channel: Channel) = { private def dispatchToTypedActor(request: RemoteRequestProtocol, channel: Channel) = {
log.debug("Dispatching to remote active object [%s :: %s]", request.getMethod, request.getTarget) val actorInfo = request.getActorInfo
val activeObject = createActiveObject(request.getTarget, request.getTimeout) val typedActorInfo = actorInfo.getTypedActorInfo
log.debug("Dispatching to remote typed actor [%s :: %s]", typedActorInfo.getMethod, typedActorInfo.getInterface)
val activeObject = createTypedActor(actorInfo)
val args = MessageSerializer.deserialize(request.getMessage).asInstanceOf[Array[AnyRef]].toList val args = MessageSerializer.deserialize(request.getMessage).asInstanceOf[Array[AnyRef]].toList
val argClasses = args.map(_.getClass) val argClasses = args.map(_.getClass)
val (unescapedArgs, unescapedArgClasses) = unescapeArgs(args, argClasses, request.getTimeout)
try { try {
val messageReceiver = activeObject.getClass.getDeclaredMethod( val messageReceiver = activeObject.getClass.getDeclaredMethod(typedActorInfo.getMethod, argClasses: _*)
request.getMethod, unescapedArgClasses: _*) if (request.getIsOneWay) messageReceiver.invoke(activeObject, args: _*)
if (request.getIsOneWay) messageReceiver.invoke(activeObject, unescapedArgs: _*)
else { else {
val result = messageReceiver.invoke(activeObject, unescapedArgs: _*) val result = messageReceiver.invoke(activeObject, args: _*)
log.debug("Returning result from remote active object invocation [%s]", result) log.debug("Returning result from remote typed actor invocation [%s]", result)
val replyBuilder = RemoteReplyProtocol.newBuilder val replyBuilder = RemoteReplyProtocol.newBuilder
.setId(request.getId) .setId(request.getId)
.setMessage(MessageSerializer.serialize(result)) .setMessage(MessageSerializer.serialize(result))
.setIsSuccessful(true) .setIsSuccessful(true)
.setIsActor(false) .setIsActor(false)
if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid)
val replyMessage = replyBuilder.build channel.write(replyBuilder.build)
channel.write(replyMessage)
} }
} catch { } catch {
case e: InvocationTargetException => case e: InvocationTargetException => channel.write(createErrorReplyMessage(e.getCause, request, false))
log.error(e.getCause, "Could not invoke remote active object [%s :: %s]", request.getMethod, request.getTarget) case e: Throwable => channel.write(createErrorReplyMessage(e, request, false))
val replyBuilder = RemoteReplyProtocol.newBuilder
.setId(request.getId)
.setException(ExceptionProtocol.newBuilder.setClassname(e.getCause.getClass.getName).setMessage(e.getCause.getMessage).build)
.setIsSuccessful(false)
.setIsActor(false)
if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid)
val replyMessage = replyBuilder.build
channel.write(replyMessage)
case e: Throwable =>
log.error(e, "Could not invoke remote active object [%s :: %s]", request.getMethod, request.getTarget)
val replyBuilder = RemoteReplyProtocol.newBuilder
.setId(request.getId)
.setException(ExceptionProtocol.newBuilder.setClassname(e.getClass.getName).setMessage(e.getMessage).build)
.setIsSuccessful(false)
.setIsActor(false)
if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid)
val replyMessage = replyBuilder.build
channel.write(replyMessage)
} }
} }
private def unescapeArgs(args: scala.List[AnyRef], argClasses: scala.List[Class[_]], timeout: Long) = {
val unescapedArgs = new Array[AnyRef](args.size)
val unescapedArgClasses = new Array[Class[_]](args.size)
val escapedArgs = for (i <- 0 until args.size) {
val arg = args(i)
if (arg.isInstanceOf[String] && arg.asInstanceOf[String].startsWith(AW_PROXY_PREFIX)) {
val argString = arg.asInstanceOf[String]
val proxyName = argString.replace(AW_PROXY_PREFIX, "")
val activeObject = createActiveObject(proxyName, timeout)
unescapedArgs(i) = activeObject
unescapedArgClasses(i) = Class.forName(proxyName)
} else {
unescapedArgs(i) = args(i)
unescapedArgClasses(i) = argClasses(i)
}
}
(unescapedArgs, unescapedArgClasses)
}
private def createActiveObject(name: String, timeout: Long): AnyRef = {
val activeObjectOrNull = activeObjects.get(name)
if (activeObjectOrNull eq null) {
try {
log.info("Creating a new remote active object [%s]", name)
val clazz = if (applicationLoader.isDefined) applicationLoader.get.loadClass(name)
else Class.forName(name)
val newInstance = ActiveObject.newInstance(clazz, timeout).asInstanceOf[AnyRef]
activeObjects.put(name, newInstance)
newInstance
} catch {
case e =>
log.error(e, "Could not create remote active object instance")
throw e
}
} else activeObjectOrNull
}
/** /**
* Creates a new instance of the actor with name, uuid and timeout specified as arguments. * Creates a new instance of the actor with name, uuid and timeout specified as arguments.
*
* If actor already created then just return it from the registry. * If actor already created then just return it from the registry.
*
* Does not start the actor. * Does not start the actor.
*/ */
private def createActor(name: String, uuid: String, timeout: Long): ActorRef = { private def createActor(actorInfo: ActorInfoProtocol): ActorRef = {
val name = actorInfo.getTarget
val uuid = actorInfo.getUuid
val timeout = actorInfo.getTimeout
val actorRefOrNull = actors.get(uuid) val actorRefOrNull = actors.get(uuid)
if (actorRefOrNull eq null) { if (actorRefOrNull eq null) {
try { try {
@ -512,4 +461,43 @@ class RemoteServerHandler(
} }
} else actorRefOrNull } else actorRefOrNull
} }
private def createTypedActor(actorInfo: ActorInfoProtocol): AnyRef = {
val uuid = actorInfo.getUuid
val activeObjectOrNull = activeObjects.get(uuid)
if (activeObjectOrNull eq null) {
val typedActorInfo = actorInfo.getTypedActorInfo
val interfaceClassname = typedActorInfo.getInterface
val targetClassname = actorInfo.getTarget
try {
log.info("Creating a new remote typed actor:\n\t[%s :: %s]", interfaceClassname, targetClassname)
val (interfaceClass, targetClass) =
if (applicationLoader.isDefined) (applicationLoader.get.loadClass(interfaceClassname),
applicationLoader.get.loadClass(targetClassname))
else (Class.forName(interfaceClassname), Class.forName(targetClassname))
val newInstance = TypedActor.newInstance(
interfaceClass, targetClass.asInstanceOf[Class[_ <: TypedActor]], actorInfo.getTimeout).asInstanceOf[AnyRef]
activeObjects.put(uuid, newInstance)
newInstance
} catch {
case e => log.error(e, "Could not create remote typed actor instance"); throw e
}
} else activeObjectOrNull
}
private def createErrorReplyMessage(e: Throwable, request: RemoteRequestProtocol, isActor: Boolean): RemoteReplyProtocol = {
val actorInfo = request.getActorInfo
log.error(e, "Could not invoke remote typed actor [%s :: %s]", actorInfo.getTypedActorInfo.getMethod, actorInfo.getTarget)
val replyBuilder = RemoteReplyProtocol.newBuilder
.setId(request.getId)
.setException(ExceptionProtocol.newBuilder.setClassname(e.getClass.getName).setMessage(e.getMessage).build)
.setIsSuccessful(false)
.setIsActor(isActor)
if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid)
replyBuilder.build
}
} }

View file

@ -5,7 +5,7 @@ import se.scalablesolutions.akka.actor.annotation.inittransactionalstate;
import se.scalablesolutions.akka.stm.*; import se.scalablesolutions.akka.stm.*;
@transactionrequired @transactionrequired
public class NestedTransactionalActiveObject { public class NestedTransactionalTypedActor {
private TransactionalMap<String, String> mapState; private TransactionalMap<String, String> mapState;
private TransactionalVector<String> vectorState; private TransactionalVector<String> vectorState;
private Ref<String> refState; private Ref<String> refState;
@ -58,7 +58,7 @@ public class NestedTransactionalActiveObject {
} }
public String failure(String key, String msg, ActiveObjectFailer failer) { public String failure(String key, String msg, TypedActorFailer failer) {
mapState.put(key, msg); mapState.put(key, msg);
vectorState.add(msg); vectorState.add(msg);
refState.swap(msg); refState.swap(msg);
@ -67,7 +67,7 @@ public class NestedTransactionalActiveObject {
} }
public void thisMethodHangs(String key, String msg, ActiveObjectFailer failer) { public void thisMethodHangs(String key, String msg, TypedActorFailer failer) {
setMapState(key, msg); setMapState(key, msg);
} }

View file

@ -2,12 +2,12 @@ package se.scalablesolutions.akka.actor;
import se.scalablesolutions.akka.actor.annotation.prerestart; import se.scalablesolutions.akka.actor.annotation.prerestart;
import se.scalablesolutions.akka.actor.annotation.postrestart; import se.scalablesolutions.akka.actor.annotation.postrestart;
import se.scalablesolutions.akka.actor.ActiveObjectContext; import se.scalablesolutions.akka.actor.TypedActorContext;
import se.scalablesolutions.akka.dispatch.CompletableFuture; import se.scalablesolutions.akka.dispatch.CompletableFuture;
public class SimpleJavaPojo { public class SimpleJavaPojo {
ActiveObjectContext context; TypedActorContext context;
public boolean pre = false; public boolean pre = false;
public boolean post = false; public boolean post = false;

View file

@ -7,7 +7,7 @@ import se.scalablesolutions.akka.actor.annotation.inittransactionalstate;
import se.scalablesolutions.akka.stm.*; import se.scalablesolutions.akka.stm.*;
@transactionrequired @transactionrequired
public class TransactionalActiveObject { public class TransactionalTypedActor {
private TransactionalMap<String, String> mapState; private TransactionalMap<String, String> mapState;
private TransactionalVector<String> vectorState; private TransactionalVector<String> vectorState;
private Ref<String> refState; private Ref<String> refState;
@ -53,14 +53,14 @@ public class TransactionalActiveObject {
refState.swap(msg); refState.swap(msg);
} }
public void success(String key, String msg, NestedTransactionalActiveObject nested) { public void success(String key, String msg, NestedTransactionalTypedActor nested) {
mapState.put(key, msg); mapState.put(key, msg);
vectorState.add(msg); vectorState.add(msg);
refState.swap(msg); refState.swap(msg);
nested.success(key, msg); nested.success(key, msg);
} }
public String failure(String key, String msg, ActiveObjectFailer failer) { public String failure(String key, String msg, TypedActorFailer failer) {
mapState.put(key, msg); mapState.put(key, msg);
vectorState.add(msg); vectorState.add(msg);
refState.swap(msg); refState.swap(msg);
@ -68,7 +68,7 @@ public class TransactionalActiveObject {
return msg; return msg;
} }
public String failure(String key, String msg, NestedTransactionalActiveObject nested, ActiveObjectFailer failer) { public String failure(String key, String msg, NestedTransactionalTypedActor nested, TypedActorFailer failer) {
mapState.put(key, msg); mapState.put(key, msg);
vectorState.add(msg); vectorState.add(msg);
refState.swap(msg); refState.swap(msg);
@ -76,7 +76,7 @@ public class TransactionalActiveObject {
return msg; return msg;
} }
public void thisMethodHangs(String key, String msg, ActiveObjectFailer failer) { public void thisMethodHangs(String key, String msg, TypedActorFailer failer) {
setMapState(key, msg); setMapState(key, msg);
} }

View file

@ -1,6 +1,6 @@
package se.scalablesolutions.akka.actor; package se.scalablesolutions.akka.actor;
public class ActiveObjectFailer implements java.io.Serializable { public class TypedActorFailer implements java.io.Serializable {
public int fail() { public int fail() {
throw new RuntimeException("expected"); throw new RuntimeException("expected");
} }

View file

@ -1,7 +1,7 @@
<aspectwerkz> <aspectwerkz>
<system id="akka"> <system id="akka">
<package name="se.scalablesolutions.akka.actor"> <package name="se.scalablesolutions.akka.actor">
<aspect class="ActiveObjectAspect" /> <aspect class="TypedActorAspect" />
</package> </package>
</system> </system>
</aspectwerkz> </aspectwerkz>

View file

@ -1,4 +1,4 @@
/** /**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se> * Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/ */
@ -14,7 +14,7 @@ import org.junit.runner.RunWith
import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor._
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class NestedTransactionalActiveObjectSpec extends class NestedTransactionalTypedActorSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
@ -25,13 +25,13 @@ class NestedTransactionalActiveObjectSpec extends
// ActorRegistry.shutdownAll // ActorRegistry.shutdownAll
} }
describe("Declaratively nested supervised transactional in-memory Active Object") { describe("Declaratively nested supervised transactional in-memory TypedActor") {
it("map should not rollback state for stateful server in case of success") { it("map should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state
val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
nested.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state nested.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired
@ -40,13 +40,13 @@ class NestedTransactionalActiveObjectSpec extends
} }
it("map should rollback state for stateful server in case of failure") { it("map should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) val failer = TypedActor.newInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
fail("should have thrown an exception") fail("should have thrown an exception")
@ -56,10 +56,10 @@ class NestedTransactionalActiveObjectSpec extends
} }
it("vector should not rollback state for stateful server in case of success") { it("vector should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
nested.setVectorState("init") // set init state nested.setVectorState("init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired
@ -68,13 +68,13 @@ class NestedTransactionalActiveObjectSpec extends
} }
it("vector should rollback state for stateful server in case of failure") { it("vector should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
nested.setVectorState("init") // set init state nested.setVectorState("init") // set init state
val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) val failer = TypedActor.newInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
fail("should have thrown an exception") fail("should have thrown an exception")
@ -84,9 +84,9 @@ class NestedTransactionalActiveObjectSpec extends
} }
it("ref should not rollback state for stateful server in case of success") { it("ref should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
nested.setRefState("init") // set init state nested.setRefState("init") // set init state
@ -96,13 +96,13 @@ class NestedTransactionalActiveObjectSpec extends
} }
it("ref should rollback state for stateful server in case of failure") { it("ref should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
nested.setRefState("init") // set init state nested.setRefState("init") // set init state
val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) val failer = TypedActor.newInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
fail("should have thrown an exception") fail("should have thrown an exception")

View file

@ -13,25 +13,25 @@ import org.junit.runner.RunWith
import org.junit.{Test, Before, After} import org.junit.{Test, Before, After}
import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config.Config
import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.TypedActorConfigurator
import se.scalablesolutions.akka.remote.{RemoteNode, RemoteServer, RemoteClient} import se.scalablesolutions.akka.remote.{RemoteNode, RemoteServer, RemoteClient}
object RemoteTransactionalActiveObjectSpec { object RemoteTransactionalTypedActorSpec {
val HOSTNAME = "localhost" val HOSTNAME = "localhost"
val PORT = 9988 val PORT = 9988
var server: RemoteServer = null var server: RemoteServer = null
} }
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class RemoteTransactionalActiveObjectSpec extends class RemoteTransactionalTypedActorSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
import RemoteTransactionalActiveObjectSpec._ import RemoteTransactionalTypedActorSpec._
Config.config Config.config
private val conf = new ActiveObjectConfigurator private val conf = new TypedActorConfigurator
private var messageLog = "" private var messageLog = ""
override def beforeAll = { override def beforeAll = {
@ -51,19 +51,19 @@ class RemoteTransactionalActiveObjectSpec extends
} }
} }
describe("Remote transactional in-memory Active Object ") { describe("Remote transactional in-memory TypedActor ") {
/* /*
it("map should not rollback state for stateful server in case of success") { it("map should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT)
stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired
stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state") stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state")
} }
it("map should rollback state for stateful server in case of failure") { it("map should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT)
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
val failer =ActiveObject.newRemoteInstance(classOf[ActiveObjectFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[ActiveObjectFailer]) val failer =TypedActor.newRemoteInstance(classOf[TypedActorFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method
fail("should have thrown an exception") fail("should have thrown an exception")
@ -72,16 +72,16 @@ class RemoteTransactionalActiveObjectSpec extends
} }
it("vector should not rollback state for stateful server in case of success") { it("vector should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT)
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired
stateful.getVectorState should equal("new state") stateful.getVectorState should equal("new state")
} }
it("vector should rollback state for stateful server in case of failure") { it("vector should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT)
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
val failer =ActiveObject.newRemoteInstance(classOf[ActiveObjectFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[ActiveObjectFailer]) val failer =TypedActor.newRemoteInstance(classOf[TypedActorFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method
fail("should have thrown an exception") fail("should have thrown an exception")
@ -90,16 +90,16 @@ class RemoteTransactionalActiveObjectSpec extends
} }
it("ref should not rollback state for stateful server in case of success") { it("ref should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT)
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired
stateful.getRefState should equal("new state") stateful.getRefState should equal("new state")
} }
it("ref should rollback state for stateful server in case of failure") { it("ref should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT)
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
val failer =ActiveObject.newRemoteInstance(classOf[ActiveObjectFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[ActiveObjectFailer]) val failer =TypedActor.newRemoteInstance(classOf[TypedActorFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method
fail("should have thrown an exception") fail("should have thrown an exception")

View file

@ -13,17 +13,17 @@ import org.junit.runner.RunWith
import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config.Config
import se.scalablesolutions.akka.config._ import se.scalablesolutions.akka.config._
import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.TypedActorConfigurator
import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.config.JavaConfig._
import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor._
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class RestartNestedTransactionalActiveObjectSpec extends class RestartNestedTransactionalTypedActorSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
private val conf = new ActiveObjectConfigurator private val conf = new TypedActorConfigurator
private var messageLog = "" private var messageLog = ""
override def beforeAll { override def beforeAll {
@ -31,13 +31,13 @@ class RestartNestedTransactionalActiveObjectSpec extends
conf.configure( conf.configure(
new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray),
List( List(
new Component(classOf[TransactionalActiveObject], new Component(classOf[TransactionalTypedActor],
new LifeCycle(new Permanent), new LifeCycle(new Permanent),
10000), 10000),
new Component(classOf[NestedTransactionalActiveObject], new Component(classOf[NestedTransactionalTypedActor],
new LifeCycle(new Permanent), new LifeCycle(new Permanent),
10000), 10000),
new Component(classOf[ActiveObjectFailer], new Component(classOf[TypedActorFailer],
new LifeCycle(new Permanent), new LifeCycle(new Permanent),
10000) 10000)
).toArray).supervise ).toArray).supervise
@ -51,15 +51,15 @@ class RestartNestedTransactionalActiveObjectSpec extends
describe("Restart nested supervised transactional Active Object") { describe("Restart nested supervised transactional Active Object") {
/* /*
it("map should rollback state for stateful server in case of failure") { it("map should rollback state for stateful server in case of failure") {
val stateful = conf.getInstance(classOf[TransactionalActiveObject]) val stateful = conf.getInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) val nested = conf.getInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
val failer = conf.getInstance(classOf[ActiveObjectFailer]) val failer = conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
@ -71,15 +71,15 @@ class RestartNestedTransactionalActiveObjectSpec extends
} }
it("vector should rollback state for stateful server in case of failure") { it("vector should rollback state for stateful server in case of failure") {
val stateful = conf.getInstance(classOf[TransactionalActiveObject]) val stateful = conf.getInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) val nested = conf.getInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
nested.setVectorState("init") // set init state nested.setVectorState("init") // set init state
val failer = conf.getInstance(classOf[ActiveObjectFailer]) val failer = conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
@ -91,15 +91,15 @@ class RestartNestedTransactionalActiveObjectSpec extends
} }
it("ref should rollback state for stateful server in case of failure") { it("ref should rollback state for stateful server in case of failure") {
val stateful = conf.getInstance(classOf[TransactionalActiveObject]) val stateful = conf.getInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) val nested = conf.getInstance(classOf[NestedTransactionalTypedActor])
nested.init nested.init
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
nested.setRefState("init") // set init state nested.setRefState("init") // set init state
val failer = conf.getInstance(classOf[ActiveObjectFailer]) val failer = conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)

View file

@ -13,17 +13,17 @@ import org.junit.runner.RunWith
import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config.Config
import se.scalablesolutions.akka.config._ import se.scalablesolutions.akka.config._
import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.TypedActorConfigurator
import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.config.JavaConfig._
import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor._
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class RestartTransactionalActiveObjectSpec extends class RestartTransactionalTypedActorSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
private val conf = new ActiveObjectConfigurator private val conf = new TypedActorConfigurator
private var messageLog = "" private var messageLog = ""
def before { def before {
@ -32,11 +32,11 @@ class RestartTransactionalActiveObjectSpec extends
new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray),
List( List(
new Component( new Component(
classOf[TransactionalActiveObject], classOf[TransactionalTypedActor],
new LifeCycle(new Temporary), new LifeCycle(new Temporary),
10000), 10000),
new Component( new Component(
classOf[ActiveObjectFailer], classOf[TypedActorFailer],
new LifeCycle(new Temporary), new LifeCycle(new Temporary),
10000) 10000)
).toArray).supervise ).toArray).supervise
@ -51,10 +51,10 @@ class RestartTransactionalActiveObjectSpec extends
/* /*
it("map should rollback state for stateful server in case of failure") { it("map should rollback state for stateful server in case of failure") {
before before
val stateful = conf.getInstance(classOf[TransactionalActiveObject]) val stateful = conf.getInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init")
val failer = conf.getInstance(classOf[ActiveObjectFailer]) val failer = conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer)
fail("should have thrown an exception") fail("should have thrown an exception")
@ -65,10 +65,10 @@ class RestartTransactionalActiveObjectSpec extends
it("vector should rollback state for stateful server in case of failure") { it("vector should rollback state for stateful server in case of failure") {
before before
val stateful = conf.getInstance(classOf[TransactionalActiveObject]) val stateful = conf.getInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
val failer = conf.getInstance(classOf[ActiveObjectFailer]) val failer = conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer)
fail("should have thrown an exception") fail("should have thrown an exception")
@ -78,10 +78,10 @@ class RestartTransactionalActiveObjectSpec extends
} }
it("ref should rollback state for stateful server in case of failure") { it("ref should rollback state for stateful server in case of failure") {
val stateful = conf.getInstance(classOf[TransactionalActiveObject]) val stateful = conf.getInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
val failer = conf.getInstance(classOf[ActiveObjectFailer]) val failer = conf.getInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer)
fail("should have thrown an exception") fail("should have thrown an exception")

View file

@ -14,7 +14,7 @@ import org.junit.runner.RunWith
import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor._
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class TransactionalActiveObjectSpec extends class TransactionalTypedActorSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
@ -27,7 +27,7 @@ class TransactionalActiveObjectSpec extends
describe("Declaratively supervised transactional in-memory Active Object ") { describe("Declaratively supervised transactional in-memory Active Object ") {
it("map should not rollback state for stateful server in case of success") { it("map should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init")
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state")
@ -35,10 +35,10 @@ class TransactionalActiveObjectSpec extends
} }
it("map should rollback state for stateful server in case of failure") { it("map should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init")
val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) val failer = TypedActor.newInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer)
fail("should have thrown an exception") fail("should have thrown an exception")
@ -47,7 +47,7 @@ class TransactionalActiveObjectSpec extends
} }
it("vector should not rollback state for stateful server in case of success") { it("vector should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state")
@ -55,10 +55,10 @@ class TransactionalActiveObjectSpec extends
} }
it("vector should rollback state for stateful server in case of failure") { it("vector should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setVectorState("init") // set init state stateful.setVectorState("init") // set init state
val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) val failer = TypedActor.newInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer)
fail("should have thrown an exception") fail("should have thrown an exception")
@ -67,7 +67,7 @@ class TransactionalActiveObjectSpec extends
} }
it("ref should not rollback state for stateful server in case of success") { it("ref should not rollback state for stateful server in case of success") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state")
@ -75,10 +75,10 @@ class TransactionalActiveObjectSpec extends
} }
it("ref should rollback state for stateful server in case of failure") { it("ref should rollback state for stateful server in case of failure") {
val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor])
stateful.init stateful.init
stateful.setRefState("init") // set init state stateful.setRefState("init") // set init state
val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) val failer = TypedActor.newInstance(classOf[TypedActorFailer])
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer)
fail("should have thrown an exception") fail("should have thrown an exception")

View file

@ -14,15 +14,15 @@ import org.junit.runner.RunWith
import se.scalablesolutions.akka.dispatch.DefaultCompletableFuture; import se.scalablesolutions.akka.dispatch.DefaultCompletableFuture;
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ActiveObjectContextSpec extends class TypedActorContextSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
describe("ActiveObjectContext") { describe("TypedActorContext") {
it("context.sender should return the sender Active Object reference") { it("context.sender should return the sender TypedActor reference") {
val pojo = ActiveObject.newInstance(classOf[SimpleJavaPojo]) val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo])
val pojoCaller = ActiveObject.newInstance(classOf[SimpleJavaPojoCaller]) val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller])
pojoCaller.setPojo(pojo) pojoCaller.setPojo(pojo)
try { try {
pojoCaller.getSenderFromSimpleJavaPojo should equal (pojoCaller) pojoCaller.getSenderFromSimpleJavaPojo should equal (pojoCaller)
@ -31,9 +31,9 @@ class ActiveObjectContextSpec extends
} }
} }
it("context.senderFuture should return the senderFuture Active Object reference") { it("context.senderFuture should return the senderFuture TypedActor reference") {
val pojo = ActiveObject.newInstance(classOf[SimpleJavaPojo]) val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo])
val pojoCaller = ActiveObject.newInstance(classOf[SimpleJavaPojoCaller]) val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller])
pojoCaller.setPojo(pojo) pojoCaller.setPojo(pojo)
try { try {
pojoCaller.getSenderFutureFromSimpleJavaPojo.getClass.getName should equal (classOf[DefaultCompletableFuture[_]].getName) pojoCaller.getSenderFutureFromSimpleJavaPojo.getClass.getName should equal (classOf[DefaultCompletableFuture[_]].getName)

View file

@ -15,18 +15,18 @@ import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith import org.junit.runner.RunWith
import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config.Config
import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.TypedActorConfigurator
import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.config.JavaConfig._
import se.scalablesolutions.akka.dispatch._ import se.scalablesolutions.akka.dispatch._
import se.scalablesolutions.akka.dispatch.FutureTimeoutException import se.scalablesolutions.akka.dispatch.FutureTimeoutException
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ActiveObjectGuiceConfiguratorSpec extends class TypedActorGuiceConfiguratorSpec extends
Spec with Spec with
ShouldMatchers with ShouldMatchers with
BeforeAndAfterAll { BeforeAndAfterAll {
private val conf = new ActiveObjectConfigurator private val conf = new TypedActorConfigurator
private var messageLog = "" private var messageLog = ""
override def beforeAll { override def beforeAll {
@ -55,9 +55,9 @@ class ActiveObjectGuiceConfiguratorSpec extends
override def afterAll = conf.stop override def afterAll = conf.stop
describe("ActiveObjectGuiceConfigurator") { describe("TypedActorGuiceConfigurator") {
/* /*
it("should inject active object using guice") { it("should inject typed actor using guice") {
messageLog = "" messageLog = ""
val foo = conf.getInstance(classOf[Foo]) val foo = conf.getInstance(classOf[Foo])
val bar = conf.getInstance(classOf[Bar]) val bar = conf.getInstance(classOf[Bar])
@ -81,7 +81,7 @@ class ActiveObjectGuiceConfiguratorSpec extends
} }
} }
it("should be able to invoke active object") { it("should be able to invoke typed actor") {
messageLog = "" messageLog = ""
val foo = conf.getInstance(classOf[Foo]) val foo = conf.getInstance(classOf[Foo])
messageLog += foo.foo("foo ") messageLog += foo.foo("foo ")
@ -91,7 +91,7 @@ class ActiveObjectGuiceConfiguratorSpec extends
messageLog should equal("foo return_foo before_bar ") messageLog should equal("foo return_foo before_bar ")
} }
it("should be able to invoke active object's invocation") { it("should be able to invoke typed actor's invocation") {
messageLog = "" messageLog = ""
val foo = conf.getInstance(classOf[Foo]) val foo = conf.getInstance(classOf[Foo])
val bar = conf.getInstance(classOf[Bar]) val bar = conf.getInstance(classOf[Bar])

View file

@ -5,20 +5,20 @@ import org.scalatest.{BeforeAndAfterAll, Spec}
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.ShouldMatchers import org.scalatest.matchers.ShouldMatchers
import se.scalablesolutions.akka.actor.ActiveObject._ import se.scalablesolutions.akka.actor.TypedActor._
import se.scalablesolutions.akka.config.{OneForOneStrategy, ActiveObjectConfigurator} import se.scalablesolutions.akka.config.{OneForOneStrategy, TypedActorConfigurator}
import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.config.JavaConfig._
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll {
var conf1: ActiveObjectConfigurator = _ var conf1: TypedActorConfigurator = _
var conf2: ActiveObjectConfigurator = _ var conf2: TypedActorConfigurator = _
var conf3: ActiveObjectConfigurator = _ var conf3: TypedActorConfigurator = _
var conf4: ActiveObjectConfigurator = _ var conf4: TypedActorConfigurator = _
override protected def beforeAll() = { override protected def beforeAll() = {
val strategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Exception])) val strategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Exception]))
@ -26,10 +26,10 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
val comp2 = new Component(classOf[SamplePojoAnnotated], new LifeCycle(new Temporary()), 1000) val comp2 = new Component(classOf[SamplePojoAnnotated], new LifeCycle(new Temporary()), 1000)
val comp3 = new Component(classOf[SamplePojo], new LifeCycle(new Permanent(), new RestartCallbacks("pre", "post")), 1000) val comp3 = new Component(classOf[SamplePojo], new LifeCycle(new Permanent(), new RestartCallbacks("pre", "post")), 1000)
val comp4 = new Component(classOf[SamplePojo], new LifeCycle(new Temporary(), new ShutdownCallback("down")), 1000) val comp4 = new Component(classOf[SamplePojo], new LifeCycle(new Temporary(), new ShutdownCallback("down")), 1000)
conf1 = new ActiveObjectConfigurator().configure(strategy, Array(comp1)).supervise conf1 = new TypedActorConfigurator().configure(strategy, Array(comp1)).supervise
conf2 = new ActiveObjectConfigurator().configure(strategy, Array(comp2)).supervise conf2 = new TypedActorConfigurator().configure(strategy, Array(comp2)).supervise
conf3 = new ActiveObjectConfigurator().configure(strategy, Array(comp3)).supervise conf3 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise
conf4 = new ActiveObjectConfigurator().configure(strategy, Array(comp4)).supervise conf4 = new TypedActorConfigurator().configure(strategy, Array(comp4)).supervise
} }
override protected def afterAll() = { override protected def afterAll() = {
@ -39,8 +39,8 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
conf4.stop conf4.stop
} }
describe("ActiveObject lifecycle management") { describe("TypedActor lifecycle management") {
it("should restart supervised, annotated active object on failure") { it("should restart supervised, annotated typed actor on failure") {
val obj = conf1.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) val obj = conf1.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated])
val cdl = obj.newCountdownLatch(2) val cdl = obj.newCountdownLatch(2)
assert(AspectInitRegistry.initFor(obj) ne null) assert(AspectInitRegistry.initFor(obj) ne null)
@ -58,7 +58,7 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
} }
} }
it("should shutdown supervised, annotated active object on failure") { it("should shutdown supervised, annotated typed actor on failure") {
val obj = conf2.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) val obj = conf2.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated])
val cdl = obj.newCountdownLatch(1) val cdl = obj.newCountdownLatch(1)
assert(AspectInitRegistry.initFor(obj) ne null) assert(AspectInitRegistry.initFor(obj) ne null)
@ -76,7 +76,7 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
} }
} }
it("should restart supervised, non-annotated active object on failure") { it("should restart supervised, non-annotated typed actor on failure") {
val obj = conf3.getInstance[SamplePojo](classOf[SamplePojo]) val obj = conf3.getInstance[SamplePojo](classOf[SamplePojo])
val cdl = obj.newCountdownLatch(2) val cdl = obj.newCountdownLatch(2)
assert(AspectInitRegistry.initFor(obj) ne null) assert(AspectInitRegistry.initFor(obj) ne null)
@ -94,7 +94,7 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
} }
} }
it("should shutdown supervised, non-annotated active object on failure") { it("should shutdown supervised, non-annotated typed actor on failure") {
val obj = conf4.getInstance[SamplePojo](classOf[SamplePojo]) val obj = conf4.getInstance[SamplePojo](classOf[SamplePojo])
val cdl = obj.newCountdownLatch(1) val cdl = obj.newCountdownLatch(1)
assert(AspectInitRegistry.initFor(obj) ne null) assert(AspectInitRegistry.initFor(obj) ne null)
@ -112,25 +112,25 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
} }
} }
it("should shutdown non-supervised, annotated active object on ActiveObject.stop") { it("should shutdown non-supervised, annotated typed actor on TypedActor.stop") {
val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated]) val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated])
assert(AspectInitRegistry.initFor(obj) ne null) assert(AspectInitRegistry.initFor(obj) ne null)
assert("hello akka" === obj.greet("akka")) assert("hello akka" === obj.greet("akka"))
ActiveObject.stop(obj) TypedActor.stop(obj)
assert(AspectInitRegistry.initFor(obj) eq null) assert(AspectInitRegistry.initFor(obj) eq null)
assert(!obj._pre) assert(!obj._pre)
assert(!obj._post) assert(!obj._post)
assert(obj._down) assert(obj._down)
try { try {
obj.greet("akka") obj.greet("akka")
fail("access to stopped active object") fail("access to stopped typed actor")
} catch { } catch {
case e: Exception => { /* test passed */ } case e: Exception => { /* test passed */ }
} }
} }
it("should shutdown non-supervised, annotated active object on ActorRegistry.shutdownAll") { it("should shutdown non-supervised, annotated typed actor on ActorRegistry.shutdownAll") {
val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated]) val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated])
assert(AspectInitRegistry.initFor(obj) ne null) assert(AspectInitRegistry.initFor(obj) ne null)
assert("hello akka" === obj.greet("akka")) assert("hello akka" === obj.greet("akka"))
ActorRegistry.shutdownAll ActorRegistry.shutdownAll
@ -140,23 +140,23 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA
assert(obj._down) assert(obj._down)
try { try {
obj.greet("akka") obj.greet("akka")
fail("access to stopped active object") fail("access to stopped typed actor")
} catch { } catch {
case e: Exception => { /* test passed */ } case e: Exception => { /* test passed */ }
} }
} }
it("should shutdown non-supervised, non-initialized active object on ActiveObject.stop") { it("should shutdown non-supervised, non-initialized typed actor on TypedActor.stop") {
val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated]) val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated])
ActiveObject.stop(obj) TypedActor.stop(obj)
assert(!obj._pre) assert(!obj._pre)
assert(!obj._post) assert(!obj._post)
assert(obj._down) assert(obj._down)
} }
it("both preRestart and postRestart methods should be invoked when an actor is restarted") { it("both preRestart and postRestart methods should be invoked when an actor is restarted") {
val pojo = ActiveObject.newInstance(classOf[SimpleJavaPojo]) val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo])
val supervisor = ActiveObject.newInstance(classOf[SimpleJavaPojo]) val supervisor = TypedActor.newInstance(classOf[SimpleJavaPojo])
link(supervisor,pojo, new OneForOneStrategy(3, 2000),Array(classOf[Throwable])) link(supervisor,pojo, new OneForOneStrategy(3, 2000),Array(classOf[Throwable]))
pojo.throwException pojo.throwException
Thread.sleep(500) Thread.sleep(500)

View file

@ -1,9 +1,10 @@
package sample.camel; package sample.camel;
import se.scalablesolutions.akka.actor.TypedActor;
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
public class BeanImpl implements BeanIntf { public class BeanImpl extends TypedActor implements BeanIntf {
public String foo(String s) { public String foo(String s) {
return "hello " + s; return "hello " + s;

View file

@ -8,17 +8,10 @@ import se.scalablesolutions.akka.actor.annotation.consume;
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
public class ConsumerPojo1 { public interface ConsumerPojo1 {
@consume("file:data/input/pojo") @consume("file:data/input/pojo")
public void foo(String body) { public void foo(String body);
System.out.println("Received message:");
System.out.println(body);
}
@consume("jetty:http://0.0.0.0:8877/camel/pojo") @consume("jetty:http://0.0.0.0:8877/camel/pojo")
public String bar(@Body String body, @Header("name") String header) { public String bar(@Body String body, @Header("name") String header);
return String.format("body=%s header=%s", body, header);
}
} }

View file

@ -0,0 +1,24 @@
package sample.camel;
import org.apache.camel.Body;
import org.apache.camel.Header;
import se.scalablesolutions.akka.actor.annotation.consume;
import se.scalablesolutions.akka.actor.TypedActor;
/**
* @author Martin Krasser
*/
public class ConsumerPojo1Impl extends TypedActor implements ConsumerPojo1 {
@consume("file:data/input/pojo")
public void foo(String body) {
System.out.println("Received message:");
System.out.println(body);
}
@consume("jetty:http://0.0.0.0:8877/camel/pojo")
public String bar(@Body String body, @Header("name") String header) {
return String.format("body=%s header=%s", body, header);
}
}

View file

@ -7,11 +7,8 @@ import se.scalablesolutions.akka.actor.annotation.consume;
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
public class ConsumerPojo2 { public interface ConsumerPojo2 {
@consume("direct:default") @consume("direct:default")
public String foo(String body) { public String foo(String body);
return String.format("default: %s", body);
}
} }

View file

@ -0,0 +1,18 @@
package sample.camel;
import org.apache.camel.Body;
import org.apache.camel.Header;
import se.scalablesolutions.akka.actor.TypedActor;
import se.scalablesolutions.akka.actor.annotation.consume;
/**
* @author Martin Krasser
*/
public class ConsumerPojo2Impl extends TypedActor implements ConsumerPojo2 {
@consume("direct:default")
public String foo(String body) {
return String.format("default: %s", body);
}
}

View file

@ -8,11 +8,8 @@ import se.scalablesolutions.akka.actor.annotation.consume;
/** /**
* @author Martin Krasser * @author Martin Krasser
*/ */
public class RemoteConsumerPojo1 { public interface RemoteConsumerPojo1 {
@consume("jetty:http://localhost:6644/camel/remote-active-object-1") @consume("jetty:http://localhost:6644/camel/remote-active-object-1")
public String foo(@Body String body, @Header("name") String header) { public String foo(@Body String body, @Header("name") String header);
return String.format("remote1: body=%s header=%s", body, header);
}
} }

View file

@ -0,0 +1,18 @@
package sample.camel;
import org.apache.camel.Body;
import org.apache.camel.Header;
import se.scalablesolutions.akka.actor.annotation.consume;
import se.scalablesolutions.akka.actor.TypedActor;
/**
* @author Martin Krasser
*/
public class RemoteConsumerPojo1Impl extends TypedActor implements RemoteConsumerPojo1 {
@consume("jetty:http://localhost:6644/camel/remote-active-object-1")
public String foo(@Body String body, @Header("name") String header) {
return String.format("remote1: body=%s header=%s", body, header);
}
}

View file

@ -7,7 +7,7 @@ import org.apache.camel.spring.spi.ApplicationContextRegistry
import org.springframework.context.support.ClassPathXmlApplicationContext import org.springframework.context.support.ClassPathXmlApplicationContext
import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.Actor._
import se.scalablesolutions.akka.actor.{ActiveObject, Supervisor} import se.scalablesolutions.akka.actor.{TypedActor, Supervisor}
import se.scalablesolutions.akka.camel.CamelContextManager import se.scalablesolutions.akka.camel.CamelContextManager
import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.config.ScalaConfig._
@ -89,7 +89,7 @@ class Boot {
// Active object example // Active object example
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
ActiveObject.newInstance(classOf[ConsumerPojo1]) TypedActor.newInstance(classOf[ConsumerPojo1], classOf[ConsumerPojo1Impl])
} }
/** /**

View file

@ -1,7 +1,7 @@
package sample.camel package sample.camel
import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.Actor._
import se.scalablesolutions.akka.actor.{ActiveObject, Actor, ActorRef} import se.scalablesolutions.akka.actor.{TypedActor, Actor, ActorRef}
import se.scalablesolutions.akka.camel.Message import se.scalablesolutions.akka.camel.Message
import se.scalablesolutions.akka.remote.RemoteClient import se.scalablesolutions.akka.remote.RemoteClient
@ -18,15 +18,15 @@ object ClientApplication {
val actor1 = actorOf[RemoteActor1] val actor1 = actorOf[RemoteActor1]
val actor2 = RemoteClient.actorFor("remote2", "localhost", 7777) val actor2 = RemoteClient.actorFor("remote2", "localhost", 7777)
val actobj1 = ActiveObject.newRemoteInstance(classOf[RemoteConsumerPojo1], "localhost", 7777) val actobj1 = TypedActor.newRemoteInstance(classOf[RemoteConsumerPojo1], classOf[RemoteConsumerPojo1Impl], "localhost", 7777)
//val actobj2 = TODO: create reference to server-managed active object (RemoteConsumerPojo2) //val actobj2 = TODO: create reference to server-managed typed actor (RemoteConsumerPojo2)
actor1.start actor1.start
println(actor1 !! Message("actor1")) // activates and publishes actor remotely println(actor1 !! Message("actor1")) // activates and publishes actor remotely
println(actor2 !! Message("actor2")) // actor already activated and published remotely println(actor2 !! Message("actor2")) // actor already activated and published remotely
println(actobj1.foo("x", "y")) // activates and publishes active object methods remotely println(actobj1.foo("x", "y")) // activates and publishes typed actor methods remotely
// ... // ...
} }

View file

@ -5,7 +5,7 @@ import org.apache.camel.builder.RouteBuilder
import org.apache.camel.spring.spi.ApplicationContextRegistry import org.apache.camel.spring.spi.ApplicationContextRegistry
import org.springframework.context.support.ClassPathXmlApplicationContext import org.springframework.context.support.ClassPathXmlApplicationContext
import se.scalablesolutions.akka.actor.{Actor, ActorRegistry, ActiveObject} import se.scalablesolutions.akka.actor.{Actor, ActorRegistry, TypedActor}
import se.scalablesolutions.akka.camel._ import se.scalablesolutions.akka.camel._
import se.scalablesolutions.akka.util.Logging import se.scalablesolutions.akka.util.Logging
@ -16,10 +16,9 @@ object StandaloneApplication {
def main(args: Array[String]) { def main(args: Array[String]) {
import CamelContextManager.context import CamelContextManager.context
// 'externally' register active objects // 'externally' register typed actors
val registry = new SimpleRegistry val registry = new SimpleRegistry
registry.put("pojo1", ActiveObject.newInstance(classOf[BeanIntf], new BeanImpl)) registry.put("pojo1", TypedActor.newInstance(classOf[BeanIntf], classOf[BeanImpl]))
registry.put("pojo2", ActiveObject.newInstance(classOf[BeanImpl]))
// customize CamelContext // customize CamelContext
CamelContextManager.init(new DefaultCamelContext(registry)) CamelContextManager.init(new DefaultCamelContext(registry))
@ -28,12 +27,12 @@ object StandaloneApplication {
// start CamelService // start CamelService
val camelService = CamelService.newInstance.load val camelService = CamelService.newInstance.load
// access 'externally' registered active objects // access 'externally' registered typed actors
assert("hello msg1" == context.createProducerTemplate.requestBody("direct:test1", "msg1")) assert("hello msg1" == context.createProducerTemplate.requestBody("direct:test1", "msg1"))
assert("hello msg2" == context.createProducerTemplate.requestBody("direct:test2", "msg2")) assert("hello msg2" == context.createProducerTemplate.requestBody("direct:test2", "msg2"))
// 'internally' register active object (requires CamelService) // 'internally' register typed actor (requires CamelService)
ActiveObject.newInstance(classOf[ConsumerPojo2]) TypedActor.newInstance(classOf[ConsumerPojo2], classOf[ConsumerPojo2Impl])
// internal registration is done in background. Wait a bit ... // internal registration is done in background. Wait a bit ...
Thread.sleep(1000) Thread.sleep(1000)
@ -52,7 +51,7 @@ object StandaloneApplication {
class StandaloneApplicationRoute extends RouteBuilder { class StandaloneApplicationRoute extends RouteBuilder {
def configure = { def configure = {
// routes to active objects (in SimpleRegistry) // routes to typed actors (in SimpleRegistry)
from("direct:test1").to("active-object:pojo1?method=foo") from("direct:test1").to("active-object:pojo1?method=foo")
from("direct:test2").to("active-object:pojo2?method=foo") from("direct:test2").to("active-object:pojo2?method=foo")
} }
@ -65,7 +64,7 @@ object StandaloneSpringApplication {
// load Spring application context // load Spring application context
val appctx = new ClassPathXmlApplicationContext("/context-standalone.xml") val appctx = new ClassPathXmlApplicationContext("/context-standalone.xml")
// access 'externally' registered active objects with active-object component // access 'externally' registered typed actors with active-object component
assert("hello msg3" == template.requestBody("direct:test3", "msg3")) assert("hello msg3" == template.requestBody("direct:test3", "msg3"))
// destroy Spring application context // destroy Spring application context
@ -78,7 +77,7 @@ object StandaloneSpringApplication {
class StandaloneSpringApplicationRoute extends RouteBuilder { class StandaloneSpringApplicationRoute extends RouteBuilder {
def configure = { def configure = {
// routes to active object (in ApplicationContextRegistry) // routes to typed actor (in ApplicationContextRegistry)
from("direct:test3").to("active-object:pojo3?method=foo") from("direct:test3").to("active-object:pojo3?method=foo")
} }
} }

View file

@ -4,11 +4,11 @@
package sample.rest.java; package sample.rest.java;
import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import se.scalablesolutions.akka.config.TypedActorConfigurator;
import static se.scalablesolutions.akka.config.JavaConfig.*; import static se.scalablesolutions.akka.config.JavaConfig.*;
public class Boot { public class Boot {
public final static ActiveObjectConfigurator configurator = new ActiveObjectConfigurator(); public final static TypedActorConfigurator configurator = new TypedActorConfigurator();
static { static {
configurator.configure( configurator.configure(
new RestartStrategy(new OneForOne(), 3, 5000, new Class[]{Exception.class}), new RestartStrategy(new OneForOne(), 3, 5000, new Class[]{Exception.class}),

View file

@ -4,42 +4,6 @@
package sample.rest.java; package sample.rest.java;
import se.scalablesolutions.akka.actor.annotation.transactionrequired; public interface PersistentSimpleService {
import se.scalablesolutions.akka.actor.annotation.prerestart; public String count();
import se.scalablesolutions.akka.actor.annotation.postrestart;
import se.scalablesolutions.akka.persistence.common.PersistentMap;
import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage;
import java.nio.ByteBuffer;
@transactionrequired
public class PersistentSimpleService {
private String KEY = "COUNTER";
private boolean hasStartedTicking = false;
private PersistentMap<byte[], byte[]> storage;
public String count() {
if (storage == null) storage = CassandraStorage.newMap();
if (!hasStartedTicking) {
storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(0).array());
hasStartedTicking = true;
return "Tick: 0\n";
} else {
byte[] bytes = (byte[])storage.get(KEY.getBytes()).get();
int counter = ByteBuffer.wrap(bytes).getInt();
storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(counter + 1).array());
return "Tick: " + counter + "\n";
}
}
@prerestart
public void preRestart() {
System.out.println("Prepare for restart by supervisor");
}
@postrestart
public void postRestart() {
System.out.println("Reinitialize after restart by supervisor");
}
} }

View file

@ -0,0 +1,42 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
package sample.rest.java;
import se.scalablesolutions.akka.actor.TypedTransactor;
import se.scalablesolutions.akka.persistence.common.PersistentMap;
import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage;
import java.nio.ByteBuffer;
public class PersistentSimpleServiceImpl extends TypedTransactor implements PersistentSimpleService {
private String KEY = "COUNTER";
private boolean hasStartedTicking = false;
private PersistentMap<byte[], byte[]> storage;
public String count() {
if (storage == null) storage = CassandraStorage.newMap();
if (!hasStartedTicking) {
storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(0).array());
hasStartedTicking = true;
return "Tick: 0\n";
} else {
byte[] bytes = (byte[])storage.get(KEY.getBytes()).get();
int counter = ByteBuffer.wrap(bytes).getInt();
storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(counter + 1).array());
return "Tick: " + counter + "\n";
}
}
@Override
public void preRestart(Throwable cause) {
System.out.println("Prepare for restart by supervisor");
}
@Override
public void postRestart(Throwable cause) {
System.out.println("Reinitialize after restart by supervisor");
}
}

View file

@ -4,17 +4,6 @@
package sample.rest.java; package sample.rest.java;
import javax.ws.rs.Path; public interface Receiver {
import javax.ws.rs.GET; SimpleService receive();
import javax.ws.rs.Produces;
import se.scalablesolutions.akka.actor.ActiveObject;
import se.scalablesolutions.akka.actor.ActiveObjectContext;
public class Receiver {
private ActiveObjectContext context = null;
public SimpleService receive() {
System.out.println("------ RECEIVE");
return (SimpleService) context.getSender();
}
} }

View file

@ -0,0 +1,14 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
package sample.rest.java;
import se.scalablesolutions.akka.actor.TypedActorContext;
import se.scalablesolutions.akka.actor.TypedActor;
public class ReceiverImpl extends TypedActor implements Receiver {
public SimpleService receive() {
return (SimpleService) getContext().getSender();
}
}

View file

@ -4,43 +4,6 @@
package sample.rest.java; package sample.rest.java;
import se.scalablesolutions.akka.actor.ActiveObject; public interface SimpleService {
import se.scalablesolutions.akka.actor.ActiveObjectContext; public String count();
import se.scalablesolutions.akka.actor.annotation.transactionrequired;
import se.scalablesolutions.akka.actor.annotation.prerestart;
import se.scalablesolutions.akka.actor.annotation.postrestart;
import se.scalablesolutions.akka.stm.TransactionalMap;
@transactionrequired
public class SimpleService {
private String KEY = "COUNTER";
private boolean hasStartedTicking = false;
private TransactionalMap<String, Integer> storage;
private Receiver receiver = ActiveObject.newInstance(Receiver.class);
public String count() {
if (storage == null) storage = new TransactionalMap<String, Integer>();
if (!hasStartedTicking) {
storage.put(KEY, 0);
hasStartedTicking = true;
return "Tick: 0\n";
} else {
// Grabs the sender address and returns it
//SimpleService sender = receiver.receive();
int counter = (Integer)storage.get(KEY).get() + 1;
storage.put(KEY, counter);
return "Tick: " + counter + "\n";
}
}
@prerestart
public void preRestart() {
System.out.println("Prepare for restart by supervisor");
}
@postrestart
public void postRestart() {
System.out.println("Reinitialize after restart by supervisor");
}
} }

View file

@ -0,0 +1,43 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
package sample.rest.java;
import se.scalablesolutions.akka.actor.TypedActor;
import se.scalablesolutions.akka.actor.TypedTransactor;
import se.scalablesolutions.akka.actor.TypedActorContext;
import se.scalablesolutions.akka.stm.TransactionalMap;
public class SimpleServiceImpl extends TypedTransactor implements SimpleService {
private String KEY = "COUNTER";
private boolean hasStartedTicking = false;
private TransactionalMap<String, Integer> storage;
private Receiver receiver = TypedActor.newInstance(Receiver.class, ReceiverImpl.class);
public String count() {
if (storage == null) storage = new TransactionalMap<String, Integer>();
if (!hasStartedTicking) {
storage.put(KEY, 0);
hasStartedTicking = true;
return "Tick: 0\n";
} else {
// Grabs the sender address and returns it
//SimpleService sender = receiver.receive();
int counter = (Integer)storage.get(KEY).get() + 1;
storage.put(KEY, counter);
return "Tick: " + counter + "\n";
}
}
@Override
public void preRestart(Throwable cause) {
System.out.println("Prepare for restart by supervisor");
}
@Override
public void postRestart(Throwable cause) {
System.out.println("Reinitialize after restart by supervisor");
}
}

View file

@ -10,7 +10,7 @@ http://www.akkasource.org/schema/akka
http://scalablesolutions.se/akka/akka-0.10.xsd"> http://scalablesolutions.se/akka/akka-0.10.xsd">
<bean id="wrappedService" <bean id="wrappedService"
class="se.scalablesolutions.akka.actor.ActiveObject" class="se.scalablesolutions.akka.actor.TypedActor"
factory-method="newInstance"> factory-method="newInstance">
<constructor-arg index="0" type="java.lang.Class" value="se.scalablesolutions.akka.spring.foo.MyPojo"/> <constructor-arg index="0" type="java.lang.Class" value="se.scalablesolutions.akka.spring.foo.MyPojo"/>
<constructor-arg index="1" value="1000"/> <constructor-arg index="1" value="1000"/>

View file

@ -21,10 +21,10 @@ import se.scalablesolutions.akka.remote.RemoteNode;
import se.scalablesolutions.akka.spring.foo.MyPojo; import se.scalablesolutions.akka.spring.foo.MyPojo;
/** /**
* Tests for spring configuration of active objects and supervisor configuration. * Tests for spring configuration of typed actors and supervisor configuration.
* @author michaelkober * @author michaelkober
*/ */
public class ActiveObjectConfigurationTest { public class TypedActorConfigurationTest {
private ApplicationContext context = null; private ApplicationContext context = null;
@ -50,7 +50,7 @@ public class ActiveObjectConfigurationTest {
} }
@Test @Test
public void testSimpleActiveObject() { public void testSimpleTypedActor() {
MyPojo myPojo = (MyPojo) context.getBean("simple-active-object"); MyPojo myPojo = (MyPojo) context.getBean("simple-active-object");
String msg = myPojo.getFoo(); String msg = myPojo.getFoo();
msg += myPojo.getBar(); msg += myPojo.getBar();
@ -58,20 +58,20 @@ public class ActiveObjectConfigurationTest {
} }
@Test(expected = FutureTimeoutException.class) @Test(expected = FutureTimeoutException.class)
public void testSimpleActiveObject_Timeout() { public void testSimpleTypedActor_Timeout() {
MyPojo myPojo = (MyPojo) context.getBean("simple-active-object"); MyPojo myPojo = (MyPojo) context.getBean("simple-active-object");
myPojo.longRunning(); myPojo.longRunning();
} }
@Test @Test
public void testSimpleActiveObject_NoTimeout() { public void testSimpleTypedActor_NoTimeout() {
MyPojo myPojo = (MyPojo) context.getBean("simple-active-object-long-timeout"); MyPojo myPojo = (MyPojo) context.getBean("simple-active-object-long-timeout");
String msg = myPojo.longRunning(); String msg = myPojo.longRunning();
assertEquals("this took long", msg); assertEquals("this took long", msg);
} }
@Test @Test
public void testTransactionalActiveObject() { public void testTransactionalTypedActor() {
MyPojo myPojo = (MyPojo) context.getBean("transactional-active-object"); MyPojo myPojo = (MyPojo) context.getBean("transactional-active-object");
String msg = myPojo.getFoo(); String msg = myPojo.getFoo();
msg += myPojo.getBar(); msg += myPojo.getBar();
@ -79,7 +79,7 @@ public class ActiveObjectConfigurationTest {
} }
@Test @Test
public void testRemoteActiveObject() { public void testRemoteTypedActor() {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
RemoteNode.start(); RemoteNode.start();

View file

@ -13,8 +13,8 @@ import org.junit.Test;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
import se.scalablesolutions.akka.actor.ActiveObject; import se.scalablesolutions.akka.actor.TypedActor;
import se.scalablesolutions.akka.config.ActiveObjectConfigurator; import se.scalablesolutions.akka.config.TypedActorConfigurator;
import se.scalablesolutions.akka.config.JavaConfig.AllForOne; import se.scalablesolutions.akka.config.JavaConfig.AllForOne;
import se.scalablesolutions.akka.config.JavaConfig.Component; import se.scalablesolutions.akka.config.JavaConfig.Component;
import se.scalablesolutions.akka.config.JavaConfig.LifeCycle; import se.scalablesolutions.akka.config.JavaConfig.LifeCycle;
@ -45,10 +45,10 @@ public class SupervisorConfigurationTest {
@Test @Test
public void testSupervision() { public void testSupervision() {
// get ActiveObjectConfigurator bean from spring context // get TypedActorConfigurator bean from spring context
ActiveObjectConfigurator myConfigurator = (ActiveObjectConfigurator) context TypedActorConfigurator myConfigurator = (TypedActorConfigurator) context
.getBean("supervision1"); .getBean("supervision1");
// get ActiveObjects // get TypedActors
Foo foo = myConfigurator.getInstance(Foo.class); Foo foo = myConfigurator.getInstance(Foo.class);
assertNotNull(foo); assertNotNull(foo);
IBar bar = myConfigurator.getInstance(IBar.class); IBar bar = myConfigurator.getInstance(IBar.class);
@ -59,7 +59,7 @@ public class SupervisorConfigurationTest {
@Test @Test
public void testTransactionalState() { public void testTransactionalState() {
ActiveObjectConfigurator conf = (ActiveObjectConfigurator) context TypedActorConfigurator conf = (TypedActorConfigurator) context
.getBean("supervision2"); .getBean("supervision2");
StatefulPojo stateful = conf.getInstance(StatefulPojo.class); StatefulPojo stateful = conf.getInstance(StatefulPojo.class);
stateful.setMapState("testTransactionalState", "some map state"); stateful.setMapState("testTransactionalState", "some map state");
@ -73,23 +73,23 @@ public class SupervisorConfigurationTest {
@Test @Test
public void testInitTransactionalState() { public void testInitTransactionalState() {
StatefulPojo stateful = ActiveObject.newInstance(StatefulPojo.class, StatefulPojo stateful = TypedActor.newInstance(StatefulPojo.class,
1000, true); 1000, true);
assertTrue("should be inititalized", stateful.isInitialized()); assertTrue("should be inititalized", stateful.isInitialized());
} }
@Test @Test
public void testSupervisionWithDispatcher() { public void testSupervisionWithDispatcher() {
ActiveObjectConfigurator myConfigurator = (ActiveObjectConfigurator) context TypedActorConfigurator myConfigurator = (TypedActorConfigurator) context
.getBean("supervision-with-dispatcher"); .getBean("supervision-with-dispatcher");
// get ActiveObjects // get TypedActors
Foo foo = myConfigurator.getInstance(Foo.class); Foo foo = myConfigurator.getInstance(Foo.class);
assertNotNull(foo); assertNotNull(foo);
// TODO how to check dispatcher? // TODO how to check dispatcher?
} }
@Test @Test
public void testRemoteActiveObject() { public void testRemoteTypedActor() {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
RemoteNode.start(); RemoteNode.start();
@ -99,13 +99,13 @@ public class SupervisorConfigurationTest {
Thread.currentThread().sleep(1000); Thread.currentThread().sleep(1000);
} catch (Exception e) { } catch (Exception e) {
} }
Foo instance = ActiveObject.newRemoteInstance(Foo.class, 2000, "localhost", 9999); Foo instance = TypedActor.newRemoteInstance(Foo.class, 2000, "localhost", 9999);
System.out.println(instance.foo()); System.out.println(instance.foo());
} }
@Test @Test
public void testSupervisedRemoteActiveObject() { public void testSupervisedRemoteTypedActor() {
new Thread(new Runnable() { new Thread(new Runnable() {
public void run() { public void run() {
RemoteNode.start(); RemoteNode.start();
@ -116,7 +116,7 @@ public class SupervisorConfigurationTest {
} catch (Exception e) { } catch (Exception e) {
} }
ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); TypedActorConfigurator conf = new TypedActorConfigurator();
conf.configure( conf.configure(
new RestartStrategy(new AllForOne(), 3, 10000, new Class[] { Exception.class }), new RestartStrategy(new AllForOne(), 3, 10000, new Class[] { Exception.class }),
new Component[] { new Component[] {

View file

@ -134,7 +134,7 @@
</xsd:attribute> </xsd:attribute>
</xsd:complexType> </xsd:complexType>
<!-- active object --> <!-- typed actor -->
<xsd:complexType name="active-object-type"> <xsd:complexType name="active-object-type">
<xsd:sequence> <xsd:sequence>
<xsd:element name="remote" type="remote-type" minOccurs="0" maxOccurs="1"/> <xsd:element name="remote" type="remote-type" minOccurs="0" maxOccurs="1"/>
@ -196,7 +196,7 @@
</xsd:choice> </xsd:choice>
</xsd:complexType> </xsd:complexType>
<!-- active objects --> <!-- typed actors -->
<xsd:complexType name="active-objects-type"> <xsd:complexType name="active-objects-type">
<xsd:choice minOccurs="1" maxOccurs="unbounded"> <xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="active-object" type="active-object-type"/> <xsd:element name="active-object" type="active-object-type"/>
@ -252,7 +252,7 @@
<xsd:attribute name="ref" type="xsd:string"/> <xsd:attribute name="ref" type="xsd:string"/>
</xsd:complexType> </xsd:complexType>
<!-- ActiveObject --> <!-- TypedActor -->
<xsd:element name="active-object" type="active-object-type"/> <xsd:element name="active-object" type="active-object-type"/>
<!-- Dispatcher --> <!-- Dispatcher -->

View file

@ -1,198 +0,0 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
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
import org.springframework.beans.BeanWrapper
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.BeanFactory
import org.springframework.beans.factory.config.AbstractFactoryBean
import org.springframework.context.{ApplicationContext,ApplicationContextAware}
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, Duration}
/**
* Factory bean for active objects.
*
* @author michaelkober
* @author <a href="johan.rask@jayway.com">Johan Rask</a>
* @author Martin Krasser
*/
class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with ApplicationContextAware {
import StringReflect._
import AkkaSpringConfigurationTags._
@BeanProperty var target: String = ""
@BeanProperty var timeout: Long = _
@BeanProperty var interface: String = ""
@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 = ""
@BeanProperty var dispatcher: DispatcherProperties = _
@BeanProperty var scope:String = VAL_SCOPE_SINGLETON
@BeanProperty var property:PropertyEntries = _
@BeanProperty var applicationContext:ApplicationContext = _
// Holds info about if deps has been set or not. Depends on
// if interface is specified or not. We must set deps on
// target instance if interface is specified
var hasSetDependecies = false
override def isSingleton:Boolean = {
if(scope.equals(VAL_SCOPE_SINGLETON)) {
true
} else {
false
}
}
/*
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
def getObjectType: Class[AnyRef] = try {
target.toClass
} catch {
// required by contract to return null
case e: ClassNotFoundException => null
}
/*
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
def createInstance: AnyRef = {
var argumentList = ""
if (isRemote) argumentList += "r"
if (hasInterface) argumentList += "i"
if (hasDispatcher) argumentList += "d"
postConstruct(
setProperties(
create(argumentList)))
}
/**
* Stop the active object if it is a singleton.
*/
override def destroyInstance(instance:AnyRef) {
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) {
if(method.isAnnotationPresent(classOf[PostConstruct])) {
method.invoke(ref)
}
}
ref
}
private def setProperties(ref:AnyRef) : AnyRef = {
if(hasSetDependecies) {
return ref
}
log.debug("Processing properties and dependencies for target class %s",target)
val beanWrapper = new BeanWrapperImpl(ref);
if(ref.isInstanceOf[ApplicationContextAware]) {
log.debug("Setting application context")
beanWrapper.setPropertyValue("applicationContext",applicationContext)
}
for(entry <- property.entryList) {
val propertyDescriptor = BeanUtils.getPropertyDescriptor(ref.getClass,entry.name)
val method = propertyDescriptor.getWriteMethod();
if(StringUtils.hasText(entry.ref)) {
log.debug("Setting property %s with bean ref %s using method %s",
entry.name,entry.ref,method.getName)
method.invoke(ref,getBeanFactory().getBean(entry.ref))
} else if(StringUtils.hasText(entry.value)) {
log.debug("Setting property %s with value %s using method %s",
entry.name,entry.value,method.getName)
beanWrapper.setPropertyValue(entry.name,entry.value)
} else {
throw new AkkaBeansException("Either property@ref or property@value must be set on property element")
}
}
ref
}
private[akka] def create(argList : String) : AnyRef = {
if (argList == "r") {
ActiveObject.newInstance(target.toClass, createConfig.makeRemote(host, port))
} else if (argList == "ri" ) {
ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.makeRemote(host, port))
} else if (argList == "rd") {
ActiveObject.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
} else if (argList == "rid") {
ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
} else if (argList == "i") {
ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig)
} else if (argList == "id") {
ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.dispatcher(dispatcherInstance))
} else if (argList == "d") {
ActiveObject.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance))
} else {
ActiveObject.newInstance(target.toClass, createConfig)
}
}
private[akka] def createConfig: ActiveObjectConfiguration = {
val config = new ActiveObjectConfiguration().timeout(Duration(timeout, "millis"))
if (hasRestartCallbacks) config.restartCallbacks(pre, post)
if (hasShutdownCallback) config.shutdownCallback(shutdown)
if (transactional) config.makeTransactionRequired
config
}
def aNewInstance[T <: AnyRef](clazz: Class[T]) : T = {
var ref = clazz.newInstance().asInstanceOf[T]
postConstruct(
setProperties(ref))
hasSetDependecies = true
ref
}
private[akka] def isRemote = (host != null) && (!host.isEmpty)
private[akka] def hasInterface = (interface != null) && (!interface.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)
private[akka] def dispatcherInstance : MessageDispatcher = {
import DispatcherFactoryBean._
createNewInstance(dispatcher)
}
}

View file

@ -12,7 +12,7 @@ import AkkaSpringConfigurationTags._
*/ */
class AkkaNamespaceHandler extends NamespaceHandlerSupport { class AkkaNamespaceHandler extends NamespaceHandlerSupport {
def init = { def init = {
registerBeanDefinitionParser(ACTIVE_OBJECT_TAG, new ActiveObjectBeanDefinitionParser()); registerBeanDefinitionParser(ACTIVE_OBJECT_TAG, new TypedActorBeanDefinitionParser());
registerBeanDefinitionParser(SUPERVISION_TAG, new SupervisionBeanDefinitionParser()); registerBeanDefinitionParser(SUPERVISION_TAG, new SupervisionBeanDefinitionParser());
registerBeanDefinitionParser(DISPATCHER_TAG, new DispatcherBeanDefinitionParser()); registerBeanDefinitionParser(DISPATCHER_TAG, new DispatcherBeanDefinitionParser());
registerBeanDefinitionParser(CAMEL_SERVICE_TAG, new CamelServiceBeanDefinitionParser); registerBeanDefinitionParser(CAMEL_SERVICE_TAG, new CamelServiceBeanDefinitionParser);

View file

@ -38,7 +38,7 @@ object AkkaSpringConfigurationTags {
// --- ATTRIBUTES // --- ATTRIBUTES
// //
// active object attributes // typed actor attributes
val TIMEOUT = "timeout" val TIMEOUT = "timeout"
val TARGET = "target" val TARGET = "target"
val INTERFACE = "interface" val INTERFACE = "interface"

View file

@ -12,7 +12,7 @@ import org.springframework.beans.factory.xml.{ParserContext, AbstractSingleBeanD
* Parser for custom namespace configuration. * Parser for custom namespace configuration.
* @author michaelkober * @author michaelkober
*/ */
class DispatcherBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActiveObjectParser with DispatcherParser { class DispatcherBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with TypedActorParser with DispatcherParser {
/* /*
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder) * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/ */

View file

@ -18,7 +18,7 @@ import org.springframework.util.xml.DomUtils
* Parser for custom namespace for Akka declarative supervisor configuration. * Parser for custom namespace for Akka declarative supervisor configuration.
* @author michaelkober * @author michaelkober
*/ */
class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActiveObjectParser { class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with TypedActorParser {
/* (non-Javadoc) /* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder) * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/ */
@ -33,7 +33,7 @@ class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser
val strategyElement = mandatoryElement(element, STRATEGY_TAG); val strategyElement = mandatoryElement(element, STRATEGY_TAG);
val activeObjectsElement = mandatoryElement(element, ACTIVE_OBJECTS_TAG); val activeObjectsElement = mandatoryElement(element, ACTIVE_OBJECTS_TAG);
parseRestartStrategy(strategyElement, builder) parseRestartStrategy(strategyElement, builder)
parseActiveObjectList(activeObjectsElement, builder) parseTypedActorList(activeObjectsElement, builder)
} }
private[akka] def parseRestartStrategy(element: Element, builder: BeanDefinitionBuilder) { private[akka] def parseRestartStrategy(element: Element, builder: BeanDefinitionBuilder) {
@ -46,9 +46,9 @@ class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser
builder.addPropertyValue("restartStrategy", restartStrategy) builder.addPropertyValue("restartStrategy", restartStrategy)
} }
private[akka] def parseActiveObjectList(element: Element, builder: BeanDefinitionBuilder) { private[akka] def parseTypedActorList(element: Element, builder: BeanDefinitionBuilder) {
val activeObjects = DomUtils.getChildElementsByTagName(element, ACTIVE_OBJECT_TAG).toArray.toList.asInstanceOf[List[Element]] val activeObjects = DomUtils.getChildElementsByTagName(element, ACTIVE_OBJECT_TAG).toArray.toList.asInstanceOf[List[Element]]
val activeObjectProperties = activeObjects.map(parseActiveObject(_)) val activeObjectProperties = activeObjects.map(parseTypedActor(_))
builder.addPropertyValue("supervised", activeObjectProperties) builder.addPropertyValue("supervised", activeObjectProperties)
} }

View file

@ -4,7 +4,7 @@
package se.scalablesolutions.akka.spring package se.scalablesolutions.akka.spring
import org.springframework.beans.factory.config.AbstractFactoryBean import org.springframework.beans.factory.config.AbstractFactoryBean
import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.TypedActorConfigurator
import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.config.JavaConfig._
import AkkaSpringConfigurationTags._ import AkkaSpringConfigurationTags._
import reflect.BeanProperty import reflect.BeanProperty
@ -14,20 +14,20 @@ import reflect.BeanProperty
* Factory bean for supervisor configuration. * Factory bean for supervisor configuration.
* @author michaelkober * @author michaelkober
*/ */
class SupervisionFactoryBean extends AbstractFactoryBean[ActiveObjectConfigurator] { class SupervisionFactoryBean extends AbstractFactoryBean[TypedActorConfigurator] {
@BeanProperty var restartStrategy: RestartStrategy = _ @BeanProperty var restartStrategy: RestartStrategy = _
@BeanProperty var supervised: List[ActiveObjectProperties] = _ @BeanProperty var supervised: List[TypedActorProperties] = _
/* /*
* @see org.springframework.beans.factory.FactoryBean#getObjectType() * @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/ */
def getObjectType: Class[ActiveObjectConfigurator] = classOf[ActiveObjectConfigurator] def getObjectType: Class[TypedActorConfigurator] = classOf[TypedActorConfigurator]
/* /*
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance() * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/ */
def createInstance: ActiveObjectConfigurator = { def createInstance: TypedActorConfigurator = {
val configurator = new ActiveObjectConfigurator() val configurator = new TypedActorConfigurator()
configurator.configure( configurator.configure(
restartStrategy, restartStrategy,
@ -36,9 +36,9 @@ class SupervisionFactoryBean extends AbstractFactoryBean[ActiveObjectConfigurato
} }
/** /**
* Create configuration for ActiveObject * Create configuration for TypedActor
*/ */
private[akka] def createComponent(props: ActiveObjectProperties): Component = { private[akka] def createComponent(props: TypedActorProperties): Component = {
import StringReflect._ import StringReflect._
val lifeCycle = if (!props.lifecycle.isEmpty && props.lifecycle.equalsIgnoreCase(VAL_LIFECYCYLE_TEMPORARY)) new LifeCycle(new Temporary()) else new LifeCycle(new Permanent()) val lifeCycle = if (!props.lifecycle.isEmpty && props.lifecycle.equalsIgnoreCase(VAL_LIFECYCYLE_TEMPORARY)) new LifeCycle(new Temporary()) else new LifeCycle(new Permanent())
val isRemote = (props.host != null) && (!props.host.isEmpty) val isRemote = (props.host != null) && (!props.host.isEmpty)

View file

@ -13,17 +13,17 @@ import org.w3c.dom.Element
* Parser for custom namespace configuration. * Parser for custom namespace configuration.
* @author michaelkober * @author michaelkober
*/ */
class ActiveObjectBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActiveObjectParser { class TypedActorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with TypedActorParser {
/* /*
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder) * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
*/ */
override def doParse(element: Element, parserContext: ParserContext, builder: BeanDefinitionBuilder) { override def doParse(element: Element, parserContext: ParserContext, builder: BeanDefinitionBuilder) {
val activeObjectConf = parseActiveObject(element) val activeObjectConf = parseTypedActor(element)
activeObjectConf.setAsProperties(builder) activeObjectConf.setAsProperties(builder)
} }
/* /*
* @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element) * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
*/ */
override def getBeanClass(element: Element): Class[_] = classOf[ActiveObjectFactoryBean] override def getBeanClass(element: Element): Class[_] = classOf[TypedActorFactoryBean]
} }

View file

@ -0,0 +1,167 @@
/**
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
*/
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
import org.springframework.beans.BeanWrapper
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.BeanFactory
import org.springframework.beans.factory.config.AbstractFactoryBean
import org.springframework.context.{ApplicationContext,ApplicationContextAware}
import org.springframework.util.ReflectionUtils
import org.springframework.util.StringUtils
import se.scalablesolutions.akka.actor.{TypedActorConfiguration, TypedActor}
import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks}
import se.scalablesolutions.akka.dispatch.MessageDispatcher
import se.scalablesolutions.akka.util.{Logging, Duration}
/**
* Factory bean for typed actors.
*
* @author michaelkober
* @author <a href="johan.rask@jayway.com">Johan Rask</a>
* @author Martin Krasser
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with ApplicationContextAware {
import StringReflect._
import AkkaSpringConfigurationTags._
@BeanProperty var target: String = ""
@BeanProperty var timeout: Long = _
@BeanProperty var interface: String = ""
@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 = ""
@BeanProperty var dispatcher: DispatcherProperties = _
@BeanProperty var scope: String = VAL_SCOPE_SINGLETON
@BeanProperty var property: PropertyEntries = _
@BeanProperty var applicationContext: ApplicationContext = _
// Holds info about if deps has been set or not. Depends on
// if interface is specified or not. We must set deps on
// target instance if interface is specified
var hasSetDependecies = false
override def isSingleton = scope.equals(VAL_SCOPE_SINGLETON)
/*
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
def getObjectType: Class[AnyRef] = try {
target.toClass
} catch {
// required by contract to return null
case e: ClassNotFoundException => null
}
/*
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
def createInstance: AnyRef = {
var argumentList = ""
if (isRemote) argumentList += "r"
if (hasInterface) argumentList += "i"
if (hasDispatcher) argumentList += "d"
postConstruct(setProperties(create(argumentList)))
}
/**
* Stop the typed actor if it is a singleton.
*/
override def destroyInstance(instance: AnyRef) = TypedActor.stop(instance.asInstanceOf[TypedActor])
/**
* Invokes any method annotated with @PostConstruct
* When interfaces are specified, this method is invoked both on the
* target instance and on the typed actor, so a developer is free do decide
* where the annotation should be. If no interface is specified it is only invoked
* on the typed actor
*/
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
log.debug("Processing properties and dependencies for target class\n\t[%s]", target)
val beanWrapper = new BeanWrapperImpl(ref);
if (ref.isInstanceOf[ApplicationContextAware]) {
log.debug("Setting application context")
beanWrapper.setPropertyValue("applicationContext", applicationContext)
}
for (entry <- property.entryList) {
val propertyDescriptor = BeanUtils.getPropertyDescriptor(ref.getClass, entry.name)
val method = propertyDescriptor.getWriteMethod
if (StringUtils.hasText(entry.ref)) {
log.debug("Setting property %s with bean ref %s using method %s", entry.name, entry.ref, method.getName)
method.invoke(ref,getBeanFactory().getBean(entry.ref))
} else if(StringUtils.hasText(entry.value)) {
log.debug("Setting property %s with value %s using method %s", entry.name, entry.value, method.getName)
beanWrapper.setPropertyValue(entry.name,entry.value)
} else throw new AkkaBeansException("Either property@ref or property@value must be set on property element")
}
ref
}
private[akka] def create(argList: String) : AnyRef = argList match {
case "ri" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.makeRemote(host, port))
case "i" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig)
case "id" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.dispatcher(dispatcherInstance))
case "rid" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass),
createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
// case "rd" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
// case "r" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port))
// case "d" => TypedActor.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance))
case _ => throw new AkkaBeansException("Illegal configuration argument list for TypedActor Spring bean [" + argList + "]")
}
private[akka] def createConfig: TypedActorConfiguration = {
val config = new TypedActorConfiguration().timeout(Duration(timeout, "millis"))
if (hasRestartCallbacks) config.restartCallbacks(pre, post)
if (hasShutdownCallback) config.shutdownCallback(shutdown)
if (transactional) config.makeTransactionRequired
config
}
def newInstanceFor[T <: AnyRef](clazz: Class[T]) : T = {
var ref = clazz.newInstance().asInstanceOf[T]
postConstruct(setProperties(ref))
hasSetDependecies = true
ref
}
private[akka] def isRemote = (host != null) && (!host.isEmpty)
private[akka] def hasInterface = (interface != null) && (!interface.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)
private[akka] def dispatcherInstance: MessageDispatcher = {
import DispatcherFactoryBean._
createNewInstance(dispatcher)
}
}

View file

@ -15,16 +15,16 @@ import se.scalablesolutions.akka.actor.IllegalActorStateException
* @author <a href="johan.rask@jayway.com">Johan Rask</a> * @author <a href="johan.rask@jayway.com">Johan Rask</a>
* @author Martin Krasser * @author Martin Krasser
*/ */
trait ActiveObjectParser extends BeanParser with DispatcherParser { trait TypedActorParser extends BeanParser with DispatcherParser {
import AkkaSpringConfigurationTags._ import AkkaSpringConfigurationTags._
/** /**
* Parses the given element and returns a ActiveObjectProperties. * Parses the given element and returns a TypedActorProperties.
* @param element dom element to parse * @param element dom element to parse
* @return configuration for the active object * @return configuration for the typed actor
*/ */
def parseActiveObject(element: Element): ActiveObjectProperties = { def parseTypedActor(element: Element): TypedActorProperties = {
val objectProperties = new ActiveObjectProperties() val objectProperties = new TypedActorProperties()
val remoteElement = DomUtils.getChildElementByTagName(element, REMOTE_TAG); val remoteElement = DomUtils.getChildElementByTagName(element, REMOTE_TAG);
val restartCallbacksElement = DomUtils.getChildElementByTagName(element, RESTART_CALLBACKS_TAG); val restartCallbacksElement = DomUtils.getChildElementByTagName(element, RESTART_CALLBACKS_TAG);
val shutdownCallbackElement = DomUtils.getChildElementByTagName(element, SHUTDOWN_CALLBACK_TAG); val shutdownCallbackElement = DomUtils.getChildElementByTagName(element, SHUTDOWN_CALLBACK_TAG);

View file

@ -8,11 +8,11 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder
import AkkaSpringConfigurationTags._ import AkkaSpringConfigurationTags._
/** /**
* Data container for active object configuration data. * Data container for typed actor configuration data.
* @author michaelkober * @author michaelkober
* @author Martin Krasser * @author Martin Krasser
*/ */
class ActiveObjectProperties { class TypedActorProperties {
var target: String = "" var target: String = ""
var timeout: Long = _ var timeout: Long = _
var interface: String = "" var interface: String = ""

View file

@ -12,16 +12,16 @@ import ScalaDom._
import org.w3c.dom.Element import org.w3c.dom.Element
/** /**
* Test for ActiveObjectParser * Test for TypedActorParser
* @author michaelkober * @author michaelkober
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ActiveObjectBeanDefinitionParserTest extends Spec with ShouldMatchers { class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers {
private class Parser extends ActiveObjectParser private class Parser extends TypedActorParser
describe("An ActiveObjectParser") { describe("An TypedActorParser") {
val parser = new Parser() val parser = new Parser()
it("should parse the active object configuration") { it("should parse the typed actor configuration") {
val xml = <akka:active-object id="active-object1" val xml = <akka:active-object id="active-object1"
target="foo.bar.MyPojo" target="foo.bar.MyPojo"
timeout="1000" timeout="1000"
@ -30,7 +30,7 @@ class ActiveObjectBeanDefinitionParserTest extends Spec with ShouldMatchers {
<property name="someProp" value="someValue" ref="someRef"/> <property name="someProp" value="someValue" ref="someRef"/>
</akka:active-object> </akka:active-object>
val props = parser.parseActiveObject(dom(xml).getDocumentElement); val props = parser.parseTypedActor(dom(xml).getDocumentElement);
assert(props != null) assert(props != null)
assert(props.timeout === 1000) assert(props.timeout === 1000)
assert(props.target === "foo.bar.MyPojo") assert(props.target === "foo.bar.MyPojo")
@ -44,25 +44,25 @@ class ActiveObjectBeanDefinitionParserTest extends Spec with ShouldMatchers {
timeout="1000" timeout="1000"
transactional="true"/> transactional="true"/>
evaluating { parser.parseActiveObject(dom(xml).getDocumentElement) } should produce [IllegalArgumentException] evaluating { parser.parseTypedActor(dom(xml).getDocumentElement) } should produce [IllegalArgumentException]
} }
it("should parse ActiveObjects configuration with dispatcher") { it("should parse TypedActors configuration with dispatcher") {
val xml = <akka:active-object id="active-object-with-dispatcher" target="se.scalablesolutions.akka.spring.foo.MyPojo" val xml = <akka:active-object id="active-object-with-dispatcher" target="se.scalablesolutions.akka.spring.foo.MyPojo"
timeout="1000"> timeout="1000">
<akka:dispatcher type="thread-based" name="my-thread-based-dispatcher"/> <akka:dispatcher type="thread-based" name="my-thread-based-dispatcher"/>
</akka:active-object> </akka:active-object>
val props = parser.parseActiveObject(dom(xml).getDocumentElement); val props = parser.parseTypedActor(dom(xml).getDocumentElement);
assert(props != null) assert(props != null)
assert(props.dispatcher.dispatcherType === "thread-based") assert(props.dispatcher.dispatcherType === "thread-based")
} }
it("should parse remote ActiveObjects configuration") { it("should parse remote TypedActors configuration") {
val xml = <akka:active-object id="remote active-object" target="se.scalablesolutions.akka.spring.foo.MyPojo" val xml = <akka:active-object id="remote active-object" target="se.scalablesolutions.akka.spring.foo.MyPojo"
timeout="1000"> timeout="1000">
<akka:remote host="com.some.host" port="9999"/> <akka:remote host="com.some.host" port="9999"/>
</akka:active-object> </akka:active-object>
val props = parser.parseActiveObject(dom(xml).getDocumentElement); val props = parser.parseTypedActor(dom(xml).getDocumentElement);
assert(props != null) assert(props != null)
assert(props.host === "com.some.host") assert(props.host === "com.some.host")
assert(props.port === 9999) assert(props.port === 9999)

View file

@ -11,14 +11,14 @@ import org.springframework.core.io.ResourceEditor
import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
/** /**
* Test for ActiveObjectFactoryBean * Test for TypedActorFactoryBean
* @author michaelkober * @author michaelkober
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { class TypedActorFactoryBeanTest extends Spec with ShouldMatchers {
describe("A ActiveObjectFactoryBean") { describe("A TypedActorFactoryBean") {
val bean = new ActiveObjectFactoryBean val bean = new TypedActorFactoryBean
it("should have java getters and setters for all properties") { it("should have java getters and setters for all properties") {
bean.setTarget("java.lang.String") bean.setTarget("java.lang.String")
assert(bean.getTarget == "java.lang.String") assert(bean.getTarget == "java.lang.String")
@ -26,7 +26,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers {
assert(bean.getTimeout == 1000) assert(bean.getTimeout == 1000)
} }
it("should create a remote active object when a host is set") { it("should create a remote typed actor when a host is set") {
bean.setHost("some.host.com"); bean.setHost("some.host.com");
assert(bean.isRemote) assert(bean.isRemote)
} }
@ -36,7 +36,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers {
assert(bean.hasInterface) assert(bean.hasInterface)
} }
it("should create an active object with dispatcher if dispatcher is set") { it("should create an typed actor with dispatcher if dispatcher is set") {
val props = new DispatcherProperties() val props = new DispatcherProperties()
props.dispatcherType = "executor-based-event-driven" props.dispatcherType = "executor-based-event-driven"
bean.setDispatcher(props); bean.setDispatcher(props);
@ -49,7 +49,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers {
} }
it("should create a proxy of type ResourceEditor") { it("should create a proxy of type ResourceEditor") {
val bean = new ActiveObjectFactoryBean() val bean = new TypedActorFactoryBean()
// we must have a java class here // we must have a java class here
bean.setTarget("org.springframework.core.io.ResourceEditor") bean.setTarget("org.springframework.core.io.ResourceEditor")
val entries = new PropertyEntries() val entries = new PropertyEntries()
@ -78,7 +78,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers {
assert(pojoInf.gotApplicationContext) assert(pojoInf.gotApplicationContext)
} }
it("should stop the created active object when scope is singleton and the context is closed") { it("should stop the created typed actor when scope is singleton and the context is closed") {
var ctx = new ClassPathXmlApplicationContext("appContext.xml"); var ctx = new ClassPathXmlApplicationContext("appContext.xml");
val target = ctx.getBean("bean-singleton").asInstanceOf[SampleBean] val target = ctx.getBean("bean-singleton").asInstanceOf[SampleBean]
assert(!target.down) assert(!target.down)
@ -86,7 +86,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers {
assert(target.down) assert(target.down)
} }
it("should not stop the created active object when scope is prototype and the context is closed") { it("should not stop the created typed actor when scope is prototype and the context is closed") {
var ctx = new ClassPathXmlApplicationContext("appContext.xml"); var ctx = new ClassPathXmlApplicationContext("appContext.xml");
val target = ctx.getBean("bean-prototype").asInstanceOf[SampleBean] val target = ctx.getBean("bean-prototype").asInstanceOf[SampleBean]
assert(!target.down) assert(!target.down)

View file

@ -6,7 +6,7 @@ import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FeatureSpec}
import org.springframework.context.support.ClassPathXmlApplicationContext import org.springframework.context.support.ClassPathXmlApplicationContext
import se.scalablesolutions.akka.camel.CamelContextManager import se.scalablesolutions.akka.camel.CamelContextManager
import se.scalablesolutions.akka.actor.{ActiveObject, ActorRegistry} import se.scalablesolutions.akka.actor.{TypedActor, ActorRegistry}
class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach with BeforeAndAfterAll { class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach with BeforeAndAfterAll {
override protected def beforeAll = { override protected def beforeAll = {
@ -20,22 +20,22 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach
feature("start CamelService from Spring application context") { feature("start CamelService from Spring application context") {
import CamelContextManager._ import CamelContextManager._
scenario("with a custom CamelContext and access a registered active object") { scenario("with a custom CamelContext and access a registered typed actor") {
val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceCustom.xml") val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceCustom.xml")
assert(context.isInstanceOf[SpringCamelContext]) assert(context.isInstanceOf[SpringCamelContext])
assert("hello sample" === template.requestBody("direct:test", "sample")) assert("hello sample" === template.requestBody("direct:test", "sample"))
appctx.close appctx.close
} }
scenario("with a default CamelContext and access a registered active object") { scenario("with a default CamelContext and access a registered typed actor") {
val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceDefault.xml") val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceDefault.xml")
// create a custom registry // create a custom registry
val registry = new SimpleRegistry val registry = new SimpleRegistry
registry.put("custom", ActiveObject.newInstance(classOf[SampleBean])) registry.put("custom", TypedActor.newInstance(classOf[SampleBean]))
// set custom registry in DefaultCamelContext // set custom registry in DefaultCamelContext
assert(context.isInstanceOf[DefaultCamelContext]) assert(context.isInstanceOf[DefaultCamelContext])
context.asInstanceOf[DefaultCamelContext].setRegistry(registry) context.asInstanceOf[DefaultCamelContext].setRegistry(registry)
// access registered active object // access registered typed actor
assert("hello sample" === template.requestBody("active-object:custom?method=foo", "sample")) assert("hello sample" === template.requestBody("active-object:custom?method=foo", "sample"))
appctx.close appctx.close
} }

View file

@ -89,7 +89,7 @@ class DispatcherBeanDefinitionParserTest extends Spec with ShouldMatchers {
} }
it("should throw IllegalArgumentException when configuring a thread based dispatcher without ActiveObject") { it("should throw IllegalArgumentException when configuring a thread based dispatcher without TypedActor") {
val xml = <akka:dispatcher id="dispatcher" type="thread-based" name="myDispatcher" /> val xml = <akka:dispatcher id="dispatcher" type="thread-based" name="myDispatcher" />
evaluating { parser.parseDispatcher(dom(xml).getDocumentElement) } should produce [IllegalArgumentException] evaluating { parser.parseDispatcher(dom(xml).getDocumentElement) } should produce [IllegalArgumentException]
} }

View file

@ -26,8 +26,8 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
val parser = new Parser() val parser = new Parser()
val builder = BeanDefinitionBuilder.genericBeanDefinition("foo.bar.Foo") val builder = BeanDefinitionBuilder.genericBeanDefinition("foo.bar.Foo")
it("should be able to parse active object configuration") { it("should be able to parse typed actor configuration") {
val props = parser.parseActiveObject(createActiveObjectElement); val props = parser.parseTypedActor(createTypedActorElement);
assert(props != null) assert(props != null)
assert(props.timeout == 1000) assert(props.timeout == 1000)
assert(props.target == "foo.bar.MyPojo") assert(props.target == "foo.bar.MyPojo")
@ -45,9 +45,9 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
expect(1000) { strategy.withinTimeRange } expect(1000) { strategy.withinTimeRange }
} }
it("should parse the supervised active objects") { it("should parse the supervised typed actors") {
parser.parseSupervisor(createSupervisorElement, builder); parser.parseSupervisor(createSupervisorElement, builder);
val supervised = builder.getBeanDefinition.getPropertyValues.getPropertyValue("supervised").getValue.asInstanceOf[List[ActiveObjectProperties]] val supervised = builder.getBeanDefinition.getPropertyValues.getPropertyValue("supervised").getValue.asInstanceOf[List[TypedActorProperties]]
assert(supervised != null) assert(supervised != null)
expect(4) { supervised.length } expect(4) { supervised.length }
val iterator = supervised.iterator val iterator = supervised.iterator
@ -75,7 +75,7 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
} }
} }
private def createActiveObjectElement : Element = { private def createTypedActorElement : Element = {
val xml = <akka:active-object id="active-object1" val xml = <akka:active-object id="active-object1"
target="foo.bar.MyPojo" target="foo.bar.MyPojo"
timeout="1000" timeout="1000"

View file

@ -8,7 +8,7 @@ import org.scalatest.matchers.ShouldMatchers
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith import org.junit.runner.RunWith
import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.config.JavaConfig._
import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.TypedActorConfigurator
private[akka] class Foo private[akka] class Foo
@ -16,10 +16,10 @@ private[akka] class Foo
class SupervisionFactoryBeanTest extends Spec with ShouldMatchers { class SupervisionFactoryBeanTest extends Spec with ShouldMatchers {
val restartStrategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Throwable])) val restartStrategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Throwable]))
val activeObjects = List(createActiveObjectProperties("se.scalablesolutions.akka.spring.Foo", 1000L)) val activeObjects = List(createTypedActorProperties("se.scalablesolutions.akka.spring.Foo", 1000L))
def createActiveObjectProperties(target: String, timeout: Long) : ActiveObjectProperties = { def createTypedActorProperties(target: String, timeout: Long) : TypedActorProperties = {
val properties = new ActiveObjectProperties() val properties = new TypedActorProperties()
properties.target = target properties.target = target
properties.timeout = timeout properties.timeout = timeout
properties properties
@ -34,8 +34,8 @@ class SupervisionFactoryBeanTest extends Spec with ShouldMatchers {
assert(bean.getSupervised == activeObjects) assert(bean.getSupervised == activeObjects)
} }
it("should return the object type ActiveObjectConfigurator") { it("should return the object type TypedActorConfigurator") {
assert(bean.getObjectType == classOf[ActiveObjectConfigurator]) assert(bean.getObjectType == classOf[TypedActorConfigurator])
} }
} }
} }

View file

@ -24,7 +24,7 @@ akka {
time-unit = "seconds" # default timeout time unit for all timeout properties throughout the config time-unit = "seconds" # default timeout time unit for all timeout properties throughout the config
# FQN (Fully Qualified Name) to the class doing initial active object/actor # FQN (Fully Qualified Name) to the class doing initial typed actor/actor
# supervisor bootstrap, should be defined in default constructor # supervisor bootstrap, should be defined in default constructor
boot = ["sample.camel.Boot", boot = ["sample.camel.Boot",
"sample.rest.java.Boot", "sample.rest.java.Boot",

View file

@ -585,7 +585,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
// Test // Test
// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
class AkkaActiveObjectTestProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaTypedActorTestProject(info: ProjectInfo) extends DefaultProject(info) {
// testing // testing
val junit = "junit" % "junit" % "4.5" % "test" val junit = "junit" % "junit" % "4.5" % "test"
val jmock = "org.jmock" % "jmock" % "2.4.0" % "test" val jmock = "org.jmock" % "jmock" % "2.4.0" % "test"