diff --git a/kernel/src/main/scala/AkkaComponentProvider.scala b/kernel/src/main/scala/AkkaComponentProvider.scala
deleted file mode 100644
index 6d778f3934..0000000000
--- a/kernel/src/main/scala/AkkaComponentProvider.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2009 Scalable Solutions.
- */
-
-package se.scalablesolutions.akka.kernel
-
-//import com.sun.ws.rest.spi.service.ComponentProvider;
-import java.lang.reflect.Constructor
-
-class AkkaComponentProvider { //extends ComponentProvider {
-/*
- override def getInstance(scope: Scope, c: Class[_]): AnyRef = {
- null
- }
-
- override def getInstance(scope: Scope, contructor: Constructor[_], parameters: Array[AnyRef]): AnyRef = {
- null
- }
-
- override def inject(instance: AnyRef) = {
- }
-*/
-}
diff --git a/kernel/src/main/scala/camel/ActiveObjectComponent.scala b/kernel/src/main/scala/camel/ActiveObjectComponent.scala
index 2d2315e943..39489156f9 100644
--- a/kernel/src/main/scala/camel/ActiveObjectComponent.scala
+++ b/kernel/src/main/scala/camel/ActiveObjectComponent.scala
@@ -4,7 +4,8 @@
package se.scalablesolutions.akka.kernel.camel
-import config.ActiveObjectGuiceConfigurator
+import config.ActiveObjectConfigurator
+
import java.util.Map
import java.util.concurrent.{BlockingQueue, LinkedBlockingQueue}
@@ -14,7 +15,7 @@ import org.apache.camel.impl.DefaultComponent
/**
* @author Jonas Bonér
*/
-class ActiveObjectComponent(val conf: ActiveObjectGuiceConfigurator) extends DefaultComponent {
+class ActiveObjectComponent(val conf: ActiveObjectConfigurator) extends DefaultComponent {
override def createEndpoint(uri: String, remaining: String, parameters: Map[_,_]): Endpoint = {
//val consumers = getAndRemoveParameter(parameters, "concurrentConsumers", classOf[Int], 1)
new ActiveObjectEndpoint(uri, this, conf)
diff --git a/kernel/src/main/scala/camel/ActiveObjectEndpoint.scala b/kernel/src/main/scala/camel/ActiveObjectEndpoint.scala
index 7946f87753..dfe70efc2e 100644
--- a/kernel/src/main/scala/camel/ActiveObjectEndpoint.scala
+++ b/kernel/src/main/scala/camel/ActiveObjectEndpoint.scala
@@ -4,7 +4,7 @@
package se.scalablesolutions.akka.kernel.camel
-import config.ActiveObjectGuiceConfigurator
+import config.ActiveObjectConfigurator
import se.scalablesolutions.akka.kernel.Logging
import java.util.{ArrayList, HashSet, List, Set}
@@ -17,7 +17,7 @@ import org.apache.camel.spi.BrowsableEndpoint;
/**
* @author Jonas Bonér
*/
-class ActiveObjectEndpoint(val uri: String, val component: DefaultComponent, val conf: ActiveObjectGuiceConfigurator) // FIXME: need abstraction trait here
+class ActiveObjectEndpoint(val uri: String, val component: DefaultComponent, val conf: ActiveObjectConfigurator) // FIXME: need abstraction trait here
extends DefaultEndpoint(uri) with BrowsableEndpoint with Logging {
val firstSep = uri.indexOf(':')
@@ -25,8 +25,9 @@ class ActiveObjectEndpoint(val uri: String, val component: DefaultComponent, val
val scheme = uri.substring(0, firstSep)
val activeObjectName = uri.substring(uri.indexOf(':') + 1, lastSep)
+ val activeObjectClass = Thread.currentThread.getContextClassLoader.loadClass(activeObjectName)
val methodName = uri.substring(lastSep + 1, uri.length)
- val activeObject = conf.getActiveObject(activeObjectName).asInstanceOf[MessageDriven]
+ val activeObject = conf.getActiveObject(activeObjectClass).asInstanceOf[MessageDriven]
// val activeObjectProxy = conf.getActiveObjectProxy(activeObjectName)
// val genericServer = supervisor.getServerOrElse(
diff --git a/kernel/src/main/scala/config/ActiveObjectConfigurator.scala b/kernel/src/main/scala/config/ActiveObjectConfigurator.scala
new file mode 100644
index 0000000000..4455788cd4
--- /dev/null
+++ b/kernel/src/main/scala/config/ActiveObjectConfigurator.scala
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.kernel.config
+
+import config.ScalaConfig.{RestartStrategy, Component}
+import javax.servlet.ServletContext
+
+object ActiveObjectConfigurator extends Logging {
+
+ private var configuration: ActiveObjectConfigurator = _
+
+ // FIXME: cheating with only having one single, scope per ServletContext
+ def registerConfigurator(conf: ActiveObjectConfigurator) = {
+ configuration = conf
+ }
+
+ def getConfiguratorFor(ctx: ServletContext): ActiveObjectConfigurator = {
+ configuration
+ //configurations.getOrElse(ctx, throw new IllegalArgumentException("No configuration for servlet context [" + ctx + "]"))
+ }
+}
+
+trait ActiveObjectConfigurator {
+ /**
+ * Returns the active abject that has been put under supervision for the class specified.
+ *
+ * @param clazz the class for the active object
+ * @return the active object for the class
+ */
+ def getActiveObject(clazz: Class[_]): AnyRef
+ def getActiveObjectProxy(clazz: Class[_]): ActiveObjectProxy
+ def getExternalDependency[T](clazz: Class[T]): T
+ def configureActiveObjects(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectConfigurator
+ def inject: ActiveObjectConfigurator
+ def supervise: ActiveObjectConfigurator
+ def reset
+ def stop
+}
diff --git a/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala b/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala
index 4d9ca0c0e1..c7f4ea5d46 100644
--- a/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala
+++ b/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala
@@ -8,19 +8,23 @@ import com.google.inject._
import com.google.inject.jsr250.ResourceProviderFactory
import java.lang.reflect.Method
-import kernel.camel.ActiveObjectComponent
+import javax.servlet.ServletContext
+
import org.apache.camel.impl.{JndiRegistry, DefaultCamelContext}
import org.apache.camel.{CamelContext, Endpoint, Routes}
+
import scala.collection.mutable.HashMap
-import se.scalablesolutions.akka.kernel.ActiveObjectFactory
-import se.scalablesolutions.akka.kernel.ActiveObjectProxy
-import se.scalablesolutions.akka.kernel.Supervisor
-import se.scalablesolutions.akka.kernel.config.ScalaConfig._
+
+import kernel.camel.ActiveObjectComponent
+import kernel.ActiveObjectFactory
+import kernel.ActiveObjectProxy
+import kernel.Supervisor
+import kernel.config.ScalaConfig._
/**
* @author Jonas Bonér
*/
-class ActiveObjectGuiceConfigurator extends Logging {
+class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurator with CamelConfigurator with Logging {
val AKKA_CAMEL_ROUTING_SCHEME = "akka"
private var injector: Injector = _
@@ -29,7 +33,7 @@ class ActiveObjectGuiceConfigurator extends Logging {
private var components: List[Component] = _
private var bindings: List[DependencyBinding] = Nil
private var configRegistry = new HashMap[Class[_], Component] // TODO is configRegistry needed?
- private var activeObjectRegistry = new HashMap[String, Tuple3[Class[_], Class[_], ActiveObjectProxy]]
+ private var activeObjectRegistry = new HashMap[Class[_], Tuple3[Class[_], Class[_], ActiveObjectProxy]]
private var activeObjectFactory = new ActiveObjectFactory
private var camelContext = new DefaultCamelContext
private var modules = new java.util.ArrayList[Module]
@@ -41,48 +45,48 @@ class ActiveObjectGuiceConfigurator extends Logging {
* @param clazz the class for the active object
* @return the active object for the class
*/
- def getActiveObject(name: String): AnyRef = synchronized {
+ override def getActiveObject(clazz: Class[_]): AnyRef = synchronized {
//def getActiveObject[T](name: String): T = synchronized {
- log.debug("Looking up active object [%s]", name)
- if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking newInstance(clazz)")
- val activeObjectOption: Option[Tuple3[Class[_], Class[_], ActiveObjectProxy]] = activeObjectRegistry.get(name)
+ log.debug("Looking up active object [%s]", clazz.getName)
+ if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getActiveObject(clazz)")
+ val activeObjectOption: Option[Tuple3[Class[_], Class[_], ActiveObjectProxy]] = activeObjectRegistry.get(clazz)
if (activeObjectOption.isDefined) {
val classInfo = activeObjectOption.get
- val intfClass = classInfo._1
- val implClass = classInfo._2
+ val intfClass = classInfo._1
+ val implClass = classInfo._2
val activeObjectProxy = classInfo._3
val target = implClass.newInstance
injector.injectMembers(target)
activeObjectProxy.setTargetInstance(target.asInstanceOf[AnyRef])
activeObjectFactory.newInstance(intfClass, activeObjectProxy).asInstanceOf[AnyRef]
- } else throw new IllegalStateException("Class " + name + " has not been put under supervision (by passing in the config to the 'supervise') method")
+ } else throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'supervise') method")
}
- def getActiveObjectProxy(name: String): ActiveObjectProxy = synchronized {
- log.debug("Looking up active object proxy [%s]", name)
- if (injector == null) throw new IllegalStateException("inject() and supervise() must be called before invoking newInstance(clazz)")
- val activeObjectOption: Option[Tuple3[Class[_], Class[_], ActiveObjectProxy]] = activeObjectRegistry.get(name)
+ override def getActiveObjectProxy(clazz: Class[_]): ActiveObjectProxy = synchronized {
+ log.debug("Looking up active object proxy [%s]", clazz.getName)
+ if (injector == null) throw new IllegalStateException("inject() and/or supervise() must be called before invoking getActiveObjectProxy(clazz)")
+ val activeObjectOption: Option[Tuple3[Class[_], Class[_], ActiveObjectProxy]] = activeObjectRegistry.get(clazz)
if (activeObjectOption.isDefined) activeObjectOption.get._3
- else throw new IllegalStateException("Class " + name + " has not been put under supervision (by passing in the config to the 'supervise') method")
+ else throw new IllegalStateException("Class [" + clazz.getName + "] has not been put under supervision (by passing in the config to the 'supervise') method")
}
- def getExternalDependency[T](clazz: Class[T]): T = synchronized {
+ override def getExternalDependency[T](clazz: Class[T]): T = synchronized {
injector.getInstance(clazz).asInstanceOf[T]
}
- def getRoutingEndpoint(uri: String): Endpoint = synchronized {
+ override def getRoutingEndpoint(uri: String): Endpoint = synchronized {
camelContext.getEndpoint(uri)
}
- def getRoutingEndpoints: java.util.Collection[Endpoint] = synchronized {
+ override def getRoutingEndpoints: java.util.Collection[Endpoint] = synchronized {
camelContext.getEndpoints
}
- def getRoutingEndpoints(uri: String): java.util.Collection[Endpoint] = synchronized {
+ override def getRoutingEndpoints(uri: String): java.util.Collection[Endpoint] = synchronized {
camelContext.getEndpoints(uri)
}
- def configureActiveObjects(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectGuiceConfigurator = synchronized {
+ override def configureActiveObjects(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectConfigurator = synchronized {
this.restartStrategy = restartStrategy
this.components = components.toArray.toList.asInstanceOf[List[Component]]
bindings = for (c <- this.components)
@@ -93,19 +97,19 @@ class ActiveObjectGuiceConfigurator extends Logging {
this
}
- def inject: ActiveObjectGuiceConfigurator = synchronized {
+ override def inject: ActiveObjectConfigurator = synchronized {
if (injector != null) throw new IllegalStateException("inject() has already been called on this configurator")
injector = Guice.createInjector(modules)
this
}
- def supervise: ActiveObjectGuiceConfigurator = synchronized {
+ override def supervise: ActiveObjectConfigurator = synchronized {
if (injector == null) inject
var workers = new java.util.ArrayList[Worker]
for (component <- components) {
val activeObjectProxy = new ActiveObjectProxy(component.intf, component.target, component.timeout)
workers.add(Worker(activeObjectProxy.server, component.lifeCycle))
- activeObjectRegistry.put(component.name, (component.intf, component.target, activeObjectProxy))
+ activeObjectRegistry.put(component.intf, (component.intf, component.target, activeObjectProxy))
camelContext.getRegistry.asInstanceOf[JndiRegistry].bind(component.name, activeObjectProxy)
for (method <- component.intf.getDeclaredMethods.toList) {
registerMethodForUri(method, component.name)
@@ -115,13 +119,15 @@ class ActiveObjectGuiceConfigurator extends Logging {
supervisor = activeObjectFactory.supervise(restartStrategy, workers)
camelContext.addComponent(AKKA_CAMEL_ROUTING_SCHEME, new ActiveObjectComponent(this))
camelContext.start
+
+ ActiveObjectConfigurator.registerConfigurator(this)
this
}
/**
* Add additional services to be wired in.
*
- * ActiveObjectGuiceModule.addExternalGuiceModule(new AbstractModule {
+ * activeObjectConfigurator.addExternalGuiceModule(new AbstractModule {
* protected void configure() {
* bind(Foo.class).to(FooImpl.class).in(Scopes.SINGLETON);
* bind(BarImpl.class);
@@ -130,39 +136,24 @@ class ActiveObjectGuiceConfigurator extends Logging {
* }})
*
*/
- def addExternalGuiceModule(module: Module): ActiveObjectGuiceConfigurator = synchronized {
+ def addExternalGuiceModule(module: Module): ActiveObjectConfigurator = synchronized {
modules.add(module)
this
}
- /**
- * Add Camel routes for the active objects.
- *
- * activeObjectGuiceModule.addRoutes(new RouteBuilder() {
- * def configure = {
- * from("akka:actor1").to("akka:actor2")
- * from("akka:actor2").process(new Processor() {
- * def process(e: Exchange) = {
- * println("Received exchange: " + e.getIn())
- * }
- * })
- * }
- * }).inject().supervise();
- *
- */
- def addRoutes(routes: Routes): ActiveObjectGuiceConfigurator = synchronized {
+ override def addRoutes(routes: Routes): ActiveObjectConfigurator = synchronized {
camelContext.addRoutes(routes)
this
}
- def getCamelContext: CamelContext = camelContext
+ override def getCamelContext: CamelContext = camelContext
def getGuiceModules: java.util.List[Module] = modules
def reset = synchronized {
modules = new java.util.ArrayList[Module]
configRegistry = new HashMap[Class[_], Component]
- activeObjectRegistry = new HashMap[String, Tuple3[Class[_], Class[_], ActiveObjectProxy]]
+ activeObjectRegistry = new HashMap[Class[_], Tuple3[Class[_], Class[_], ActiveObjectProxy]]
methodToUriRegistry = new HashMap[Method, String]
injector = null
restartStrategy = null
diff --git a/kernel/src/main/scala/config/CamelConfigurator.scala b/kernel/src/main/scala/config/CamelConfigurator.scala
new file mode 100644
index 0000000000..5f2f6bf0aa
--- /dev/null
+++ b/kernel/src/main/scala/config/CamelConfigurator.scala
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.kernel.config
+
+import org.apache.camel.{Routes, CamelContext, Endpoint}
+
+trait CamelConfigurator {
+
+ /**
+ * Add Camel routes for the active objects.
+ *
+ * activeObjectConfigurator.addRoutes(new RouteBuilder() {
+ * def configure = {
+ * from("akka:actor1").to("akka:actor2")
+ * from("akka:actor2").process(new Processor() {
+ * def process(e: Exchange) = {
+ * println("Received exchange: " + e.getIn())
+ * }
+ * })
+ * }
+ * }).inject().supervise();
+ *
+ */
+ def addRoutes(routes: Routes): ActiveObjectConfigurator
+
+ def getCamelContext: CamelContext
+
+ def getRoutingEndpoint(uri: String): Endpoint
+
+ // F
+ def getRoutingEndpoints: java.util.Collection[Endpoint]
+
+ def getRoutingEndpoints(uri: String): java.util.Collection[Endpoint]
+}
diff --git a/kernel/src/main/scala/jersey/ActiveObjectComponentProvider.scala b/kernel/src/main/scala/jersey/ActiveObjectComponentProvider.scala
new file mode 100644
index 0000000000..039aa19ec0
--- /dev/null
+++ b/kernel/src/main/scala/jersey/ActiveObjectComponentProvider.scala
@@ -0,0 +1,21 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.kernel.jersey
+
+import kernel.Logging
+import config.ActiveObjectConfigurator
+
+import com.sun.jersey.core.spi.component.ioc.IoCComponentProvider
+import com.sun.jersey.core.spi.component.ComponentProvider
+
+import java.lang.reflect.{Constructor, InvocationTargetException}
+
+class ActiveObjectComponentProvider(val clazz: Class[_], val configurator: ActiveObjectConfigurator)
+ extends IoCComponentProvider with Logging {
+
+ override def getInstance: AnyRef = {
+ configurator.getActiveObject(clazz).asInstanceOf[AnyRef]
+ }
+}
\ No newline at end of file
diff --git a/kernel/src/main/scala/jersey/ActiveObjectComponentProviderFactory.scala b/kernel/src/main/scala/jersey/ActiveObjectComponentProviderFactory.scala
new file mode 100644
index 0000000000..898af47028
--- /dev/null
+++ b/kernel/src/main/scala/jersey/ActiveObjectComponentProviderFactory.scala
@@ -0,0 +1,21 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.kernel.jersey
+
+import com.sun.jersey.core.spi.component.ioc.{IoCComponentProvider, IoCComponentProviderFactory}
+import com.sun.jersey.core.spi.component.{ComponentContext, ComponentProviderFactory}
+import config.ActiveObjectConfigurator
+
+class ActiveObjectComponentProviderFactory(val configurator: ActiveObjectConfigurator)
+ extends IoCComponentProviderFactory {
+
+ override def getComponentProvider(clazz: Class[_]): ActiveObjectComponentProvider = {
+ new ActiveObjectComponentProvider(clazz, configurator)
+ }
+
+ override def getComponentProvider(context: ComponentContext, clazz: Class[_]): ActiveObjectComponentProvider = {
+ new ActiveObjectComponentProvider(clazz, configurator)
+ }
+}
\ No newline at end of file
diff --git a/kernel/src/main/scala/jersey/AkkaServlet.scala b/kernel/src/main/scala/jersey/AkkaServlet.scala
new file mode 100644
index 0000000000..5795434277
--- /dev/null
+++ b/kernel/src/main/scala/jersey/AkkaServlet.scala
@@ -0,0 +1,19 @@
+/**
+ * Copyright (C) 2009 Scalable Solutions.
+ */
+
+package se.scalablesolutions.akka.kernel.jersey
+
+import com.sun.jersey.api.core.ResourceConfig
+import com.sun.jersey.spi.container.servlet.ServletContainer
+import com.sun.jersey.spi.container.WebApplication
+
+import config.ActiveObjectConfigurator
+
+class AkkaServlet extends ServletContainer {
+
+ override def initiate(rc: ResourceConfig, wa: WebApplication) = {
+ val configurator = ActiveObjectConfigurator.getConfiguratorFor(getServletContext)
+ wa.initiate(rc, new ActiveObjectComponentProviderFactory(configurator));
+ }
+}
\ No newline at end of file
diff --git a/kernel/src/test/scala/JerseySpec.scala b/kernel/src/test/scala/JerseySpec.scala
index 83c3d43881..f2c6c12eac 100644
--- a/kernel/src/test/scala/JerseySpec.scala
+++ b/kernel/src/test/scala/JerseySpec.scala
@@ -46,7 +46,7 @@ class JerseySpec extends Spec with ShouldMatchers {
1000) ::
Nil).supervise
- conf.getActiveObject("jerseyfoo")
+ conf.getActiveObject(classOf[resource.JerseyFoo])
/*
val client = Client.create
diff --git a/kernel/web.xml b/kernel/web.xml
new file mode 100644
index 0000000000..68a6bf82c5
--- /dev/null
+++ b/kernel/web.xml
@@ -0,0 +1,14 @@
+
+
+
+ Jersey Akka
+ se.scalablesolutions.akka.kernel.jersey.AkkaServlet
+
+
+ Jersey Akka
+ /*
+
+