Some more service orientation to master conf
authorChristos KK Loverdos <loverdos@gmail.com>
Mon, 12 Dec 2011 11:24:44 +0000 (13:24 +0200)
committerChristos KK Loverdos <loverdos@gmail.com>
Mon, 12 Dec 2011 11:24:44 +0000 (13:24 +0200)
logic/src/main/resources/aquarium.properties
logic/src/main/scala/gr/grnet/aquarium/MasterConf.scala
logic/src/main/scala/gr/grnet/aquarium/actor/ActorProvider.scala
logic/src/main/scala/gr/grnet/aquarium/actor/SimpleLocalActorProvider.scala
logic/src/main/scala/gr/grnet/aquarium/rest/RESTService.scala [new file with mode: 0644]
logic/src/main/scala/gr/grnet/aquarium/rest/actor/RESTActorService.scala [new file with mode: 0644]
logic/src/test/scala/gr/grnet/aquarium/rest/actor/RESTActorTest.scala

index 40fc598..c28925b 100644 (file)
@@ -23,6 +23,8 @@ rest.port=8080
 # DO NOT TOUCH the following, unless you know what you are doing
 # Actor subsystem
 actor.provider.class=gr.grnet.aquarium.actor.SimpleLocalActorProvider
+# Class that initializes the REST service
+rest.service.class=gr.grnet.aquarium.rest.actor.RESTActorService
 
 # Comma separated list of exchanges known to aquarium
 amqp.exchanges=aquarium
index 3ecfd12..6e91805 100644 (file)
@@ -41,6 +41,7 @@ import com.ckkloverdos.sys.SysProp
 import com.ckkloverdos.props.Props
 import com.ckkloverdos.maybe.{Maybe, Failed, Just, NoVal}
 import com.ckkloverdos.convert.Converters.{DefaultConverters => TheDefaultConverters}
+import rest.RESTService
 
 /**
  * The master configurator. Responsible to load all of application configuration and provide the relevant services.
@@ -50,16 +51,23 @@ import com.ckkloverdos.convert.Converters.{DefaultConverters => TheDefaultConver
 class MasterConf(val props: Props) {
   import MasterConf.Keys
 
-  private[this] val _actorProvider: ActorProvider = {
-    val className = props.getEx(Keys.actor_provider_class)
-    val actorProvider = defaultClassLoader.loadClass(className).newInstance().asInstanceOf[ActorProvider]
-    
-    actorProvider match {
+  private[this] def newInstance[C : Manifest](className: String): C = {
+    val c = defaultClassLoader.loadClass(className).newInstance().asInstanceOf[C]
+    c match {
       case configurable: Configurable ⇒
         configurable configure props
+        c
+      case _ ⇒
+        c
     }
+  }
 
-    actorProvider
+  private[this] val _actorProvider: ActorProvider = {
+    newInstance[ActorProvider](props.getEx(Keys.actor_provider_class))
+  }
+  
+  private[this] val _restService: RESTService = {
+    newInstance[RESTService](props.getEx(Keys.rest_service_class))
   }
 
   def get(prop: String): String =
@@ -69,6 +77,23 @@ class MasterConf(val props: Props) {
     }
 
   def defaultClassLoader = Thread.currentThread().getContextClassLoader
+
+  def startServices(): Unit = {
+    _actorProvider.start()
+    _restService.start()
+  }
+
+  def stopServices(): Unit = {
+    _restService.stop()
+    _actorProvider.stop()
+    
+//    akka.actor.Actor.registry.shutdownAll()
+  }
+
+  def stopServicesWithDelay(millis: Long) {
+    Thread sleep millis
+    stopServices()
+  }
   
   def actorProvider = _actorProvider
 }
@@ -175,6 +200,11 @@ object MasterConf {
     final val actor_provider_class = "actor.provider.class"
 
     /**
+     * The class that initializes the REST service
+     */
+    final val rest_service_class = "rest.service.class"
+
+    /**
      * Comma separated list of amqp servers running in active-active
      * configuration.
      */
index 7a4a9f2..4e5b543 100644 (file)
@@ -51,4 +51,8 @@ trait ActorProvider {
    */
   @throws(classOf[Exception])
   def actorForRole(role: ActorRole, hints: Props = Props.empty): ActorRef
+
+  def start(): Unit
+
+  def stop(): Unit
 }
\ No newline at end of file
index eb47bee..100cfdc 100644 (file)
@@ -47,7 +47,15 @@ import gr.grnet.aquarium.Configurable
  */
 class SimpleLocalActorProvider extends ActorProvider with Configurable {
   def configure(props: Props): Unit = {
+  }
+
+  def start(): Unit = {
+    for(role <- SimpleLocalActorProvider.KnownRoles) {
+      actorForRole(role)
+    }
+  }
 
+  def stop(): Unit = {
   }
 
   @throws(classOf[Exception])
diff --git a/logic/src/main/scala/gr/grnet/aquarium/rest/RESTService.scala b/logic/src/main/scala/gr/grnet/aquarium/rest/RESTService.scala
new file mode 100644 (file)
index 0000000..868de17
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2011 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+
+package gr.grnet.aquarium.rest
+
+import gr.grnet.aquarium.Configurable
+
+/**
+ * 
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+trait RESTService {
+  def start(): Unit
+  def stop(): Unit
+}
\ No newline at end of file
diff --git a/logic/src/main/scala/gr/grnet/aquarium/rest/actor/RESTActorService.scala b/logic/src/main/scala/gr/grnet/aquarium/rest/actor/RESTActorService.scala
new file mode 100644 (file)
index 0000000..382e57a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+
+package gr.grnet.aquarium.rest
+package actor
+
+import gr.grnet.aquarium.MasterConf
+import gr.grnet.aquarium.actor.RESTRole
+import _root_.akka.actor._
+import cc.spray.can.{ClientConfig, HttpClient, ServerConfig, HttpServer}
+
+/**
+ * 
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+class RESTActorService extends RESTService {
+  private[this] var _port: Int = 8080
+  private[this] var _restActor: ActorRef = _
+  private[this] var _serverActor: ActorRef = _
+  private[this] var _clientActor: ActorRef = _
+
+  def start(): Unit = {
+    val mc = MasterConf.MasterConf
+    this._port = mc.props.getInt(MasterConf.Keys.rest_port).getOr(this._port)
+    this._restActor = mc.actorProvider.actorForRole(RESTRole)
+    // Start Spray subsystem
+    val serverConfig = ServerConfig(port = _port)
+    val clientConfig = ClientConfig()
+    this._serverActor = Actor.actorOf(new HttpServer(serverConfig)).start()
+    this._clientActor = Actor.actorOf(new HttpClient(clientConfig)).start()
+  }
+
+  def stop(): Unit = {
+    this._serverActor ! PoisonPill
+    this._clientActor ! PoisonPill
+  }
+}
\ No newline at end of file
index 2ab6dc1..2d0ff76 100644 (file)
@@ -55,15 +55,11 @@ import net.liftweb.json.JsonAST.JInt
  */
 class RESTActorTest {
   @Test
-  def testOneCall: Unit = {
+  def testPing: Unit = {
     // Initialize configuration subsystem
     val mc = MasterConf.MasterConf
+    mc.startServices()
     val port = mc.props.getInt(MasterConf.Keys.rest_port).getOr(8080)
-    // Initialize REST actor
-    val rest = mc.actorProvider.actorForRole(RESTRole)
-    // Initialize spray underlying server
-    val server = Actor.actorOf(new SprayHttpServer()).start()
-    val client = Actor.actorOf(new SprayHttpClient()).start()
     val dialog = SprayHttpDialog("localhost", port)
 
     val pingReq = HttpRequest(method = GET, uri = "/ping", headers = HttpHeader("Content-Type", "text/plain; charset=UTF-8")::Nil)
@@ -86,10 +82,7 @@ class RESTActorTest {
           fail("Got nothing")
       }
     }
-    
-    Thread.sleep(3000)
-    server ! PoisonPill
-    client ! PoisonPill
-    Actor.registry.shutdownAll()
+
+    mc.stopServicesWithDelay(1000)
   }
 }
\ No newline at end of file