Introduce the REST module.
authorChristos KK Loverdos <loverdos@gmail.com>
Mon, 5 Dec 2011 15:32:11 +0000 (17:32 +0200)
committerChristos KK Loverdos <loverdos@gmail.com>
Mon, 5 Dec 2011 15:33:35 +0000 (17:33 +0200)
This is powered by spray (spray.cc), an akka-based HTTP server.
The test is not working correctly yet.

logic/pom.xml
logic/src/main/scala/gr/grnet/aquarium/rest/akka/service/PingSprayService.scala [new file with mode: 0644]
logic/src/test/resources/akka.conf
logic/src/test/resources/log4j.properties [new file with mode: 0644]
logic/src/test/scala/gr/grnet/aquarium/LogicTestsAssumptions.scala
logic/src/test/scala/gr/grnet/aquarium/PropertyNames.scala
logic/src/test/scala/gr/grnet/aquarium/rest/akka/service/PingSprayServiceTest.scala [new file with mode: 0644]
project/build/Aquarium.scala

index 18ab16c..49b873e 100644 (file)
       <name>Typesafe releases</name>
       <url>http://repo.typesafe.com/typesafe/releases</url>
     </repository>
+
+    <repository>
+      <id>twitter</id>
+      <name>Twitter</name>
+      <url>http://maven.twttr.com</url>
+    </repository>
+
+    <repository>
+      <id>scala-tools-snapshots</id>
+      <name>Scala-Tools Dependencies Repository for Releases</name>
+      <url>http://scala-tools.org/repo-snapshots</url>
+    </repository>
   </repositories>
 
   <dependencies>
     <!-- Official MongoDB scala driver -->
     <!-- For issues with the driver see: https://jira.mongodb.org/browse/SCALA -->
     <!--<dependency>-->
-      <!--<groupId>com.mongodb.casbah</groupId>-->
-      <!--<artifactId>casbah-core_2.9.1</artifactId>-->
-      <!--<version>2.1.5-1</version>-->
+    <!--<groupId>com.mongodb.casbah</groupId>-->
+    <!--<artifactId>casbah-core_2.9.1</artifactId>-->
+    <!--<version>2.1.5-1</version>-->
     <!--</dependency>-->
 
     <dependency>
       <version>1.3-RC1</version>
       <scope>test</scope>
     </dependency>
+
+    <dependency>
+      <groupId>javax.ws.rs</groupId>
+      <artifactId>jsr311-api</artifactId>
+      <version>1.1.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.twitter</groupId>
+      <artifactId>finagle-core</artifactId>
+      <version>1.9.10</version>
+    </dependency>
+
+    <dependency>
+      <groupId>cc.spray.can</groupId>
+      <artifactId>spray-can</artifactId>
+      <version>0.9.1</version>
+    </dependency>
   </dependencies>
 </project>
diff --git a/logic/src/main/scala/gr/grnet/aquarium/rest/akka/service/PingSprayService.scala b/logic/src/main/scala/gr/grnet/aquarium/rest/akka/service/PingSprayService.scala
new file mode 100644 (file)
index 0000000..cfc4d06
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.akka.service
+
+import org.slf4j.LoggerFactory
+import cc.spray.can.HttpMethods.GET
+import akka.actor.Actor
+import cc.spray.can.{HttpHeader, HttpResponse, HttpRequest, RequestContext}
+
+/**
+ * 
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+class PingSprayService extends Actor {
+  private[this] val logger = LoggerFactory.getLogger(getClass)
+//  self.id = "aquarium-rest"
+
+  // https://github.com/spray/spray-can/blob/master/server-example/src/main/scala/cc/spray/can/example/TestService.scala
+  val defaultHeaders = List(HttpHeader("Content-Type", "text/plain"))
+
+  def response(msg: String, status: Int = 200) = HttpResponse(status, defaultHeaders , msg.getBytes("UTF-8"))
+
+  protected def receive = {
+    case RequestContext(HttpRequest(GET, "/ping", _, _, _), _, responder) =>
+      responder.complete(response("pong " + System.currentTimeMillis()))
+  }
+}
\ No newline at end of file
index 3bb8ad8..b8b068a 100644 (file)
@@ -12,7 +12,7 @@ akka {
 
   time-unit = "seconds"      # Time unit for all timeout properties throughout the config
 
-  event-handlers = ["akka.event.EventHandler$DefaultListener"] # event handlers to register at boot time (EventHandler$DefaultListener logs to STDOUT)
+  event-handlers = ["akka.event.EventHandler$DefaultListener", "akka.event.slf4j.Slf4jEventHandler"] # event handlers to register at boot time (EventHandler$DefaultListener logs to STDOUT)
   event-handler-level = "DEBUG" # Options: ERROR, WARNING, INFO, DEBUG
 
   # These boot classes are loaded (and created) automatically when the Akka Microkernel boots up
@@ -68,33 +68,6 @@ akka {
       lifecycle = "false"     # enable DEBUG logging of actor lifecycle changes
     }
 
-    mailbox {
-        mongodb {
-            # Any specified collection name will be used as a prefix for collections that use durable mongo mailboxes
-            uri = "mongodb://localhost/akka.mailbox"   # Follow Mongo URI Spec - http://www.mongodb.org/display/DOCS/Connections
-            # Configurable timeouts for certain ops
-            timeout {
-                read = 3000 # number of milliseconds to wait for a read to succeed before timing out the future
-                write = 3000 # number of milliseconds to wait for a write to succeed before timing out the future
-            }
-        }
-      }
-    }
-
-  stm {
-    fair             = on     # Should global transactions be fair or non-fair (non fair yield better performance)
-    max-retries      = 1000
-    timeout          = 5      # Default timeout for blocking transactions and transaction set (in unit defined by
-                              #     the time-unit property)
-    write-skew       = true
-    blocking-allowed = false
-    interruptible    = false
-    speculative      = true
-    quick-release    = true
-    propagation      = "requires"
-    trace-level      = "none"
-  }
-
   http {
     hostname = "localhost"
     port = 9998
@@ -104,7 +77,7 @@ akka {
     # resource-packages = ["sample.rest.scala",
     #                      "sample.rest.java",
     #                      "sample.security"] # List with all resource packages for your Jersey services
-    resource-packages = []
+    resource-packages = ["gr.grnet.aquarium.rest", "gr.grnet.aquarium.rest.service"]
 
     # The authentication service to use. Need to be overridden (sample now)
     # authenticator = "sample.security.BasicAuthenticationService"
@@ -174,4 +147,12 @@ akka {
   test {
     timefactor = "1.0"    # factor by which to scale timeouts during tests, e.g. to account for shared build system load
   }
+}
+
+# spray-can config
+spray-can {
+  server {
+    port = 8080
+    request-timeout = 2000 # require all requests to be completed within 2 seconds
+  }
 }
\ No newline at end of file
diff --git a/logic/src/test/resources/log4j.properties b/logic/src/test/resources/log4j.properties
new file mode 100644 (file)
index 0000000..8ff7d5a
--- /dev/null
@@ -0,0 +1,6 @@
+log4j.rootLogger=DEBUG,console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d %t %F:%L - %m%n
+log4j.appender.console.threshold=DEBUG
index f0634ca..95e01c6 100644 (file)
@@ -65,4 +65,5 @@ object LogicTestsAssumptions {
   val EnableRabbitMQTests = testPropertyTrue(PropertyNames.TestEnableRabbitMQ)
   val EnableMongoDBTests  = testPropertyTrue(PropertyNames.TestEnableMongoDB)
   val EnablePerfTests = testPropertyTrue(PropertyNames.TestEnablePerf)
+  val EnableSprayTests = testPropertyTrue(PropertyNames.TestEnableSpray)
 }
\ No newline at end of file
index dd488c4..05dca13 100644 (file)
@@ -45,6 +45,7 @@ object PropertyNames {
   val TestEnableRabbitMQ = "test.enable.rabbitmq"
   val TestEnableMongoDB  = "test.enable.mongodb"
   val TestEnablePerf     = "test.enable.perf"
+  val TestEnableSpray    = "test.enable.spray"
 
   // Test configuration files used
   val MongoDBConfFile  = "mongodb.conf.file"
diff --git a/logic/src/test/scala/gr/grnet/aquarium/rest/akka/service/PingSprayServiceTest.scala b/logic/src/test/scala/gr/grnet/aquarium/rest/akka/service/PingSprayServiceTest.scala
new file mode 100644 (file)
index 0000000..95627cd
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.akka.service
+
+import org.junit.Test
+import cc.spray.can.HttpClient._
+import akka.actor.{PoisonPill, Actor}
+import cc.spray.can.{HttpClient, HttpResponse, HttpRequest, HttpServer}
+
+import cc.spray.can.HttpMethods.GET
+import gr.grnet.aquarium.util.Loggable
+import org.junit.Assume._
+import gr.grnet.aquarium.LogicTestsAssumptions
+
+/**
+ * 
+ * @author Christos KK Loverdos <loverdos@gmail.com>.
+ */
+class PingSprayServiceTest extends Loggable {
+  def show(response: HttpResponse) {
+      println(
+        """|Result from host:
+           |status : {}
+           |headers: {}
+           |body   : {}""".stripMargin,
+        Array(response.status: java.lang.Integer, response.headers, response.bodyAsString)
+      )
+    }
+  @Test
+  def testPing: Unit = {
+    assumeTrue(LogicTestsAssumptions.EnableSprayTests)
+    
+    val server = Actor.actorOf(new HttpServer()).start()
+    val client = Actor.actorOf(new HttpClient()).start()
+
+    val dialog = HttpDialog("localhost", 8080)
+    val result = dialog.send(HttpRequest(method = GET, uri = "/ping")).end
+    result onComplete { future =>
+      future.value match {
+        case Some(Right(response)) =>
+          show(response)
+        case other =>
+          logger.error("Error: %s".format(other))
+      }
+
+      server ! PoisonPill
+      client ! PoisonPill
+    }
+
+    Thread.sleep(10000)
+  }
+}
\ No newline at end of file
index 5ea1074..0796b53 100644 (file)
@@ -46,6 +46,7 @@ class Aquarium(info: ProjectInfo) extends ParentProject(info) {
        //val repo5 = "jcrontab" at "http://kenai.com/projects/crontab-parser/sources/maven-repo/content/"
        // val repo6 = "typsafe" at "http://repo.typesafe.com/typesafe/releases/"
        // val repo7 = "akka" at "http://akka.io/repository/"
+       // repo8 = "twitter" at "http://maven.twttr.com"
 
        val lib_slf4j     = "org.slf4j"      % "slf4j-api"            % "1.6.1"   withSources()
        val lib_h2        = "com.h2database" % "h2"                   % "1.3.160" withSources()
@@ -69,8 +70,10 @@ class Aquarium(info: ProjectInfo) extends ParentProject(info) {
        //val lib_casbah    = "com.mongodb.casbah" % "casbah-core_2.9.1"  % "2.1.5-1" withSources()
        val lib_akka_actor  = "se.scalablesolutions.akka" % "akka-actor" % "1.3-RC1" withSources()
        val lib_akka_remote = "se.scalablesolutions.akka" % "akka-remote" % "1.3-RC1" withSources()
+       val lib_akka_test   = "se.scalablesolutions.akka" % "akka-testkit" % "1.3-RC1" % "test" withSources()
 
-       val lib_akka_test = "se.scalablesolutions.akka" % "akka-testkit" % "1.3-RC1" % "test" withSources()
+       val lib_javaxrs     = "javax.ws.rs" % "jsr311-api" % "1.1.1" withSources()
+       val lib_spray_can   = "cc.spray.can" % "spray-can" % "0.9.2-SNAPSHOT" withSources()
 
                val lib_converter      = "com.ckkloverdos" % "converter_2.9.1"      % "0.3.0" withSources()
                val lib_streamresource = "com.ckkloverdos" % "streamresource_2.9.1" % "0.2.0" withSources()