();
+ for (int i = 0; i < components.length; i++) {
+ final Component c = components[i];
+ final ActiveObjectProxy activeObjectProxy = new ActiveObjectProxy(c.intf(), c.target(), c.timeout());
+ workers.add(c.newWorker(activeObjectProxy));
+ activeObjectRegistry.put(c.intf(), activeObjectProxy);
+ }
+ supervisor = activeObjectFactory.supervise(restartStrategy.transform(), workers);
+ return this;
+ }
+
+
+ /**
+ * Add additional services to be wired in.
+ *
+ * ActiveObjectGuiceConfigurator.addExternalGuiceModule(new AbstractModule {
+ * protected void configure() {
+ * bind(Foo.class).to(FooImpl.class).in(Scopes.SINGLETON);
+ * bind(BarImpl.class);
+ * link(Bar.class).to(BarImpl.class);
+ * bindConstant(named("port")).to(8080);
+ * }})
+ *
+ */
+ public synchronized ActiveObjectGuiceConfigurator addExternalGuiceModule(Module module) {
+ modules.add(module);
+ return this;
+ }
+
+ public List getGuiceModules() {
+ return modules;
+ }
+
+ public synchronized void reset() {
+ modules = new ArrayList();
+ configRegistry = new HashMap();
+ activeObjectRegistry = new HashMap();
+ injector = null;
+ restartStrategy = null;
+ }
+
+ public synchronized void stop() {
+ // TODO: fix supervisor.stop();
+ }
+}
diff --git a/api-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java b/api-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
new file mode 100755
index 0000000000..0f40e57bbc
--- /dev/null
+++ b/api-java/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.api;
+
+import se.scalablesolutions.akka.annotation.oneway;
+import se.scalablesolutions.akka.kernel.configuration.*;
+
+import com.google.inject.Inject;
+import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
+
+import junit.framework.TestCase;
+
+public class ActiveObjectGuiceConfiguratorTest extends TestCase {
+ static String messageLog = "";
+
+ final private ActiveObjectGuiceConfigurator conf = new ActiveObjectGuiceConfigurator();
+
+ protected void setUp() {
+ conf.addExternalGuiceModule(new AbstractModule() {
+ protected void configure() {
+ bind(Ext.class).to(ExtImpl.class).in(Scopes.SINGLETON);
+ }
+ }).configureActiveObjects(
+ new RestartStrategy(new AllForOne(), 3, 100), new Component[]{
+ new Component(
+ Foo.class,
+ FooImpl.class,
+ new LifeCycle(new Permanent(), 100),
+ 1000),
+ new Component(
+ Bar.class,
+ BarImpl.class,
+ new LifeCycle(new Permanent(), 100),
+ 1000)
+ }).inject().supervise();
+
+ }
+
+ public void testGuiceActiveObjectInjection() {
+ messageLog = "";
+ Foo foo = conf.getActiveObject(Foo.class);
+ Bar bar = conf.getActiveObject(Bar.class);
+ assertTrue(foo.getBar().toString().equals(bar.toString()));
+ }
+
+ public void testGuiceExternalDependencyInjection() {
+ messageLog = "";
+ Bar bar = conf.getActiveObject(Bar.class);
+ Ext ext = conf.getExternalDependency(Ext.class);
+ assertTrue(bar.getExt().toString().equals(ext.toString()));
+ }
+
+ public void testActiveObjectInvocation() throws InterruptedException {
+ messageLog = "";
+ Foo foo = conf.getActiveObject(Foo.class);
+ messageLog += foo.foo("foo ");
+ foo.bar("bar ");
+ messageLog += "before_bar ";
+ Thread.sleep(500);
+ assertEquals("foo return_foo before_bar ", messageLog);
+ }
+
+ public void testActiveObjectInvocationsInvocation() throws InterruptedException {
+ messageLog = "";
+ Foo foo = conf.getActiveObject(Foo.class);
+ Bar bar = conf.getActiveObject(Bar.class);
+ messageLog += foo.foo("foo ");
+ foo.bar("bar ");
+ messageLog += "before_bar ";
+ Thread.sleep(500);
+ assertEquals("foo return_foo before_bar ", messageLog);
+ }
+
+ public void testForcedTimeout() {
+ messageLog = "";
+ Foo foo = conf.getActiveObject(Foo.class);
+ try {
+ foo.longRunning();
+ fail("exception should have been thrown");
+ } catch (se.scalablesolutions.akka.kernel.ActiveObjectInvocationTimeoutException e) {
+ }
+ }
+
+ public void testForcedException() {
+ messageLog = "";
+ Foo foo = conf.getActiveObject(Foo.class);
+ try {
+ foo.throwsException();
+ fail("exception should have been thrown");
+ } catch (RuntimeException e) {
+ }
+ }
+}
+
+// ============== TEST SERVICES ===============
+
+interface Foo {
+ public String foo(String msg);
+
+ @oneway
+ public void bar(String msg);
+
+ public void longRunning();
+
+ public void throwsException();
+
+ public Bar getBar();
+}
+
+class FooImpl implements Foo {
+ @Inject
+ private Bar bar;
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public String foo(String msg) {
+ return msg + "return_foo ";
+ }
+
+ public void bar(String msg) {
+ bar.bar(msg);
+ }
+
+ public void longRunning() {
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ public void throwsException() {
+ throw new RuntimeException("expected");
+ }
+}
+
+interface Bar {
+ @oneway
+ void bar(String msg);
+
+ Ext getExt();
+}
+
+class BarImpl implements Bar {
+ @Inject
+ private Ext ext;
+
+ public Ext getExt() {
+ return ext;
+ }
+
+ public void bar(String msg) {
+ }
+}
+
+interface Ext {
+ void ext();
+}
+
+class ExtImpl implements Ext {
+ public void ext() {
+ }
+}
+
+
diff --git a/util-java/src/main/java/se/scalablesolutions/akka/annotation/oneway.java b/util-java/src/main/java/se/scalablesolutions/akka/annotation/oneway.java
new file mode 100644
index 0000000000..7a0c7261f0
--- /dev/null
+++ b/util-java/src/main/java/se/scalablesolutions/akka/annotation/oneway.java
@@ -0,0 +1,11 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.annotation;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface oneway {}