This repository is private.
All pages are served over SSL and all pushing and pulling is done over SSH.
No one may fork, clone, or view it unless they are added as a member.
Every repository with this icon (
) is private.
Every repository with this icon (
This repository is public.
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
Every repository with this icon (
scala-otp / component
| name | age | message | |
|---|---|---|---|
| .. | |||
| |
Makefile | Thu Aug 21 04:32:23 -0700 2008 | |
| |
README | Fri Oct 10 03:48:45 -0700 2008 | |
| |
pom.xml | Mon Feb 16 04:40:33 -0800 2009 | |
| |
src/ | Wed Feb 18 03:47:38 -0800 2009 | |
| |
testng.xml | Thu Oct 09 01:15:09 -0700 2008 |
component/README
This package implements asynchronous components, also known as Active Objects. Each component is a GenericServer that is
managed by a Supervisor, either in isolation or as part of a supervisor hierarchy/tree. The components creation is based
on dynamic proxies and the component has to be build up by an interface (trait) and a regular Scala class as
implementation. Each component is instantiated through a factory.
Here is a simple example of a component that is using default Supervisor management (which among other things mean that
it is not part of a hierarchy). We start with the component interface and implementation.
trait Foo {
def foo(msg: String): String
@oneway def bar(msg: String)
}
class FooImpl extends Foo {
def foo(msg: String): String = { println("foo: " + msg); msg }
def bar(msg: String) = println("bar: " + msg)
}
Now let's instantiate this component. The integer 100 specifies the time interval an (asynchronous) invocation should
have before timing out.
val foo = ActiveObject.newInstance[Foo](classOf[Foo], new FooImpl, 1000)
Now we can use this component as any regular instance of Foo. With the difference that:
* All invocations are asynchronous
* The default scheme is that all invocations are based on a Future waiting for the return value
* If a method is marked by the @scala.actors.annotation.oneway annotation then it return immediately
* The component is a fault-tolerant GenericServer managed by a Supervisor
foo.foo("foo ")
foo.bar("bar ") // returns immediately since annotated with @oneway
Now, if I would like to have more control over the Supervisor configuration and/or want to compose different components
into supervisor hierarchies, then I can use another factory method along with a method called 'start' that allows you to
pass in a Supervisor configuration.
Here is a full example:
trait Foo {
def foo(msg: String): String
@oneway def bar(msg: String)
}
class FooImpl extends Foo {
val bar: Bar = new BarImpl
def foo(msg: String): String = { println("foo: " + msg); msg }
def bar(msg: String) = bar.bar(msg)
}
trait Bar {
def bar(msg: String)
}
class BarImpl extends Bar {
def bar(msg: String) = println("bar: " + msg)
}
First create a proxy (GenericServer).
val fooProxy = new ActiveObjectProxy(new FooImpl, 1000)
val barProxy = new ActiveObjectProxy(new BarImpl, 1000)
Then configure the GenericServer(s) (this method takes a list of GenericServer configurations) by passing the proxy's
server. This configuration is passed into the 'supervise' method which also starts up the Supervisor which starts up all
GenericServer's according to their configurations before returning the Supervisor instance (which can be used for later
management).
val supervisor =
ActiveObject.supervise(
RestartStrategy(AllForOne, 3, 100),
Component(
fooProxy,
LifeCycle(Permanent, 100)) ::
Component(
barProxy,
LifeCycle(Permanent, 100))
:: Nil)
Create and use the components as usual.
val foo = ActiveObject.newInstance[Foo](classOf[Foo], fooProxy)
val bar = ActiveObject.newInstance[Bar](classOf[Bar], barProxy)
foo.foo("foo ")
bar.bar("bar ")
That pretty much sums it up. Try it out and send suggestions, improvements, patches etc. to jonas AT jonasboner DOT com.







