Now that I am a speaker at JavaOne 2012, I would like to take the opportunity to promote Java University 2012 (where I present the Developing Secure Java Web Services track).
Java University 2012 (see http://www.oracle.com/javaone/program/schedule/university/index.html) which will be held on Sunday September 30, 2012 8:00 a.m.– 3:30 p.m, will be available to JavaOne with Java University Pass and Java University Pass holders. Learn form the experts the latest state of the art technologies like: Java SE 7 New Features, Java EE 6, JavaFX, SOA, Cloud Computing, Secure Web Services, Web 2.0, JSF 2.2 and much more.
Architect and Design Robust Enterprise Java Applications for the Cloud and Beyond In other words, how to structure applications to head off the rogue side effects that impact quality of service, such as performance, reliability, availability, and security. The latest java EE 6 practices and patterns addressed in this course give you the answer. Design Robust Enterprise Java Applications for the Cloud. Adopt SOA capabilities to efficiently respond to changing market conditions in a cost-effective manner. Learn about the Enterprise Service Bus (ESB) (based on Java Business Integration (JBI) specification) which helps automate, manage, and optimize business processes and workflows across systems, people, and partners.
Developing Secure Java Web Services The focus here is on B2B applications: Secure Web Services that communicate with each other through XML documents. The technology in question is the new robust Java API for XML-based Web services (JAX-WS) and Restful Web services (JAX-RS). The result: a seamless, transparent process, independent of operating systems and other platforms.
Building Dynamic Rich Internet Applications (RIAs) using JavaScript, Ajax, Comet, and Dojo Toolkit Learn how to build rich interactive web applications using Ajax, Asynchronous JavaScript and XML technologies. We'll explore Comet and the Dojo toolkit which has Ajax components to simplify the creation of rich web applications. Dojo provides a rich set of APIs to interact with the DOM, a client side event model, as well as rich set of client side UI components.
Developing Portable Java EE Applications with the Enterprise JavaBeans 3.1 API and Java Persistence API 2.0 Learn how to build business logic that can be invoked synchronously or asynchronously with an application server that complies with the Java EE platform. The technology in question is the efficient and robust EJB EJB3.1 framework. Learn the new robust Java Persistence API 2.0 needed to develop and deploy data-driven applications with the Java EE and Java SE platforms. Learn how the Java Persistence API allows Java SE and Java EE technology developers model database entities as POJOs (Plain Old Java Objects) and how it integrates with EJB 3.1 component services to facilitate the development of enterprise applications.
Developing Enterprise Applications with the Spring Framework Gain a clear understanding of the Spring framework. Learn the Spring’s extensive support for middle-tier functionality including persistence, remoting, management, messaging, and control flow. And of course get the new features of Spring.
Developing Rich Client Applications with Java SE 7 The demand continues to grow for secure, interactive content, applications, and services that run on a variety of clients. To simplify and speed the creation and deployment of high-impact content for a wide range of devices, learn JavaFX for GUI, a new family of products based on Java technology designed to enable consistent user experiences.
Extreme Performance: Tuning Java SE for Throughput and Latency A large family of software applications has very stringent response time or service level agreement goals. The requirements of this family of applications have traditionally been challenging for Java SE applications to meet due to garbage collection pauses. However, with advancements made to Java Virtual Machines and the introduction of Java Real-Time System (Java RTS), these stringent response time requirements can be met. This seminar will give you the knowledge and skills required to tune both Java SE and Java RTS applications.
More Than Skin Deep: JSF 2.2 Foundation and Practice An in-depth survey of JavaServer Faces (JSF) 2.2, the standard Web application framework for Java EE. The Seminar assumes no familiarity with JSF, but the material covering the new features of JSF 2.2 is used for the second half of the course. Typical JSF gotchas will also be covered in context.
Java SE 7: New Features An in-depth overview of the major updates available with the Java SE 7 release for Java professionals who are already proficient with developing Java programs by using Java SE 6 or earlier Java SE platforms.
The idea behind this post is (as its title suggests) to implement futures in a pure functional way.
More precisely, the identity monad is transformed to add state and control to it. The implementation does not make use of var's nor does it make use of the delimited continuations plugin.
Note: this post is not self contained.
Computational Features
Here are the main computational features that the implementation makes use of
// computations yield a result def result[Z]: Z => M[Z]
def shift(a__f__m_b__f___m_c: (A => M[B]) => M[C]): M[A]
Pure Functional Futures
As stated above, all we need is state and control, so we are ready for our implementation. Cells and futures (making use of cells) are implemented in a way that closely follows the implementation of Node.scala - Implementing Scalable Async IO using Delimited Continuations as presented at the Scala Days 2012.
object IdentityMonadWithOptionState extends IdentityMonadWithStateModule { type State = Option[A] }
private[imaginej] val fromMonad = IdentityMonadWithOptionState private[imaginej]type MonadModuleType = IdentityMonadWithOptionState.type
class Cell(executor: ExecutorService) { def get(): M[FutureJ[A]] = reset { shift { c => getS(()) bindM { o_a => o_a match { case Some(a) => val callable = new Callable[A] { def call(): A = { logger.info("submit c(" + a + ") ...") (c(a) run ())(o_a)._1 } } result { executor.submit(callable) } case None => sys.error("state not set") } } } bindF { a => sleep(10000); logger.info("result(" + a + ")") a } }
def set(a: A): M[Cell] = getS(()) bindM { o_a => o_a match { case Some(_) => sys.error("state already set") case None => logger.info("set " + a) setS(Some(a)) seqF { this } } } }
def m_cell(implicit executor: ExecutorService): A => M[Cell] = new Cell(executor) set (_)
type Future[A] = M[FutureJ[A]]
def future(implicit executor: ExecutorService): A => Future[A] = a => { val m__fj_a = m_cell(executor)(a) bindM { cell => cell get () } result { ((m__fj_a run ())(None))._1 } }
}
Example
Here is an example
object PureFutureExample { val logger = Logger.getLogger("") def sleep(time: Int) { Thread.sleep(round(time * random)) } object Implicits { implicit val executor = new ScheduledThreadPoolExecutor(10) } def parFuturesTest() { import Implicits.executor val monad_l = new IntFutureIdentityMonadWithOptionStateWithControl val monad_r = new IntFutureIdentityMonadWithOptionStateWithControl val future_l = monad_l.future val future_r = monad_r.future logger.info("set futures") val (m__fj_l, m__fj_r) = (future_l apply (1), future_r apply (2)) logger.info("sleep before get futures ...") sleep(12000) logger.info("get futures") val m_l = m__fj_l bindF { fj_l => fj_l.get() } val m_r = m__fj_r bindF { fj_r => fj_r.get() } logger.info("(" + ((m_l run ())(None))._1 + ", " + ((m_r run ())(None))._1 + ")") executor.shutdown() }
The idea behind this Akka Space library is, again, (as its name suggests) to implement Local Akka Spaces and Remote Akka Spaces (in another way than in the previous posts).
Note: this post is, again, self contained, so, some code similar to code of previous posts has been repeated.
I have (temporarily) given up the idea to make use of partial functions for pattern matching. On the one hand this is a pity (the { case pattern => code } idiom looks like a very appealing one to me). On the other hand, remotely the idiom comes with issues (locally it works as a charm).
In this post I make use of (less powerful) equality insead of pattern matching. Luckily, both the pingpong table and the stick table examples can elegantly be implemented using equality (the full power of pattern matching is not needed).
Note: in the previous Remote Akka Spaces post I forgot to clean up the space when space actors have finished using the space (for example, when pingers and pongers have finished using the pingpong table).
Messages
case class Put[A](a: A)
case class Reg[A](b: A)
case class PutCleanup[A](as: Vector[A])
case class RegCleanup[A](bs: Vector[A])
case class Get[A](a: A)
The case classes Put[A] and Reg[A] model messages that a space actor can send to a space.
The case classes PutCleanup[A] and RegCleanup[A] model messages that a space actor can send to a space (typically when it has finished using the space).
The case class Get[A] models messages that a space can send back to a space actor.
Space
class Space[A](spaceSystem: ActorSystem) extends Actor { val log = Logging(context.system, this)
private val pva = Agent(Vector[A]())(spaceSystem) private val rva = Agent(Vector[(A, ActorRef)]())(spaceSystem)
private def put(a: A) = atomic { _ => rva.await find { case (b, _) => a == b } match { case None => pva send (_ :+ a) log.info("" + this) case Some(r) => val (b, ar) = r rva send (_ diff Vector(r)) log.info("" + this) ar ! Get(a) } }
private def reg(b: A, ar: ActorRef) = atomic { _ => pva.await find { case a => b == a } match { case None => val r = (b, ar) rva send (_ :+ r) log.info("" + this) case Some(a) => pva send (_ diff Vector(a)) log.info("" + this) ar ! Get(a) } }
private def putCleanup(as: Vector[A]) = atomic { _ => val pv = pva.await val fpv = for { a <- pv; if (as contains a) } yield a pva send (_ diff fpv) log.info("" + this) }
private def regCleanup(bs: Vector[A]) = atomic { _ => val rv = rva.await val frv = for { r @ (b, _) <- rv; if (bs contains b) } yield r rva send (_ diff frv) log.info("" + this) }
def receive = { case Put(a: A) => put(a) case Reg(b: A) => reg(b, sender) case PutCleanup(as: Vector[A]) => putCleanup(as) case RegCleanup(bs: Vector[A]) => regCleanup(bs) case other => sys.error("space: this should never happen") } }
A space processes Put[A] and Reg[A] messages. The space has two vectors of agents
pva: a vector of (agents of) puts to be matched to regs
rva: a vector of (agents of) regs to be matched to puts
When receiving a put
when there is no matching reg, the put is added to the vector of puts
when there is a matching reg, the put is sent back to its sender
When receiving a reg
when there is no matching put, the reg is added to the vector regs
when there is a matching put, the put is sent back to its sender
When receiving a put cleanup
remaining matching puts are cleaned up
When receiving a reg cleanup
remaining matching regs are cleaned up
SpaceActor
abstract class SpaceActor[A] extends Actor { initialState()
var pf: PartialFunction[A, Unit] = _
protected def initialState(): Unit
private def get(a: A) { pf apply a }
def receive = { case Get(a: A) => get(a) case other => sys.error("space actor: this should never happen") } }
A space actor processes Get[A] messages. The space actor has a partial function. The space actor processes a message by applying its partial function to the message argument.
A space actor starts in its (to be defined) initial state.
PingPongTableApp
We are ready for a first applicationPingPongTableApp.
PingPong
sealed abstract class PingPong
case class Ping() extends PingPong
case class Pong() extends PingPong
case class KoPing() extends PingPong
case class KoPong() extends PingPong
case class OkPing() extends PingPong
case class OkPong() extends PingPong
The sealed abstract class PingPong and the case classes implementing it model the data that drive the application.
PingPongTable
import akka.actor.ActorSystem
case class PingPongTable(spaceSystem: ActorSystem) extends Space[PingPong](spaceSystem) { }
The case class PingPongTable models the pingpong table.
Pingers and Pongers
case class Pingers(pingPongTableRef: ActorRef, numberOfPingers: Int) extends SpaceActor[PingPong] { val log = Logging(context.system, this)
val pingers = for { i <- 1 to numberOfPingers } yield { context.actorOf( Props(Pinger(pingPongTableRef)), name = "pinger_" + i) }
A pinger starts in its ping state receiving a Pong from a ponger. This can either succeed, in which case he puts a Ping on the pingpong table and stays in its ping state, or fail, in which case he puts a KoPing on the pingpong table.
A ponger starts in its pong state receiving a Ping from a pinger. This can either succeed, in which case he puts a Pong on the pingpong table and stays in its pong state, or fail, in which case he puts a KoPong on the pingpong table.
The pingers supervisor creates pingers and starts in its playing state receiving a KoPing from a pinger, in which case he puts an OkPong on the pingpong table and cleans up, or an OkPing from a pongers supervisor, in which case he cleans up.
The pongers supervisor creates pongers and starts in its playing state receiving a KoPong from a ponger, in which case he puts an OkPing on the pingpong table and cleans up, or an OkPong from a pingers supervisor, in which case he cleans up.
Note: in the preStart of the pingers supervisor, a ping is put on the pingpong table.
PingPongTableApp
object PingPongTableGlobal { val pingPongTableSystem = ActorSystem( "PingPongTable", ConfigFactory.load.getConfig("pingPongTable")) }
class PingPongTableApplication extends Bootable { val pingPongTableRef = pingPongTableSystem.actorOf( Props(PingPongTable(pingPongTableSystem)), name = "pingPongTable")
We are ready for a second applicationStickTableApp.
Stick
case class Stick(i: Int)
The case class Stick models the data that drive the application.
PingPongTable
case class StickTable(spaceSystem: ActorSystem, numberOfSticks: Int) extends Space[Stick](spaceSystem) { override def preStart() { (1 to numberOfSticks) foreach { i => self ! Put(Stick(i)) } } }
The case class PingPongTable models the stick table.
Note: in the preStart of the stick table, the sticks are put on the stick table.
Hackers
case class Hackers(stickTableRef: ActorRef, numberOfSticks: Int) extends Actor { (1 to numberOfSticks) foreach { i => context.actorOf( Props(Hakker(i, numberOfSticks, stickTableRef, 4000, 4000, 5000, 8000)), name = "hacker_" + i) }
def receive: Receive = { case _ => } }
case class Hakker( n: Int, numberOfSticks: Int, stickTableRef: ActorRef, startTime: Long, thinkTime: Long, eatTime: Long, delayTime: Long) extends SpaceActor[Stick] { val log = Logging(context.system, this)
private def next(n: Int) = if (n == numberOfSticks) { 1 } else { n + 1 }
def takeLeftState() { val left = n
pf = { case l @ Stick(`left`) => { log.info("has taken " + l) takeRightState() } }
stickTableRef ! Reg(Stick(n)) }
def takeRightState() { val right = next(n)
pf = { case r @ Stick(`right`) => { log.info("has taken " + r) hack() takeLeftState() } }
A hackers supervisor creates hackers. A hacker starts in its take left state taking the Stick left to and transitioning to its take right state taking the Stick right to it.
When he has taken both sticks, he starts eating, puts back the sticks, thinks for a moment, and transitions back to its take left state.
StickTableApp
class StickTableApplication extends Bootable { val stickTableSystem = ActorSystem( "StickTable", ConfigFactory.load.getConfig("stickTable"))
val numberOfSticks = 5
val stickTableRef = stickTableSystem.actorOf( Props(StickTable(stickTableSystem, numberOfSticks)), name = "stickTable")
def startup() { }
def shutdown() { stickTableSystem.shutdown() } }
object StickTableApp { df main(args: Array[String]) = { val application = new StickTableApplication } }
The stick table app simply installs a stick table.
PingersApp and PongersApp
class HackersApplication extends Bootable { val hackersSystem = ActorSystem( "Hackers", ConfigFactory.load.getConfig("hackers"))
val stickTableRef = hackersSystem.actorFor( "akka://StickTable@127.0.0.1:2555/user/stickTable")
val numberOfSticks = 5
val hackersRef = hackersSystem.actorOf( Props(Hackers(stickTableRef, numberOfSticks)), name = "hackers")
def startup() { }
def shutdown() { hackersSystem.shutdown() } }
object HackersApp { def main(args: Array[String]) = { val application = new HackersApplication } }
The hackers app simply looks up a stick table and installs a hackers supervisor.
Configuration
//# application.conf stickTable { include "common"
akka { remote.netty.port = 2555 } }
hackers { include "common"
akka { remote.netty.port = 2556 } }
Running the HackersApp and StickTableApp
Running the apps produces something like below (in this case an immediate deadlock).
The idea behind the Remote Akka Space library is (as its name suggests) to implement remoteAkka Spaces.
Note: this post is self contained, so, some code similar to code of Akka Spaces has been repeated. The most important issue to deal with is to avoid a java.io.InvalidClassException because (partial) functions capturing variables of an outer scope have to be serialized.
This has lead to a design where (partial) functions to be applied to arguments in the space actor JVM are separated from matchers that are stored in the space JVM.
For the PingPongApp this results in a perfect solution. For the StickApp there is still an issue because the matchers themselves are (partial) functions capturing variables of an outer scope. So, the distributed version of the StickApp has been implemented in a way that cannot be parameterized over the number of sticks.
I may be missing something here. All comments are welcome.
Messages
case class Put[A](a: A)
case class Reg[A](m: PartialFunction[A, Unit])
case class Get[A](a: A)
The case classes Put[A] and Reg[A] model messages that a space actor can send to a space.
The case class Get[A] models messages that a space can send back to a space actor.
private def put(a: A) = atomic { _ => import akka.event.Logging val log = Logging(context.system, this) rva.await find { case (m, _) => m.isDefinedAt(a) } match { case None => pva send (_ :+ a) log.info("" + this) case Some(r) => val (m, ar) = r rva send (_ diff Vector(r)) log.info("" + this) ar ! Get(a) } }
private def reg(m: PartialFunction[A, Unit], ar: ActorRef) = atomic { _ => import akka.event.Logging val log = Logging(context.system, this) pva.await find { case a => m.isDefinedAt(a) } match { case None => val r = (m, ar) rva send (_ :+ r) log.info("" + this) case Some(a) => pva send (_ diff Vector(a)) log.info("" + this) ar ! Get(a) } }
def receive = { case Put(a: A) => put(a) case Reg(m) => reg(m, sender) case other => sys.error("space: this should never happen") } }
A space processes Put[A] and Reg[A] messages. The space has two vectors of agents
pva: a vector of (agents of) argument puts to be matched to matchers
rva: a queue of (agents of) matcher regs to be matched to arguments
When receiving an argument put
when there is no matching matcher reg, the argument put is added to the vector of arguments puts
when there is a matching matcher reg, the argument is sent back to its sender
When receiving a matcher reg
when there is no matching argument put, the matcher put is added to the vector of matcher regs
when there is a matching argument put, the argument is sent back to its sender
SpaceActor
import akka.actor.Actor
abstract class SpaceActor[A] extends Actor { initialState()
var pf: PartialFunction[A, Unit] = _
protected def initialState(): Unit
private def get(a: A) { pf apply a }
def receive = { case Get(a: A) => get(a) case other => sys.error("space actor: this should never happen") } }
A space actor processes Get[A] messages. The space actor has a partial function. The space actor processes a message by applying its partial function to the message argument.
A space actor starts in its (to be defined) initial state.
Local PingPongTableApp
We are ready for a first local applicationPingPongTableApp.
PingPong
sealed abstract class PingPong
case class Ping() extends PingPong
case class Pong() extends PingPong
case class FailPing() extends PingPong
case class FailPong() extends PingPong
The sealed abstract class PingPong and the case objects implementing it model the data that drive the application.
PingPongTable
import akka.actor.ActorSystem
case class PingPongTable(spaceSystem: ActorSystem) extends Space[PingPong](spaceSystem) { }
The case class PingPongTable models the pingpong table.
Pingers and Pongers
object PingPongGlobal { import akka.actor.ActorSystem val pingPongTableSystem = ActorSystem("pingPongTable") }
import akka.actor.ActorRef
case class Pingers(pingPongTableRef: ActorRef, numberOfPingers: Int) extends SpaceActor[PingPong] { import akka.actor.Props
val pingers = for { i <= 1 to numberOfPingers } yield { context.actorOf( Props(Pinger(pingPongTableRef)), name = "pinger_" + i) }
val pongMatcher: PartialFunction[PingPong, Unit] = { case Ping() => }
pingPongTableRef ! Reg(pongMatcher) }
def initialState() { pongState() } }
A pinger starts in its ping state receiving a Pong from a ponger. This can either succeed, in which case he puts Ping on the pingpong table and stays in its ping state, or fail, in which case he puts a FailPing and a FailPong on the pingpong table.
A ponger starts in its pong state receiving a Ping from a pinger. This can either succeed, in which case he puts Pong on the pingpong table and stays in its pong state, or fail, in which case he puts a FailPong and a FailPing on the pingpong table.
The pingers supervisor creates pingers and starts in its shutdown state receiving a FailPing from a pinger, in which case he cleans up.
The pongers supervisor creates pongers and starts in its shutdown state receiving a FailPong from a ponger, in which case he cleans up.
So what about a second remote applicationStickTableApp?
Changing the stick table app from local to remote is not as simple as changing the pingpong table app from local to remote because the matchers are more complex.
A hacker registers a matcher for a stick on his left or on his right, so the matcher refers to an instance variable (left or right) of the hacker.
Therefore the remote application deals with a fixed number (say, 5) of sticks.
Configuration
//# application.conf stickTable { include "common"
akka { remote.netty.port = 2555 } }
hackers { include "common"
akka { remote.netty.port = 2556 } }
Running the stick table app remotely is, again, merely a question of configuration.
Stick
sealed abstract class Stick
case class Stick1() extends Stick
case class Stick2() extends Stick
case class Stick3() extends Stick
case class Stick4() extends Stick
case class Stick5() extends Stick
The sealed abstract class Stick and the case objects implementing it model the data that drive the application.