pekko/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala

176 lines
5.2 KiB
Scala
Raw Normal View History

2009-08-02 12:33:42 +02:00
/**
2009-12-27 16:01:53 +01:00
* Copyright (C) 2009-2010 Scalable Solutions AB <http://scalablesolutions.se>
2009-08-02 12:33:42 +02:00
*/
package sample.scala
2009-12-18 21:26:03 +01:00
import se.scalablesolutions.akka.actor.{Transactor, SupervisorFactory, Actor}
import se.scalablesolutions.akka.stm.TransactionalState
import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage
import se.scalablesolutions.akka.config.ScalaConfig._
import se.scalablesolutions.akka.util.Logging
import se.scalablesolutions.akka.comet.AkkaClusterBroadcastFilter
import java.lang.Integer
2009-12-07 08:13:34 +01:00
import java.nio.ByteBuffer
2009-08-02 12:58:20 +02:00
import javax.ws.rs.core.MultivaluedMap
2009-12-02 21:08:29 +01:00
import javax.ws.rs.{GET, POST, Path, Produces, WebApplicationException, Consumes,PathParam}
import org.atmosphere.annotation.{Broadcast, Suspend,Cluster}
2009-08-02 12:58:20 +02:00
import org.atmosphere.util.XSSHtmlFilter
2009-12-07 08:13:34 +01:00
import org.atmosphere.cpr.{Broadcaster, BroadcastFilter}
2009-12-02 21:08:29 +01:00
import org.atmosphere.jersey.Broadcastable
class Boot {
val factory = SupervisorFactory(
SupervisorConfig(
2009-12-02 21:08:29 +01:00
RestartStrategy(OneForOne, 3, 100,List(classOf[Exception])),
Supervise(
new SimpleService,
LifeCycle(Permanent)) ::
Supervise(
new Chat,
LifeCycle(Permanent)) ::
Supervise(
new PersistentSimpleService,
2009-12-02 21:08:29 +01:00
LifeCycle(Permanent)) ::
2009-12-18 21:26:03 +01:00
Supervise(
2009-12-02 21:08:29 +01:00
new PubSub,
LifeCycle(Permanent))
:: Nil))
factory.newInstance.start
}
/**
* Try service out by invoking (multiple times):
* <pre>
* curl http://localhost:9998/scalacount
* </pre>
* Or browse to the URL from a web browser.
*/
@Path("/scalacount")
2009-12-18 21:26:03 +01:00
class SimpleService extends Transactor {
case object Tick
2009-10-23 22:37:28 +01:00
private val KEY = "COUNTER"
private var hasStartedTicking = false
private lazy val storage = TransactionalState.newMap[String, Integer]
@GET
@Produces(Array("text/html"))
def count = (this !! Tick).getOrElse(<error>Error in counter</error>)
def receive = {
case Tick => if (hasStartedTicking) {
val counter = storage.get(KEY).get.asInstanceOf[Integer].intValue
storage.put(KEY, new Integer(counter + 1))
reply(<success>Tick:{counter + 1}</success>)
} else {
storage.put(KEY, new Integer(0))
hasStartedTicking = true
reply(<success>Tick: 0</success>)
}
}
}
2009-12-18 21:26:03 +01:00
@Path("/pubsub/")
class PubSub extends Actor {
case class Msg(topic: String, message: String)
@GET
@Suspend
@Produces(Array("text/plain;charset=ISO-8859-1"))
@Path("/topic/{topic}/")
def subscribe(@PathParam("topic") topic: Broadcaster): Broadcastable = new Broadcastable("", topic)
@GET
@Broadcast
@Path("/topic/{topic}/{message}/")
@Produces(Array("text/plain;charset=ISO-8859-1"))
@Cluster(Array(classOf[AkkaClusterBroadcastFilter])) { val name = "foo" }
2009-12-18 21:26:03 +01:00
def say(@PathParam("topic") topic: Broadcaster, @PathParam("message") message: String): Broadcastable = new Broadcastable(message, topic)
def receive = { case _ => }
}
/**
* Try service out by invoking (multiple times):
* <pre>
* curl http://localhost:9998/persistentscalacount
* </pre>
* Or browse to the URL from a web browser.
*/
@Path("/persistentscalacount")
2009-12-25 11:37:43 +01:00
class PersistentSimpleService extends Transactor {
case object Tick
2009-10-23 22:37:28 +01:00
private val KEY = "COUNTER"
private var hasStartedTicking = false
private lazy val storage = CassandraStorage.newMap
@GET
@Produces(Array("text/html"))
def count = (this !! Tick).getOrElse(<error>Error in counter</error>)
def receive = {
case Tick => if (hasStartedTicking) {
val bytes = storage.get(KEY.getBytes).get
val counter = ByteBuffer.wrap(bytes).getInt
storage.put(KEY.getBytes, ByteBuffer.allocate(4).putInt(counter + 1).array)
2009-08-02 12:33:42 +02:00
reply(<success>Tick:{counter + 1}</success>)
} else {
storage.put(KEY.getBytes, Array(0.toByte))
hasStartedTicking = true
reply(<success>Tick: 0</success>)
}
}
}
@Path("/chat")
2009-12-25 11:37:43 +01:00
class Chat extends Actor {
case class Chat(val who: String, val what: String, val msg: String)
2009-08-02 12:33:42 +02:00
@Suspend
@GET
@Produces(Array("text/html"))
def suspend = ()
2009-08-02 12:33:42 +02:00
def receive = {
case Chat(who, what, msg) => {
what match {
case "login" => reply("System Message__" + who + " has joined.")
case "post" => reply("" + who + "__" + msg)
case _ => throw new WebApplicationException(422)
}
}
case x => log.info("recieve unknown: " + x)
}
@POST
@Broadcast(Array(classOf[XSSHtmlFilter], classOf[JsonpFilter]))
@Cluster(Array(classOf[AkkaClusterBroadcastFilter])) { val name = "bar" }
@Consumes(Array("application/x-www-form-urlencoded"))
@Produces(Array("text/html"))
2009-12-03 09:14:39 +01:00
def publishMessage(form: MultivaluedMap[String, String]) =
(this !! Chat(form.getFirst("name"),
form.getFirst("action"),
form.getFirst("message"))).getOrElse("System__error")
}
2009-07-29 20:17:40 +02:00
class JsonpFilter extends BroadcastFilter[String] with Logging {
def filter(an: AnyRef) = {
val m = an.toString
var name = m
var message = ""
2009-07-29 20:17:40 +02:00
if (m.indexOf("__") > 0) {
name = m.substring(0, m.indexOf("__"))
message = m.substring(m.indexOf("__") + 2)
}
2010-02-02 19:20:07 +01:00
new BroadcastFilter.BroadcastAction("<script type='text/javascript'>\n (window.app || window.parent.app).update({ name: \"" +
2009-12-03 09:14:39 +01:00
name + "\", message: \"" + message + "\" }); \n</script>\n")
}
2009-08-02 16:14:12 +02:00
}