fixed final issues with AW proxy integration and remaining tests

This commit is contained in:
Jonas Boner 2009-05-23 22:24:02 +02:00
parent e0591005ed
commit bbec315eb2
29 changed files with 933 additions and 866 deletions

862
akka.iws

File diff suppressed because it is too large Load diff

View file

@ -56,5 +56,6 @@
<classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/commons-collections-3.2.1.jar"/> <classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/commons-collections-3.2.1.jar"/>
<classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/commons-lang-2.4.jar"/> <classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/commons-lang-2.4.jar"/>
<classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/high-scale-lib.jar"/> <classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/high-scale-lib.jar"/>
<classpathentry kind="lib" path="/Users/jboner/src/scala/akka/lib/jersey-client-1.1.0-ea.jar"/>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View file

@ -24,31 +24,37 @@
<groupId>com.sun.grizzly</groupId> <groupId>com.sun.grizzly</groupId>
<artifactId>grizzly-servlet-webserver</artifactId> <artifactId>grizzly-servlet-webserver</artifactId>
<version>1.9.9</version> <version>1.9.9</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId> <artifactId>jersey-server</artifactId>
<version>1.0.3</version> <version>1.0.3</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId> <artifactId>jersey-json</artifactId>
<version>1.0.3</version> <version>1.0.3</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId> <artifactId>jersey-client</artifactId>
<version>1.1.0-ea</version> <version>1.1.0-ea</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.jersey</groupId> <groupId>com.sun.jersey</groupId>
<artifactId>jersey-atom</artifactId> <artifactId>jersey-atom</artifactId>
<version>1.0.3</version> <version>1.0.3</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.5</version> <version>4.5</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jmock</groupId> <groupId>org.jmock</groupId>

View file

@ -32,17 +32,14 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
}).configureActiveObjects( }).configureActiveObjects(
new RestartStrategy(new AllForOne(), 3, 5000), new Component[]{ new RestartStrategy(new AllForOne(), 3, 5000), new Component[]{
new Component( new Component(
"foo",
Foo.class, Foo.class,
FooImpl.class,
new LifeCycle(new Permanent(), 1000), new LifeCycle(new Permanent(), 1000),
1000), 10000),
new Component( new Component(
"bar",
Bar.class, Bar.class,
BarImpl.class, BarImpl.class,
new LifeCycle(new Permanent(), 1000), new LifeCycle(new Permanent(), 1000),
1000) 10000)
}).inject().supervise(); }).inject().supervise();
} }
@ -51,7 +48,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
messageLog = ""; messageLog = "";
Foo foo = conf.getActiveObject(Foo.class); Foo foo = conf.getActiveObject(Foo.class);
Bar bar = conf.getActiveObject(Bar.class); Bar bar = conf.getActiveObject(Bar.class);
assertTrue(foo.getBar().toString().equals(bar.toString())); assertEquals(foo.getBar(), bar);
} }
public void testGuiceExternalDependencyInjection() { public void testGuiceExternalDependencyInjection() {
@ -66,7 +63,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
String str = conf.getActiveObject(String.class); String str = conf.getActiveObject(String.class);
fail("exception should have been thrown"); fail("exception should have been thrown");
} catch (Exception e) { } catch (Exception e) {
assertEquals("Class string has not been put under supervision (by passing in the config to the supervise() method", e.getMessage()); assertEquals("Class [java.lang.String] has not been put under supervision (by passing in the config to the 'configureActiveObjects' and then invoking 'supervise') method", e.getMessage());
} }
} }
@ -113,57 +110,4 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase {
} }
} }
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() {
}
}

View file

@ -0,0 +1,9 @@
package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.annotation.oneway;
public interface Bar {
@oneway
void bar(String msg);
Ext getExt();
}

View file

@ -0,0 +1,13 @@
package se.scalablesolutions.akka.api;
import com.google.inject.Inject;
public class BarImpl implements Bar {
@Inject
private Ext ext;
public Ext getExt() {
return ext;
}
public void bar(String msg) {
}
}

View file

@ -0,0 +1,6 @@
package se.scalablesolutions.akka.api;
public interface Ext {
void ext();
}

View file

@ -0,0 +1,6 @@
package se.scalablesolutions.akka.api;
public class ExtImpl implements Ext {
public void ext() {
}
}

View file

@ -0,0 +1,28 @@
package se.scalablesolutions.akka.api;
import com.google.inject.Inject;
import se.scalablesolutions.akka.annotation.oneway;
public class Foo {
@Inject
private Bar bar;
public Bar getBar() {
return bar;
}
public String foo(String msg) {
return msg + "return_foo ";
}
@oneway
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");
}
}

View file

@ -1,5 +1,7 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
public interface InMemFailer { public class InMemFailer {
public void fail(); public void fail() {
throw new RuntimeException("expected");
}
} }

View file

@ -1,23 +1,68 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.annotation.state;
import se.scalablesolutions.akka.annotation.transactional; import se.scalablesolutions.akka.annotation.transactional;
import se.scalablesolutions.akka.kernel.*;
public interface InMemStateful { public class InMemStateful {
// transactional @state private TransactionalMap<String, String> mapState = new InMemoryTransactionalMap<String, String>();
@transactional @state private TransactionalVector<String> vectorState = new InMemoryTransactionalVector<String>();
public void success(String key, String msg); @state private TransactionalRef<String> refState = new TransactionalRef<String>();
@transactional public String getMapState(String key) {
public void failure(String key, String msg, InMemFailer failer); return (String)mapState.get(key).get();
}
//@transactional
//public void clashOk(String key, String msg, InMemClasher clasher); public String getVectorState() {
return (String)vectorState.last();
//@transactional }
//public void clashNotOk(String key, String msg, InMemClasher clasher);
public String getRefState() {
// non-transactional return (String)refState.get().get();
public String getState(String key); }
public void setState(String key, String value); public void setMapState(String key, String msg) {
mapState.put(key, msg);
}
public void setVectorState(String msg) {
vectorState.add(msg);
}
public void setRefState(String msg) {
refState.swap(msg);
}
@transactional
public void success(String key, String msg) {
mapState.put(key, msg);
vectorState.add(msg);
refState.swap(msg);
}
@transactional
public void failure(String key, String msg, InMemFailer failer) {
mapState.put(key, msg);
vectorState.add(msg);
refState.swap(msg);
failer.fail();
}
@transactional
public void thisMethodHangs(String key, String msg, InMemFailer failer) {
setMapState(key, msg);
}
/*
public void clashOk(String key, String msg, InMemClasher clasher) {
mapState.put(key, msg);
clasher.clash();
}
public void clashNotOk(String key, String msg, InMemClasher clasher) {
mapState.put(key, msg);
clasher.clash();
this.success("clash", "clash");
}
*/
} }

View file

@ -1,40 +0,0 @@
package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.annotation.state;
import se.scalablesolutions.akka.kernel.TransactionalMap;
import se.scalablesolutions.akka.kernel.InMemoryTransactionalMap;
public class InMemStatefulImpl implements InMemStateful {
@state
private TransactionalMap<String, String> state = new InMemoryTransactionalMap<String, String>();
public String getState(String key) {
return state.get(key).get();
}
public void setState(String key, String msg) {
state.put(key, msg);
}
public void success(String key, String msg) {
state.put(key, msg);
}
public void failure(String key, String msg, InMemFailer failer) {
state.put(key, msg);
failer.fail();
}
/*
public void clashOk(String key, String msg, InMemClasher clasher) {
state.put(key, msg);
clasher.clash();
}
public void clashNotOk(String key, String msg, InMemClasher clasher) {
state.put(key, msg);
clasher.clash();
this.success("clash", "clash");
}
*/
}

View file

@ -4,11 +4,8 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.annotation.*;
import se.scalablesolutions.akka.kernel.config.*;
import static se.scalablesolutions.akka.kernel.config.JavaConfig.*; import static se.scalablesolutions.akka.kernel.config.JavaConfig.*;
import se.scalablesolutions.akka.kernel.TransactionalMap; import se.scalablesolutions.akka.kernel.config.*;
import se.scalablesolutions.akka.kernel.InMemoryTransactionalMap;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -22,8 +19,8 @@ public class InMemoryStateTest extends TestCase {
new RestartStrategy(new AllForOne(), 3, 5000), new RestartStrategy(new AllForOne(), 3, 5000),
new Component[] { new Component[] {
// FIXME: remove string-name, add ctor to only accept target class // FIXME: remove string-name, add ctor to only accept target class
new Component("inmem-stateful", InMemStateful.class, InMemStatefulImpl.class, new LifeCycle(new Permanent(), 1000), 10000000), new Component(InMemStateful.class, new LifeCycle(new Permanent(), 1000), 10000000),
new Component("inmem-failer", InMemFailer.class, InMemFailerImpl.class, new LifeCycle(new Permanent(), 1000), 1000) new Component(InMemFailer.class, new LifeCycle(new Permanent(), 1000), 1000)
//new Component("inmem-clasher", InMemClasher.class, InMemClasherImpl.class, new LifeCycle(new Permanent(), 1000), 100000) //new Component("inmem-clasher", InMemClasher.class, InMemClasherImpl.class, new LifeCycle(new Permanent(), 1000), 100000)
}).inject().supervise(); }).inject().supervise();
} }
@ -32,25 +29,58 @@ public class InMemoryStateTest extends TestCase {
conf.stop(); conf.stop();
} }
public void testShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { public void testMapShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
InMemStateful stateful = conf.getActiveObject(InMemStateful.class); InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
stateful.setState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit
assertEquals("new state", stateful.getState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess")); assertEquals("new state", stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess"));
} }
public void testShouldRollbackStateForStatefulServerInCaseOfFailure() { public void testMapShouldRollbackStateForStatefulServerInCaseOfFailure() {
InMemStateful stateful = conf.getActiveObject(InMemStateful.class); InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
stateful.setState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
InMemFailer failer = conf.getActiveObject(InMemFailer.class); InMemFailer failer = conf.getActiveObject(InMemFailer.class);
try { try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception"); fail("should have thrown an exception");
} catch (RuntimeException e) { } catch (RuntimeException e) {
} // expected } // expected
assertEquals("init", stateful.getState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state assertEquals("init", stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
} }
public void testVectorShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
stateful.setVectorState("init"); // set init state
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit
assertEquals("new state", stateful.getVectorState());
}
public void testVectorShouldRollbackStateForStatefulServerInCaseOfFailure() {
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
stateful.setVectorState("init"); // set init state
InMemFailer failer = conf.getActiveObject(InMemFailer.class);
try {
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception");
} catch (RuntimeException e) {
} // expected
assertEquals("init", stateful.getVectorState()); // check that state is == init state
}
public void testNestedNonTransactionalMethodHangs() {
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
InMemFailer failer = conf.getActiveObject(InMemFailer.class);
try {
stateful.thisMethodHangs("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
fail("should have thrown an exception");
} catch (RuntimeException e) {
} // expected
assertEquals("init", stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
}
/* /*
*/ */
// public void testShouldRollbackStateForStatefulServerInCaseOfMessageClash() // public void testShouldRollbackStateForStatefulServerInCaseOfMessageClash()

View file

@ -5,8 +5,10 @@ import javax.ws.rs.GET;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@Path("/foo") @Path("/foo")
public interface JerseyFoo { public class JerseyFoo {
@GET @GET
@Produces({"application/json"}) @Produces({"application/json"})
public String foo(); public String foo() {
return "hello foo";
}
} }

View file

@ -1,14 +0,0 @@
package se.scalablesolutions.akka.api;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
//@Path("/foo")
public class JerseyFooImpl implements JerseyFoo {
//@GET
//@Produces({"application/json"})
public String foo() {
return "hello foo";
}
}

View file

@ -0,0 +1,29 @@
package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.kernel.TransactionalMap;
import se.scalablesolutions.akka.kernel.CassandraPersistentTransactionalMap;
public class PersistentClasher {
private TransactionalMap state = new CassandraPersistentTransactionalMap(this);
public String getState(String key) {
return (String)state.get(key).get();
}
public void setState(String key, String msg) {
state.put(key, msg);
}
public void clash() {
state.put("clasher", "was here");
// spend some time here
// FIXME: this statement gives me this error:
// se.scalablesolutions.akka.kernel.ActiveObjectException:
// Unexpected message [!(scala.actors.Channel@c2b2f6,ErrRef[Right(null)])]
// to
// [GenericServer[se.scalablesolutions.akka.api.StatefulImpl]] from
// [GenericServer[se.scalablesolutions.akka.api.ClasherImpl]]]
// try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
}

View file

@ -1,6 +1,6 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
public class InMemFailerImpl implements InMemFailer { public class PersistentFailer {
public void fail() { public void fail() {
throw new RuntimeException("expected"); throw new RuntimeException("expected");
} }

View file

@ -6,11 +6,6 @@ package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.annotation.*; import se.scalablesolutions.akka.annotation.*;
import se.scalablesolutions.akka.kernel.config.*; import se.scalablesolutions.akka.kernel.config.*;
import se.scalablesolutions.akka.kernel.config.JavaConfig.AllForOne;
import se.scalablesolutions.akka.kernel.config.JavaConfig.Component;
import se.scalablesolutions.akka.kernel.config.JavaConfig.LifeCycle;
import se.scalablesolutions.akka.kernel.config.JavaConfig.Permanent;
import se.scalablesolutions.akka.kernel.config.JavaConfig.RestartStrategy;
import static se.scalablesolutions.akka.kernel.config.JavaConfig.*; import static se.scalablesolutions.akka.kernel.config.JavaConfig.*;
import se.scalablesolutions.akka.kernel.Kernel; import se.scalablesolutions.akka.kernel.Kernel;
import se.scalablesolutions.akka.kernel.TransactionalMap; import se.scalablesolutions.akka.kernel.TransactionalMap;
@ -29,11 +24,11 @@ public class PersistentStateTest extends TestCase {
protected void setUp() { protected void setUp() {
conf.configureActiveObjects( conf.configureActiveObjects(
new JavaConfig.RestartStrategy(new JavaConfig.AllForOne(), 3, 5000), new RestartStrategy(new AllForOne(), 3, 5000),
new Component[] { new Component[] {
new Component("persistent-stateful", PersistentStateful.class, PersistentStatefulImpl.class, new LifeCycle(new Permanent(), 1000), 10000000), new Component(PersistentStateful.class, new LifeCycle(new Permanent(), 1000), 10000000),
new Component("persistent-failer", PersistentFailer.class, PersistentFailerImpl.class, new LifeCycle(new Permanent(), 1000), 1000), new Component(PersistentFailer.class, new LifeCycle(new Permanent(), 1000), 1000),
new Component("persistent-clasher", PersistentClasher.class, PersistentClasherImpl.class, new LifeCycle(new Permanent(), 1000), 100000) new Component(PersistentClasher.class, new LifeCycle(new Permanent(), 1000), 100000)
}).supervise(); }).supervise();
} }
@ -61,96 +56,3 @@ public class PersistentStateTest extends TestCase {
assertEquals("init", stateful.getState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state assertEquals("init", stateful.getState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
} }
} }
interface PersistentStateful {
@transactional
public void success(String key, String msg);
@transactional
public void failure(String key, String msg, PersistentFailer failer);
@transactional
public void clashOk(String key, String msg, PersistentClasher clasher);
@transactional
public void clashNotOk(String key, String msg, PersistentClasher clasher);
public String getState(String key);
public void setState(String key, String value);
}
class PersistentStatefulImpl implements PersistentStateful {
private TransactionalMap state = new CassandraPersistentTransactionalMap(this);
public String getState(String key) {
return (String)state.get(key).get();
}
public void setState(String key, String msg) {
state.put(key, msg);
}
public void success(String key, String msg) {
state.put(key, msg);
}
public void failure(String key, String msg, PersistentFailer failer) {
state.put(key, msg);
failer.fail();
}
public void clashOk(String key, String msg, PersistentClasher clasher) {
state.put(key, msg);
clasher.clash();
}
public void clashNotOk(String key, String msg, PersistentClasher clasher) {
state.put(key, msg);
clasher.clash();
clasher.clash();
}
}
interface PersistentFailer {
public void fail();
}
class PersistentFailerImpl implements PersistentFailer {
public void fail() {
throw new RuntimeException("expected");
}
}
interface PersistentClasher {
public void clash();
public String getState(String key);
public void setState(String key, String value);
}
class PersistentClasherImpl implements PersistentClasher {
private TransactionalMap state = new CassandraPersistentTransactionalMap(this);
public String getState(String key) {
return (String)state.get(key).get();
}
public void setState(String key, String msg) {
state.put(key, msg);
}
public void clash() {
state.put("clasher", "was here");
// spend some time here
// FIXME: this statement gives me this error:
// se.scalablesolutions.akka.kernel.ActiveObjectException:
// Unexpected message [!(scala.actors.Channel@c2b2f6,ErrRef[Right(null)])]
// to
// [GenericServer[se.scalablesolutions.akka.api.StatefulImpl]] from
// [GenericServer[se.scalablesolutions.akka.api.ClasherImpl]]]
// try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
}

View file

@ -0,0 +1,42 @@
package se.scalablesolutions.akka.api;
import se.scalablesolutions.akka.kernel.TransactionalMap;
import se.scalablesolutions.akka.kernel.CassandraPersistentTransactionalMap;
import se.scalablesolutions.akka.annotation.transactional;
public class PersistentStateful {
private TransactionalMap state = new CassandraPersistentTransactionalMap(this);
public String getState(String key) {
return (String)state.get(key).get();
}
public void setState(String key, String msg) {
state.put(key, msg);
}
@transactional
public void success(String key, String msg) {
state.put(key, msg);
}
@transactional
public void failure(String key, String msg, PersistentFailer failer) {
state.put(key, msg);
failer.fail();
}
@transactional
public void clashOk(String key, String msg, PersistentClasher clasher) {
state.put(key, msg);
clasher.clash();
}
@transactional
public void clashNotOk(String key, String msg, PersistentClasher clasher) {
state.put(key, msg);
clasher.clash();
clasher.clash();
}
}

View file

@ -4,7 +4,6 @@
package se.scalablesolutions.akka.api; package se.scalablesolutions.akka.api;
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;
import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource; import com.sun.jersey.api.client.WebResource;
import com.sun.grizzly.http.SelectorThread; import com.sun.grizzly.http.SelectorThread;
@ -18,7 +17,6 @@ import javax.servlet.Servlet;
import org.junit.*; import org.junit.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.util.Map;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -39,9 +37,7 @@ public class RestTest extends TestSuite {
new JavaConfig.RestartStrategy(new JavaConfig.AllForOne(), 3, 5000), new JavaConfig.RestartStrategy(new JavaConfig.AllForOne(), 3, 5000),
new JavaConfig.Component[] { new JavaConfig.Component[] {
new JavaConfig.Component( new JavaConfig.Component(
"jersey-foo",
JerseyFoo.class, JerseyFoo.class,
JerseyFooImpl.class,
new JavaConfig.LifeCycle(new JavaConfig.Permanent(), 1000), 10000000) new JavaConfig.LifeCycle(new JavaConfig.Permanent(), 1000), 10000000)
}).inject().supervise(); }).inject().supervise();
selector = startJersey(); selector = startJersey();

View file

@ -10,10 +10,11 @@ import config.ScalaConfig._
import java.util.{List => JList, ArrayList} import java.util.{List => JList, ArrayList}
import java.lang.reflect.{Method, Field} import java.lang.reflect.{Method, Field}
import java.lang.annotation.Annotation
import org.codehaus.aspectwerkz.intercept.{Advisable, AroundAdvice} import org.codehaus.aspectwerkz.intercept.{Advisable, AroundAdvice}
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
import java.lang.annotation.Annotation
import org.apache.camel.{Processor, Exchange} import org.apache.camel.{Processor, Exchange}
@ -42,8 +43,8 @@ class ActiveObjectFactory {
ActiveObject.newInstance(intf, target, server) ActiveObject.newInstance(intf, target, server)
} }
def supervise(restartStrategy: RestartStrategy, components: JList[Worker]): Supervisor = def supervise(restartStrategy: RestartStrategy, components: List[Worker]): Supervisor =
ActiveObject.supervise(restartStrategy, components.toArray.toList.asInstanceOf[List[Worker]]) ActiveObject.supervise(restartStrategy, components)
} }
/** /**
@ -61,13 +62,13 @@ object ActiveObject {
def newInstance[T](target: Class[T], server: GenericServerContainer): T = { def newInstance[T](target: Class[T], server: GenericServerContainer): T = {
val proxy = Proxy.newInstance(target, false, true) val proxy = Proxy.newInstance(target, false, true)
// FIXME switch to weaving in the aspect at compile time // FIXME switch to weaving in the aspect at compile time
proxy.asInstanceOf[Advisable].aw_addAdvice("execution(* *.*(..))", new ActorAroundAdvice(target, proxy, server)) proxy.asInstanceOf[Advisable].aw_addAdvice("execution(* *.*(..))", new TransactionalAroundAdvice(target, proxy, server))
proxy.asInstanceOf[T] proxy.asInstanceOf[T]
} }
def newInstance[T](intf: Class[T], target: AnyRef, server: GenericServerContainer): T = { def newInstance[T](intf: Class[T], target: AnyRef, server: GenericServerContainer): T = {
val proxy = Proxy.newInstance(Array(intf), Array(target), false, true) val proxy = Proxy.newInstance(Array(intf), Array(target), false, true)
proxy.asInstanceOf[Advisable].aw_addAdvice("execution(* *.*(..))", new ActorAroundAdvice(intf, target, server)) proxy.asInstanceOf[Advisable].aw_addAdvice("execution(* *.*(..))", new TransactionalAroundAdvice(intf, target, server))
proxy.asInstanceOf[T] proxy.asInstanceOf[T]
} }
@ -79,16 +80,6 @@ object ActiveObject {
supervisor ! se.scalablesolutions.akka.kernel.Start supervisor ! se.scalablesolutions.akka.kernel.Start
supervisor supervisor
} }
/*
private def supervise(proxy: AnyRef): Supervisor =
supervise(
RestartStrategy(OneForOne, 5, 1000),
Worker(
proxy.server,
LifeCycle(Permanent, 100))
:: Nil)
*/
} }
/** /**
@ -96,9 +87,9 @@ object ActiveObject {
*/ */
// FIXME: STM that allows concurrent updates, detects collision, rolls back and restarts // FIXME: STM that allows concurrent updates, detects collision, rolls back and restarts
sealed class ActorAroundAdvice(target: Class[_], sealed class TransactionalAroundAdvice(target: Class[_],
targetInstance: AnyRef, targetInstance: AnyRef,
val server: GenericServerContainer) extends AroundAdvice { server: GenericServerContainer) extends AroundAdvice {
val (maps, vectors, refs) = getTransactionalItemsFor(targetInstance) val (maps, vectors, refs) = getTransactionalItemsFor(targetInstance)
server.transactionalRefs = refs server.transactionalRefs = refs
server.transactionalMaps = maps server.transactionalMaps = maps
@ -109,17 +100,14 @@ sealed class ActorAroundAdvice(target: Class[_],
def invoke(joinpoint: JoinPoint): AnyRef = { def invoke(joinpoint: JoinPoint): AnyRef = {
// FIXME: switch to using PCD annotation matching, break out into its own aspect + switch to StaticJoinPoint // FIXME: switch to using PCD annotation matching, break out into its own aspect + switch to StaticJoinPoint
val method = joinpoint.getRtti.asInstanceOf[MethodRtti].getMethod val rtti = joinpoint.getRtti.asInstanceOf[MethodRtti]
val method = rtti.getMethod
if (method.isAnnotationPresent(Annotations.transactional)) { if (method.isAnnotationPresent(Annotations.transactional)) {
if (activeTx.isDefined) { if (activeTx.isDefined) {
val tx = activeTx.get val tx = activeTx.get
//val cflowTx = threadBoundTx.get
// if (cflowTx.isDefined && cflowTx.get != tx) {
// new tx in scope; try to commit
tx.commit(server) tx.commit(server)
threadBoundTx.set(None) threadBoundTx.set(None)
activeTx = None activeTx = None
// }
} }
// FIXME: check if we are already in a transaction if so NEST (set parent) // FIXME: check if we are already in a transaction if so NEST (set parent)
val newTx = new Transaction val newTx = new Transaction
@ -134,37 +122,14 @@ sealed class ActorAroundAdvice(target: Class[_],
activeTx = Some(currentTx) activeTx = Some(currentTx)
} }
activeTx = threadBoundTx.get activeTx = threadBoundTx.get
invoke(joinpoint, activeTx)
//invoke(Invocation(method, joinpoint.getRtti.asInstanceOf[MethodRtti].getParameterValues, targetInstance, activeTx))
}
private def invoke(joinpoint: JoinPoint, tx: Option[Transaction]): AnyRef = {
val result: AnyRef =
/*
if (joinpoint.target.isInstanceOf[MessageDriven] &&
joinpoint.method.getName == "onMessage") {
val m = joinpoint.method
val endpointName = m.getDeclaringClass.getName + "." + m.getName
val activeObjectName = m.getDeclaringClass.getName
val endpoint = conf.getRoutingEndpoint(conf.lookupUriFor(m))
val producer = endpoint.createProducer
val exchange = endpoint.createExchange
exchange.getIn().setBody(joinpoint)
producer.process(exchange)
val fault = exchange.getException();
if (fault != null) throw new InvocationTargetException(fault)
// FIXME: need some timeout and future here...
exchange.getOut.getBody
} else */
// FIXME: switch to using PCD annotation matching, break out into its own aspect + switch to StaticJoinPoint // FIXME: switch to using PCD annotation matching, break out into its own aspect + switch to StaticJoinPoint
if (joinpoint.getRtti.asInstanceOf[MethodRtti].getMethod.isAnnotationPresent(Annotations.oneway)) { val result: AnyRef =
server ! (tx, joinpoint) if (rtti.getMethod.isAnnotationPresent(Annotations.oneway)) {
server ! (activeTx, joinpoint)
} else { } else {
val result: ErrRef[AnyRef] = val result: ErrRef[AnyRef] =
server !!! ((tx, joinpoint), { server !!! ((activeTx, joinpoint), {
var ref = ErrRef(activeTx) var ref = ErrRef(activeTx)
ref() = throw new ActiveObjectInvocationTimeoutException("Invocation to active object [" + targetInstance.getClass.getName + "] timed out after " + server.timeout + " milliseconds") ref() = throw new ActiveObjectInvocationTimeoutException("Invocation to active object [" + targetInstance.getClass.getName + "] timed out after " + server.timeout + " milliseconds")
ref ref
@ -173,7 +138,6 @@ sealed class ActorAroundAdvice(target: Class[_],
result() result()
} catch { } catch {
case e => case e =>
println("$$$$$$$$$$$$$$ " + joinpoint)
rollback(result.tx) rollback(result.tx)
throw e throw e
} }
@ -190,14 +154,20 @@ sealed class ActorAroundAdvice(target: Class[_],
threadBoundTx.set(Some(tx)) threadBoundTx.set(Some(tx))
} }
/**
* Search for transactional items for a specific target instance, crawl the class hierarchy recursively up to the top.
*/
private def getTransactionalItemsFor(targetInstance: AnyRef): private def getTransactionalItemsFor(targetInstance: AnyRef):
Tuple3[List[TransactionalMap[_, _]], List[TransactionalVector[_]], List[TransactionalRef[_]]] = { Tuple3[List[TransactionalMap[_, _]], List[TransactionalVector[_]], List[TransactionalRef[_]]] = {
require(targetInstance != null) require(targetInstance != null)
var maps: List[TransactionalMap[_, _]] = Nil var maps: List[TransactionalMap[_, _]] = Nil
var vectors: List[TransactionalVector[_]] = Nil
var refs: List[TransactionalRef[_]] = Nil var refs: List[TransactionalRef[_]] = Nil
var vectors: List[TransactionalVector[_]] = Nil
def getTransactionalItemsFor(target: Class[_]):
Tuple3[List[TransactionalMap[_, _]], List[TransactionalVector[_]], List[TransactionalRef[_]]] = {
for { for {
field <- targetInstance.getClass.getDeclaredFields.toArray.toList.asInstanceOf[List[Field]] field <- target.getDeclaredFields.toArray.toList.asInstanceOf[List[Field]]
fieldType = field.getType fieldType = field.getType
if fieldType == classOf[TransactionalMap[_, _]] || if fieldType == classOf[TransactionalMap[_, _]] ||
fieldType == classOf[TransactionalVector[_]] || fieldType == classOf[TransactionalVector[_]] ||
@ -212,7 +182,13 @@ sealed class ActorAroundAdvice(target: Class[_],
else if (txItem.isInstanceOf[TransactionalRef[_]]) refs ::= txItem.asInstanceOf[TransactionalRef[_]] else if (txItem.isInstanceOf[TransactionalRef[_]]) refs ::= txItem.asInstanceOf[TransactionalRef[_]]
else if (txItem.isInstanceOf[TransactionalVector[_]]) vectors ::= txItem.asInstanceOf[TransactionalVector[_]] else if (txItem.isInstanceOf[TransactionalVector[_]]) vectors ::= txItem.asInstanceOf[TransactionalVector[_]]
} }
(maps, vectors, refs) val parent = target.getSuperclass
if (parent == null) (maps, vectors, refs)
else getTransactionalItemsFor(parent)
}
// start the search for transactional items, crawl the class hierarchy up until we reach 'null'
getTransactionalItemsFor(targetInstance.getClass)
} }
} }
@ -248,56 +224,6 @@ private[kernel] class Dispatcher(val targetName: String) extends GenericServer {
override def toString(): String = "GenericServer[" + targetName + "]" override def toString(): String = "GenericServer[" + targetName + "]"
} }
/**
* Represents a snapshot of the current invocation.
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
private[kernel] case class Invocation(val method: Method,
val args: Array[AnyRef],
val target: AnyRef,
val tx: Option[Transaction]) {
method.setAccessible(true)
def invoke: AnyRef = synchronized {
println("======== " + this.toString)
if (method.getDeclaringClass.isInterface) {
target.getClass.getDeclaredMethod(method.getName, method.getParameterTypes).invoke(target, args:_*)
} else method.invoke(target, args:_*)
}
override def toString: String = synchronized {
"Invocation [method: " + method.getName + ", args: " + argsToString(args) + ", target: " + target + "]"
}
override def hashCode(): Int = synchronized {
var result = HashCode.SEED
result = HashCode.hash(result, method)
result = HashCode.hash(result, args)
result = HashCode.hash(result, target)
result
}
override def equals(that: Any): Boolean = synchronized {
that != null &&
that.isInstanceOf[Invocation] &&
that.asInstanceOf[Invocation].method == method &&
that.asInstanceOf[Invocation].target == target &&
isEqual(that.asInstanceOf[Invocation].args, args)
}
private[this] def isEqual(a1: Array[Object], a2: Array[Object]): Boolean =
(a1 == null && a2 == null) ||
(a1 != null &&
a2 != null &&
a1.size == a2.size &&
a1.zip(a2).find(t => t._1 == t._2).isDefined)
private[this] def argsToString(array: Array[Object]): String =
array.foldLeft("(")(_ + " " + _) + ")"
}
/* /*
ublic class CamelInvocationHandler implements InvocationHandler { ublic class CamelInvocationHandler implements InvocationHandler {
private final Endpoint endpoint; private final Endpoint endpoint;
@ -332,4 +258,24 @@ ublic class CamelInvocationHandler implements InvocationHandler {
} }
} }
} }
if (joinpoint.target.isInstanceOf[MessageDriven] &&
joinpoint.method.getName == "onMessage") {
val m = joinpoint.method
val endpointName = m.getDeclaringClass.getName + "." + m.getName
val activeObjectName = m.getDeclaringClass.getName
val endpoint = conf.getRoutingEndpoint(conf.lookupUriFor(m))
val producer = endpoint.createProducer
val exchange = endpoint.createExchange
exchange.getIn().setBody(joinpoint)
producer.process(exchange)
val fault = exchange.getException();
if (fault != null) throw new InvocationTargetException(fault)
// FIXME: need some timeout and future here...
exchange.getOut.getBody
} else
*/ */

View file

@ -23,6 +23,7 @@ case class HotSwap(code: Option[PartialFunction[Any, Unit]]) extends GenericServ
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a> * @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/ */
trait GenericServer extends Actor { trait GenericServer extends Actor {
private val actorScheduler = new ManagedActorScheduler
/** /**
* Template method implementing the server logic. * Template method implementing the server logic.
@ -62,6 +63,8 @@ trait GenericServer extends Actor {
def act = loop { react { genericBase orElse actorBase } } def act = loop { react { genericBase orElse actorBase } }
//override protected def scheduler = actorScheduler
private def actorBase: PartialFunction[Any, Unit] = hotswap getOrElse body private def actorBase: PartialFunction[Any, Unit] = hotswap getOrElse body
private var hotswap: Option[PartialFunction[Any, Unit]] = None private var hotswap: Option[PartialFunction[Any, Unit]] = None
@ -226,6 +229,7 @@ class GenericServerContainer(
*/ */
def !!![T](message: Any, errorHandler: => T, time: Int): T = { def !!![T](message: Any, errorHandler: => T, time: Int): T = {
require(server != null) require(server != null)
println("---------- SERVER " + server + " MESSAGE " + message)
val future: FutureWithTimeout[T] = lock.withReadLock { server !!! message } val future: FutureWithTimeout[T] = lock.withReadLock { server !!! message }
future.receiveWithin(time) match { future.receiveWithin(time) match {
case None => errorHandler case None => errorHandler

View file

@ -12,7 +12,43 @@ import scala.actors.{FJTaskScheduler2, Scheduler, IScheduler, Actor}
// FIXME: add managing interface to this class using JMX // FIXME: add managing interface to this class using JMX
// FIXME: configure one instance per GenericServer // FIXME: configure one instance per GenericServer
object ManagedActorScheduler extends Logging {
class ManagedActorScheduler extends IScheduler with Logging {
protected var threadPoolSize = 10
protected val threadPool = Executors.newFixedThreadPool(threadPoolSize)
def execute(fun: => Unit): Unit = threadPool.execute(new Runnable {
def run = {
try {
fun
} catch {
case e => log.error("Actor scheduler", e)
}
}
})
def execute(task: Runnable) = threadPool.execute(new Runnable {
def run = {
try {
task.run
} catch {
case e => log.error("Actor scheduler", e)
}
}
})
def tick(a: Actor): Unit = {}
def shutdown: Unit = threadPool.shutdown
def onLockup(handler: () => Unit): Unit = {}
def onLockup(millis: Int)(handler: () => Unit): Unit = {}
def printActorDump: Unit = {}
}
object GlobalManagedActorScheduler extends Logging {
@volatile private var isRegistered = false @volatile private var isRegistered = false
private var threadPoolSize = 10 private var threadPoolSize = 10
@ -24,38 +60,8 @@ object ManagedActorScheduler extends Logging {
fj.shutdown fj.shutdown
case _ => case _ =>
} }
Scheduler.impl = new ManagedActorScheduler
Scheduler.impl = {
val threadPool = Executors.newFixedThreadPool(threadPoolSize)
new IScheduler {
def execute(fun: => Unit): Unit = threadPool.execute(new Runnable {
def run = {
try {
fun
} catch {
case e => log.error("Actor scheduler", e)
}
}
})
def execute(task: Runnable) = es.execute(new Runnable {
def run = {
try {
task.run
} catch {
case e => log.error("Actor scheduler", e)
}
}
})
def tick(a: Actor): Unit = {}
def shutdown: Unit = { threadPool.shutdown }
def onLockup(handler: () => Unit): Unit = {}
def onLockup(millis: Int)(handler: () => Unit): Unit = {}
def printActorDump: Unit = {}
}
}
}
isRegistered = true isRegistered = true
} }
} }
}

View file

@ -29,9 +29,10 @@ class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelC
private var supervisor: Supervisor = _ private var supervisor: Supervisor = _
private var restartStrategy: RestartStrategy = _ private var restartStrategy: RestartStrategy = _
private var components: List[Component] = _ private var components: List[Component] = _
private var workers: List[Worker] = Nil
private var bindings: List[DependencyBinding] = Nil private var bindings: List[DependencyBinding] = Nil
private var configRegistry = new HashMap[Class[_], Component] // TODO is configRegistry needed? private var configRegistry = new HashMap[Class[_], Component] // TODO is configRegistry needed?
private var activeObjectRegistry = new HashMap[Class[_], Tuple2[Component, GenericServerContainer]] private var activeObjectRegistry = new HashMap[Class[_], Tuple4[AnyRef, AnyRef, Component, GenericServerContainer]]
private var activeObjectFactory = new ActiveObjectFactory private var activeObjectFactory = new ActiveObjectFactory
private var camelContext = new DefaultCamelContext private var camelContext = new DefaultCamelContext
private var modules = new java.util.ArrayList[Module] private var modules = new java.util.ArrayList[Module]
@ -44,23 +45,14 @@ class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelC
* @return the active object for the class * @return the active object for the class
*/ */
override def getActiveObject[T](clazz: Class[T]): T = synchronized { override def getActiveObject[T](clazz: Class[T]): T = synchronized {
log.debug("Creating new active object [%s]", clazz.getName) log.debug("Retrieving active object [%s]", clazz.getName)
if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getActiveObject(clazz)") if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getActiveObject(clazz)")
val activeObjectOption: Option[Tuple2[Component, GenericServerContainer]] = activeObjectRegistry.get(clazz) val (proxy, targetInstance, component, server) =
if (activeObjectOption.isDefined) { activeObjectRegistry.getOrElse(clazz, throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'configureActiveObjects' and then invoking 'supervise') method"))
val (component, server) = activeObjectOption.get injector.injectMembers(targetInstance)
server.setTimeout(component.timeout) proxy.asInstanceOf[T]
val proxy = if (component.intf == null) { // subclassing proxy
activeObjectFactory.newInstance(component.target, server).asInstanceOf[T]
} else { // delegating proxy
component.target.getConstructor(Array[Class[_]]()).setAccessible(true)
val targetInstance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry
activeObjectFactory.newInstance(component.intf, targetInstance, server).asInstanceOf[T]
}
injector.injectMembers(proxy)
proxy
} else throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'supervise') method")
} }
/* /*
override def getActiveObjectProxy(clazz: Class[_]): ActiveObjectProxy = synchronized { override def getActiveObjectProxy(clazz: Class[_]): ActiveObjectProxy = synchronized {
log.debug("Looking up active object proxy [%s]", clazz.getName) log.debug("Looking up active object proxy [%s]", clazz.getName)
@ -74,7 +66,11 @@ class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelC
injector.getInstance(clazz).asInstanceOf[T] injector.getInstance(clazz).asInstanceOf[T]
} }
override def getComponentInterfaces: List[Class[_]] = components.map(_.intf) override def getComponentInterfaces: List[Class[_]] =
for (c <- components) yield {
if (c.intf.isDefined) c.intf.get
else c.target
}
override def getRoutingEndpoint(uri: String): Endpoint = synchronized { override def getRoutingEndpoint(uri: String): Endpoint = synchronized {
camelContext.getEndpoint(uri) camelContext.getEndpoint(uri)
@ -88,17 +84,46 @@ class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelC
camelContext.getEndpoints(uri) camelContext.getEndpoints(uri)
} }
override def configureActiveObjects(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectConfigurator = synchronized { override def configureActiveObjects(
restartStrategy: RestartStrategy,
components: List[Component]): ActiveObjectConfigurator = 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 (c <- this.components) bindings = for (component <- this.components) yield {
yield new DependencyBinding(c.intf, c.target) // build up the Guice interface class -> impl class bindings if (component.intf.isDefined) newDelegatingProxy(component)
else newSubclassingProxy(component)
}
//camelContext.getRegistry.asInstanceOf[JndiRegistry].bind(component.name, activeObjectProxy)
//for (method <- component.intf.getDeclaredMethods.toList) registerMethodForUri(method, component.name)
//log.debug("Registering active object in Camel context under the name [%s]", component.target.getName)
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 ActiveObjectGuiceModule(deps))
this this
} }
private def newSubclassingProxy(component: Component): DependencyBinding = {
val targetClass = component.target
val server = new GenericServerContainer(targetClass.getName, () => new Dispatcher(component.target.getName))
server.setTimeout(component.timeout)
workers ::= Worker(server, component.lifeCycle)
val proxy = activeObjectFactory.newInstance(targetClass, server).asInstanceOf[AnyRef]
activeObjectRegistry.put(targetClass, (proxy, proxy, component, server))
new DependencyBinding(targetClass, proxy)
}
private def newDelegatingProxy(component: Component): DependencyBinding = {
val targetClass = component.intf.get
val server = new GenericServerContainer(targetClass.getName, () => new Dispatcher(component.target.getName))
server.setTimeout(component.timeout)
workers ::= Worker(server, component.lifeCycle)
component.target.getConstructor(Array[Class[_]]()).setAccessible(true)
val targetInstance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry
val proxy = activeObjectFactory.newInstance(targetClass, targetInstance, server).asInstanceOf[AnyRef]
activeObjectRegistry.put(targetClass, (proxy, targetInstance, component, server))
new DependencyBinding(targetClass, proxy)
}
override def inject: ActiveObjectConfigurator = synchronized { override def inject: ActiveObjectConfigurator = synchronized {
if (injector != null) throw new IllegalStateException("inject() has already been called on this configurator") if (injector != null) throw new IllegalStateException("inject() has already been called on this configurator")
injector = Guice.createInjector(modules) injector = Guice.createInjector(modules)
@ -107,17 +132,6 @@ class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelC
override def supervise: ActiveObjectConfigurator = synchronized { override def supervise: ActiveObjectConfigurator = synchronized {
if (injector == null) inject if (injector == null) inject
var workers = new java.util.ArrayList[Worker]
for (component <- components) {
val target = if (component.intf != null) component.intf // TODO: use Option
else component.target
val server = new GenericServerContainer(target.getName, () => new Dispatcher(component.target.getName))
activeObjectRegistry.put(target, (component, server))
workers.add(Worker(server, component.lifeCycle))
//camelContext.getRegistry.asInstanceOf[JndiRegistry].bind(component.name, activeObjectProxy)
for (method <- component.intf.getDeclaredMethods.toList) registerMethodForUri(method, component.name)
log.debug("Registering active object in Camel context under the name [%s]", component.target.getName)
}
supervisor = activeObjectFactory.supervise(restartStrategy, workers) supervisor = activeObjectFactory.supervise(restartStrategy, workers)
//camelContext.addComponent(AKKA_CAMEL_ROUTING_SCHEME, new ActiveObjectComponent(this)) //camelContext.addComponent(AKKA_CAMEL_ROUTING_SCHEME, new ActiveObjectComponent(this))
//camelContext.start //camelContext.start
@ -154,7 +168,7 @@ class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelC
def reset = synchronized { def reset = synchronized {
modules = new java.util.ArrayList[Module] modules = new java.util.ArrayList[Module]
configRegistry = new HashMap[Class[_], Component] configRegistry = new HashMap[Class[_], Component]
activeObjectRegistry = new HashMap[Class[_], Tuple2[Component, GenericServerContainer]] activeObjectRegistry = new HashMap[Class[_], Tuple4[AnyRef, AnyRef, Component, GenericServerContainer]]
methodToUriRegistry = new HashMap[Method, String] methodToUriRegistry = new HashMap[Method, String]
injector = null injector = null
restartStrategy = null restartStrategy = null

View file

@ -57,6 +57,7 @@ class ActiveObjectGuiceConfiguratorForJava {
this this
} }
def getComponentInterfaces: List[Class[_]] = { def getComponentInterfaces: List[Class[_]] = {
val al = new ArrayList[Class[_]] val al = new ArrayList[Class[_]]
for (c <- INSTANCE.getComponentInterfaces) al.add(c) for (c <- INSTANCE.getComponentInterfaces) al.add(c)

View file

@ -33,11 +33,18 @@ object ScalaConfig {
case object Transient extends Scope case object Transient extends Scope
case object Temporary extends Scope case object Temporary extends Scope
case class Component(val name: String, class Component(_intf: Class[_],
val intf: Class[_],
val target: Class[_], val target: Class[_],
val lifeCycle: LifeCycle, val lifeCycle: LifeCycle,
val timeout: Int) extends Server val timeout: Int) extends Server {
val intf: Option[Class[_]] = if (_intf == null) None else Some(_intf)
}
object Component {
def apply(intf: Class[_], target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
new Component(intf, target, lifeCycle, timeout)
def apply(target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
new Component(null, target, lifeCycle, timeout)
}
} }
/** /**
@ -81,13 +88,14 @@ object JavaConfig {
} }
abstract class Server extends ConfigElement abstract class Server extends ConfigElement
class Component(@BeanProperty val name: String, class Component(@BeanProperty val intf: Class[_],
@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 this(target: Class[_], lifeCycle: LifeCycle, timeout: Int) =
this(null, target, lifeCycle, timeout)
def transform = se.scalablesolutions.akka.kernel.config.ScalaConfig.Component( def transform = se.scalablesolutions.akka.kernel.config.ScalaConfig.Component(
name, intf, target, lifeCycle.transform, timeout) intf, target, lifeCycle.transform, timeout)
def newWorker(server: GenericServerContainer) = def newWorker(server: GenericServerContainer) =
se.scalablesolutions.akka.kernel.config.ScalaConfig.Worker(server, lifeCycle.transform) se.scalablesolutions.akka.kernel.config.ScalaConfig.Worker(server, lifeCycle.transform)
} }

View file

@ -32,21 +32,20 @@ class JerseySpec extends Spec with ShouldMatchers {
describe("A Jersey REST service") { describe("A Jersey REST service") {
it("should ...") { it("should ...") {
//val selector = startJersey val selector = startJersey
//oselector.start selector.start
/*
val conf = new ActiveObjectGuiceConfigurator val conf = new ActiveObjectGuiceConfigurator
conf.configureActiveObjects( conf.configureActiveObjects(
RestartStrategy(AllForOne, 3, 5000), RestartStrategy(AllForOne, 3, 5000),
Component( Component(
"jerseyfoo",
classOf[resource.JerseyFoo], classOf[resource.JerseyFoo],
classOf[resource.JerseyFooImpl],
LifeCycle(Permanent, 1000), LifeCycle(Permanent, 1000),
1000) :: 1000) ::
Nil).supervise Nil).supervise
conf.getActiveObject(classOf[resource.JerseyFoo]) conf.getActiveObject(classOf[resource.JerseyFoo])
*/
/* /*
val client = Client.create val client = Client.create
@ -79,20 +78,14 @@ class JerseySpec extends Spec with ShouldMatchers {
package resource { package resource {
import javax.ws.rs.{Produces, Path, GET} import javax.ws.rs.{Produces, Path, GET}
trait JerseyFoo { class JerseyFoo {
def foo: String
}
trait JerseyBar {
def bar(msg: String): String
}
@Path("/foo")
class JerseyFooImpl extends JerseyFoo {
@GET @GET
@Produces(Array("application/json")) @Produces(Array("application/json"))
def foo: String = { val ret = "JerseyFoo.foo"; println(ret); ret } def foo: String = { val ret = "JerseyFoo.foo"; println(ret); ret }
} }
class JerseyBarImpl extends JerseyBar { @Path("/foo")
class JerseyFooSub extends JerseyFoo
class JerseyBar {
def bar(msg: String) = msg + "return_bar " def bar(msg: String) = msg + "return_bar "
} }
} }

View file

@ -24,7 +24,9 @@ public class ActiveObjectGuiceModule extends AbstractModule {
bind(ResourceProviderFactory.class); bind(ResourceProviderFactory.class);
for (int i = 0; i < bindings.size(); i++) { for (int i = 0; i < bindings.size(); i++) {
final DependencyBinding db = bindings.get(i); final DependencyBinding db = bindings.get(i);
bind((Class) db.getInterface()).to((Class) db.getTarget()).in(Singleton.class); //if (db.getInterface() != null) bind((Class) db.getInterface()).to((Class) db.getTarget()).in(Singleton.class);
//else
this.bind(db.getInterface()).toInstance(db.getTarget());
} }
} }
} }

View file

@ -9,16 +9,16 @@ package se.scalablesolutions.akka.kernel.config;
*/ */
public class DependencyBinding { public class DependencyBinding {
private final Class intf; private final Class intf;
private final Class target; private final Object target;
public DependencyBinding(final Class intf, final Class target) { public DependencyBinding(final Class intf, final Object target) {
this.intf = intf; this.intf = intf;
this.target = target; this.target = target;
} }
public Class getInterface() { public Class getInterface() {
return intf; return intf;
} }
public Class getTarget() { public Object getTarget() {
return target; return target;
} }
} }