integration of the framework akka and java ee 6 - masaryk university

30
Masaryk University Faculty of Informatics Integration of the framework Akka and Java EE 6 Bachelors thesis Tibor Bogár Brno, autumn 2013 1

Upload: others

Post on 12-Feb-2022

8 views

Category:

Documents


0 download

TRANSCRIPT

Masaryk UniversityFaculty of Informatics

Integration of the frameworkAkka and Java EE 6

Bachelors thesis

Tibor Bogár

Brno, autumn 2013

1

Announcement

I annouce, that this bachelor's thesis is my original author's work, which I created autonomosly. Every source, strand and literature, which I used or extracted in my work is properly quoted specifying entire reference on the relevant source.

Thesis supervisor: doc. RNDr. Tomáš Pitner, Ph.D.

2

Acknowledgement

Foremost, I would like to express my sincere gratitude to my advisor Mgr. Martin Švehla, for his patience, motivation and immense knowledge. His guidance helped me in the time of research and writing this thesis.

Besides my advisor, I would like to thank my thesis supervisor doc. RNDr. Tomáš Pitner, Ph.D., for his patience and tolerance.

My sincere thanks to Helena Kryštofová and whole Office for Studies for helping me with administration.

Last and not least, my mother for supporting me and making it possible to work entirely on thesis.

3

Contents

1. Introduction....................................................................................52. Context and Dependency Injection.............................................7

2.1. CDI bean characteristic....................................................................82.2. Qualifiers............................................................................................82.3. Scope...................................................................................................92.4. Injection Points..................................................................................92.5. Lose coupling with strong typing..................................................10

2.5.1. Producer methods.......................................................................102.5.2. Interceptors..................................................................................112.5.3. Decorators....................................................................................112.5.4. Events...........................................................................................112.5.5. Stereotypes...................................................................................12

3. Akka framework...........................................................................133.1. Actor Systems...................................................................................133.2. Actor Reference................................................................................143.3. State …...............................................................................................143.4. Behavior.............................................................................................153.5. Mailbox..............................................................................................153.6. Children.............................................................................................163.7. Supervisor Strategy..........................................................................163.8. When an Actor Terminates.............................................................163.9. Creating Actors.................................................................................17

3.9.1. Untyped Actor.............................................................................173.9.2. Props.............................................................................................173.9.3. Typed Actor.................................................................................18

4. Application.....................................................................................195. CDI Extension................................................................................216. Akka Modul.....…..........................................................................257. Examples in Spring and Google Guice......................................278. Conclusion......................................................................................299. Reference........................................................................................30

4

1. Introduction

The goal of this work was to make an extension for Context and Depedency Injection [1] and a modul for framework Akka [2], which allows to use design pattern Dependency Injection in Actors of framework Akka i.e. Automatization of creating Java EE components and sources in Akka Actors and creating Actors into Java EE components using anotations.

Context and Dependency Injection (CDI) framework deal with inserting dependencies and context in Java EE 6. Main advantage of this framework is to simplify access to objects and unify used services. Accessing to objects is secured throught design pattern inversion of control sometimes also called depednency injection, where we access to objects not directly through creating instancies with standard constructing methods, but our application server is managing the whole lifecycle of a corectly created class. These objects are called beans. CDI includes built-in support for several different kinds of bean, including Java EE component types as managed beans and EJB session beans.

Prior to Java EE 6, there was no clear definition of the term "bean" in the Java EE platform. Java EE 6 finally lays down that common definition in the Managed Beans specification. Managed Beans are defined as container-managed objects with minimal programming restrictions, otherwise known by the acronym POJO (Plain Old Java Object). CDI allows the container to create and destroy instances of your beans and associate them with a designated context, injecting them into other beans, using them in EL expressions, specializing them with qualifier annotations, even adding interceptors and decorators to them.

Akka framework uses Actor Model to raise the abstraction level and provide a better platform to build concurrent scalable and fault-tolerant applications. Any system that have the need for high-throughput and low latency can be easily implemented using Akka framework. Thnks to Actor Model developers musnt take care of managing threads and accesing to mutable data objects. Actors are objects which encapsulate state and behavior, they communicate exclusively by exchanging messages. In a sense, actors are the most stringent form of object-oriented programming, but it serves better to view them as persons: while modeling a solution with actors, imagine a group of people and assign sub-tasks to them, arrange

5

their functions into an organizational structure and think about how to deal with a failure and not careing for their emotional state or moral issues.

Actors form hierarchies in terms of one actor with a certain function can split up tasks into smaller more managable pieces. Every Actor which splits his task into other actors must supervise these newly created actors. It is called parental supervision. This spliting tasks into smaller and smaller ones helps us to solve complex problems and makeing them easier to work up. There may be milions of actors within one system. The exact order in which messages are processed in large systems is not controllable by the application author, so we let Akka to take care of that.

An actor object needs to be shielded from the outside in order to benefit from the actor model. Therefore, actors are represented to the outside using actor references, which are objects that can be passed around freely and without restriction. This split into inner and outer object enables transparency for all the desired operations and making impossible to look inside an actor and see its state from the outside, unless an actor publishes this information itself.

Actors communicate with oneanother by exchanging messages. An actor can recieve message from other actors or from outside the actor system and its purpouse is to process these messages. Each actor has exactly one mailbox to which all senders enqueue their messages. Messages in mailboxes are defualtly defined by FIFO queue's algorithm, but they can be also prioritized. Actors always handle the next dequeued message.

First of all we had to read and understand the uppermentioned frameworks and learn how to use them. Integrating modules are now used in many important and often used frameworks e.g. Spring and Google Guice. There is often a loss of clarity in writing new applications and therefore every developer wants the process of writing source code to be simple and a lot of things to be delegated and automatized. This simplifing of creating source codes is called convention over configuration. By decreasing the amount of decisions there is often a loss in flexibility. Our integration solution bring us simplicity but it doesnt lose much flexibility, because for example in case of creating new ActorSystem we can still use the old method of instanciating.

Work on the implementation consists of two tasks. First of all we had to create a simple application based on assigment of consultant Mr. Mgr. Martin Švehla, on which we can see the function of our CDI extension and Akka module.

The first task was to make extension for CDI framework,

6

where we had worked on automatic creating of actor classes, which were being created by the application server. We had to decide how to mark and specify the actor, which we wanted to instanciate by application server. We decide to mark the actors by annotation Named. This was easier as anotating it by annotation Qualifiers. Actors marked by annotation Named must have unique name so as application server could specify our actor, create it and insert into reference ActorRef. Thus our extension tells the server to create new reference ActorRef with our actor.

The second task was aimed to insertion of Java EE components and sources into Akka actors. In order for useing Java EE components we had to secure the creation of Java beans with actors. By creating classes, which extend UntypedActor and TypedActor, our moudle register a new bean by creating new entry in bean.xml file for server to recognise actors.

Our work should help many Java developers, those who decide to use Akka framework in their own applications. Since our work simplify creating new actors, so they musnt take care of creating ActorFactory or ActorSystem class when creating new actor and so they can use the advantages of Java EE 6 in created actros.

2. Context and Dependency Injection

CDI is the Java standard for dependency injection and contextual lifecycle management.It defines a set of rules which improves the structure of the application. This framework describes the Java EE (JSR-299) specification and it has some implementations from whose the most popular ones are Weld [3], Resin and OpenWebBeans. It simplifys services and accessing to objects by defining component model. Each component is managed by server, losely coupled and therefore is the application easily extensible and variable.Java EE componet is a bean if the lifecycle of its instancies can be managable by container defined by context model lifecycle. Bean can contain metadata, which defines its lifecycle and the interaction with other components. Bean is a source of contextual objects, whose define the logic and state of the application. These objects are called contextual bean instancies. Application container creates and deletes these instancies and it combines them with their contexts. Instancies with their context can be placed into other objects

7

including other bean instancies with same context.

2.1. CDI bean characteristicBean is almost every java class having nonparametric constructor or a constructor annotated with @Inject. This annotation tells the container to call that constructor when instatiating the bean. Managed Beans are defined as container-managed objects with minimal programming restrictions, otherwise known by the acronym POJO (Plain Old Java Object). They support a small set of basic services, such as resource injection, lifecycle callbacks and interceptors. Companion specifications, such as EJB and CDI, build on this basic model.There are three bean component models: • stateless, • stateful, • singleton.However, like a stateless or singleton model, but unlike stateful session beans, the client does not control the lifecycle of the instance by explicitly creating and destroying it. Instead, the scope of the bean determines.

A bean comprises the following attributes:• A (nonempty) set of bean types• A (nonempty) set of qualifiers• A scope• Optionally, a bean EL name• A set of interceptor bindings• A bean implementationFurthermore, a bean may or may not be an alternative.

2.2. QualifiersBeans usually acquire references to other beans via dependency injection. Any injected attribute specifies a bean type with a set of qualifiers that must be satisfied by the bean to be injected. A bean type is a user-defined class or interface. CDI never relies on string-based identifiers to determine how collaborating objects fit together. Instead, CDI uses the typing information that is already available in the Java object model, augmented using a new programming pattern, called qualifier annotations, to wire together beans, their dependencies, their interceptors and decorators, and their event consumers. Usage of XML descriptors is minimized to truly deployment-specific information.

When a bean type doesn't provide enough information for

8

the container to know which bean to inject the client must specify additional information. This additional information is provided by qualifiers. A qualifier is a user-defined annotation that is itself annotated @Qualifer. A qualifier annotation is an extension of the type system. It lets us disambiguate a type without having to fall back to string-based names. Here's an example of a qualifier annotation:

@Qualifier@Target({TYPE, METHOD, PARAMETER, FIELD})@Retention(RUNTIME)public @interface ActorQualifier {}

For each injection point, the container searches for a bean which satisfies the contract, one which has the bean type and all the qualifiers. If it finds exactly one matching bean, it injects an instance of that bean. If it doesn't, it reports an error to the user.

2.3. ScopeThe scope of a bean defines the lifecycle and visibility of its instances. The CDI context model is extensible, accommodating arbitrary scopes. However, certain important scopes are built into the specification, and provided by the container. Each scope is represented by an annotation type. If a scope is not explicitly specified, then the bean belongs to a special scope called the dependent pseudo-scope. Beans with this scope live to serve the object into which they were injected, which means their lifecycle is bound to the lifecycle of that object. It's possible to define new scopes by creating a new scope type annotation:

@ScopeType@Retention(RUNTIME)@Target({TYPE, METHOD})public @interface NewScoped{}

Every scope, to be useful, will need to implement a Context, which is very technical task so we will usually use one of CDI's built-in scopes:• @RequestScoped• @SessionScoped• @ApplicationScoped• @ConversationScoped

2.4. Injection PointsThe @Inject annotation lets us define an injection point that is injected during bean instantiation. Injection can occur via three different mechanisms. A bean can only have one injectable constructor. Dependency injection always occurs when the bean

9

instance is first instantiated by the container. Simplifying just a little, things happen in this order:1. the container calls the bean constructor (the default

constructor or the on annotated @Inject), to obtain an instance of the bean.

2. Next, the container initializes the values of all injected fields of the bean.

3. Next, the container calls all initializer methods of bean (the call order is not portable, don't rely on it).

4. Finally, the @PostConstruct method, if any, is called.

Whenever a bean or injection point does not explicitly declare a qualifier, the container assumes the qualifier @Default. From time to time, you'll need to decare an injection point without specifying a qualifier. There's a qualifier for that too. All beans have the qualifier @Any. Therefore, by explicitly specifying @Any at an injection point, you suppress the default qualifier, without otherwise restricting the beans that are eligible for injection.

2.5. Lose coupling with strong typingThe first major theme of CDI is loose coupling. These techniques, alternatives enabling deployment time polymorphism, producer methods enabling runtime polymorphism and contextual lifecycle management docoupling bean lifecycles, serve to enable loose coupling of client and server. The client is no longer tightly bound to an implementation of an interface, nor is it required to manage the lifecycle of the implementation. This approach lets stateful objects interact as if they were services.

Loose coupling makes a system more dynamic. The system can respond to change in a well-defined manner. In the past, frameworks that attempted to provide the facilities listed above invariably did it by sacrificing type safety (most notably by using XML descriptors). CDI is the first technology, and certainly the first specification in the Java EE platform, that achieves this level of loose coupling in a typesafe way.

The second major theme of CDI is strong typing. The information about the dependencies, interceptors and decorators of a bean, and the information about event consumers for an event producer, is contained in typesafe Java constructs that may be validated by the compiler.

2.5.1. Producer methodsProducer methods let us overcome certain limitations that arise

10

when a container, instead of the application, is responsible for instantiating objects. They're also the easiest way to integrate objects which are not beans into the CDI environment.

2.5.2. InterceptorsInterceptor functionality is defined in the Java Interceptors specification. CDI enhances this functionality with a more sophisticated, semantic, annotation-based approach to binding interceptors to beans. The Interceptors specification defines two kinds of interception points: business method interception, and lifecycle callback interception. In addition, the EJB specification defines timeout method interception.

2.5.3. DecoratorsInterceptors are a powerful way to capture and separate concerns which are orthogonal to the application (and type system). Any interceptor is able to intercept invocations of any Java type. This makes them perfect for solving technical concerns such as transaction management, security and call logging. However, by nature, interceptors are unaware of the actual semantics of the events they intercept. Thus, interceptors aren't an appropriate tool for separating business-related concerns.

The reverse is true of decorators. A decorator intercepts invocations only for a certain Java interface, and is therefore aware of all the semantics attached to that interface. Since decorators directly implement operations with business semantics, it makes them the perfect tool for modeling some kinds of business concerns. It also means that a decorator doesn't have the generality of an interceptor. Decorators aren't able to solve technical concerns that cut across many disparate types. Interceptors and decorators, though similar in many ways, are complementary. Let's look at some cases where decorators fit the bill.

2.5.4. EventsDependency injection enables loose-coupling by allowing the implementation of the injected bean type to vary, either a deployment time or runtime. Events go one step further, allowing beans to interact with no compile time dependency at all. Event producers raise events that are delivered to event observers by the container.This basic schema might sound like the familiar observer/observable pattern, but there are a couple of twists:• not only are event producers decoupled from observers;

11

observers are completely decoupled from producers, • observers can specify a combination of "selectors" to narrow the set of event notifications they will receive, and • observers can be notified immediately, or can specify that delivery of the event should be delayed until the end of the current transaction.

The CDI event notification facility uses more or less the same typesafe approach that we've already seen with the dependency injection service.

2.5.5. StereotypesThe CDI specification defines a stereotype as follows:„In many systems, use of architectural patterns produces a set of recurring bean roles. Astereotype allows a framework developer to identify such a role and declare some common metadata for beans with that role in a central place.“So a stereotype specify that it encapsulate any combination of a default scope and a set of interceptor bindings. A bean may declare zero, one or multiple stereotypes. Stereotype annotations may be applied to a bean class or producer method or field. A stereotype is an annotation, annotated @Stereotype, that packages several other annotations. For instance, the following stereotype identifies action classes in some MVC framework:

@Stereotype@Retention(RUNTIME)@Target(TYPE)…public @interface Action {}

We use the stereotype by applying the annotation to a bean.@Actionpublic class LoginAction{ … }

Java EE 5 already introduced some limited support for dependency injection, in the form of component environment injection. A component environment resource is a Java EE component, for example a JDBC datasource, JMS queue or topic, JPA persistence context, remote EJB or web service.

Naturally, there is now a slight mismatch with the new style of dependency injection in CDI. Most notably, component environment injection relies on string-based names to qualify ambiguous types, and there is no real consistency as to the nature of the names (sometimes a JNDI name, sometimes a persistence unit name, sometimes an EJB link, sometimes a nonportable "mapped

12

name"). Producer fields turned out to be an elegant adaptor to reduce all this complexity to a common model and get component environment resources to participate in the CDI system just like any other kind of bean. Fields have a duality in that they can both be the target of Java EE component environment injection and be declared as a CDI producer field. Therefore, they can define a mapping from a string-based name in the component environment, to a combination of type and qualifiers used in the world of typesafe injection. We call a producer field that represents a reference to an object in the Java EE component environment a resource.

Resource refers to any of the following kinds of object which might be available in Java EE component enviroment: • JDBC Datasources, JMS Queues, Topics and

ConnectionFactorys, JavaMail Sessions and other transactional resources including JCA connectors,

• JPA EntityManagers and EntityManagerFactorys,• remote EJBs, and• web servicesWe declare a resource by annotating a producer field with a component environment injection annotation:@Resource, @EJB, @PersistenceContext, @PersistenceUnit or @WebServiceRef.

3. Akka framework

Actors were defined in the 1973 paper by Carl Hewitt but have been popularized by the Erlang language, and used for example at Ericsson with great success to build highly concurrent and reliable telecom systems.

Akka uses the Actor Model to raise the abstraction level and provide a better platform to build correct concurrent and scalable applications. For fault-tolerance it adopts the “Let it crash” model which has been used with great success in the telecom industry to build applications that self-heals, systems that never stop. Actors also provides the abstraction for transparent distribution and the basis for truly scalable and fault-tolerant applications. Akka is Open Source and available under the Apache 2 License.

3.1. Actor SystemsActors are objects which encapsulate state and behavior, they communicate by exchanging messages. These messages are placed

13

into the recipient’s mailbox. In a sense, actors are the most stringent form of object-oriented programming, but it serves better to view them as persons. While modeling a solution with actors, imagine a group of people and assign sub-tasks to them, arrange their functions into an organizational structure and think about how to escalate failure.

An ActorSystem is typicaly a large structure that will allocate many threads. Actors in this system naturally form hierarchies. One actor, which is to oversee a certain function in the program might want to split up its task into smaller, more manageable pieces. For this purpose it starts child actors which it supervises. Actor systems beahve so that tasks are split up and delegated until they become small enough to be handled in one piece. In doing so, not only is the task itself clearly structured, but the resulting actors can be reasoned about in terms of which messages they should process, how they should react normally and how failure should be handled. If one actor does not have the means for dealing with a certain situation, it sends a corresponding failure message to its supervisor, asking for help. The recursive structure then allows to handle failure at the right level.

3.2. Actor ReferenceAs detailed below, an actor object needs to be shielded from the outside in order to benefit from the actor model. Therefore, actors are represented to the outside using actor references, which are objects that can be passed around freely and without restriction. This split into inner and outer object enables transparency for all the desired operations: restarting an actor without needing to update references elsewhere, placing the actual actor object on remote hosts, sending messages to actors in completely different applications. But the most important aspect is that it is not possible to look inside an actor and get hold of its state from the outside, unless the actor unwisely publishes this information itself.

3.3. StateActor objects will typically contain some variables which reflect possible states the actor may be in. This can be an explicit state machine (e.g. using the fsm-scala module), or it could be a counter, set of listeners, pending requests, etc. These data are what make an actor valuable, and they must be protected from corruption by other actors. The good news is that Akka actors conceptually each have their own light-weight thread, which is completely shielded from the rest of the system. This means that instead of having to

14

synchronize access using locks you can just write your actor code without worrying about concurrency at all. Behind the scenes Akka will run sets of actors on sets of real threads, where typically many actors share one thread, and subsequent invocations of one actor may end up being processed on different threads. Akka ensures that this implementation detail does not affect the single-threadedness of handling the actor’s state.

3.4. BehaviorEvery time a message is processed, it is matched against the current behavior of the actor. Behavior means a function which defines the actions to be taken in reaction to the message at that point in time, say forward a request if the client is authorized, deny it otherwise. This behavior may change over time, e.g. because different clients obtain authorization over time, or because the actor may go into an “out-of-service” mode and later comeback. These changes are achieved by either encoding them in state variables which are read from the behavior logic, or the function itself may be swapped out at runtime, see the become and unbecome operations. However, the initial behavior defined during construction of the actor object is special in the sense that a restart of the actorwill reset its behavior to this initial one.

3.5. MailboxAn actor’s purpose is the processing of messages, and these messages were sent to the actor from other actors (or from outside the actor system). The piece which connects sender and receiver is the actor’s mailbox: each actor has exactly one mailbox to which all senders enqueue their messages. Enqueuing happens in the time-order of send operations, which means that messages sent from different actors may not have a defined order at runtime due to the apparent randomness of distributing actors across threads. Sending multiple messages to the same target from the same actor, on the other hand, will enqueue them in the same order.

There are different mailbox implementations to choose from, the default being a FIFO: the order of the messages processed by the actor matches the order in which they were enqueued. This is usually a good default, but applications may need to prioritize some messages over others. In this case, a priority mailbox will enqueue not always at the end but at a position as given by the message priority, which might even be at the front. While using such a queue, the order of messages processed will naturally be defined by the

15

queue’s algorithm and in general not be FIFO. An important feature in which Akka differs from some other

actor model implementations is that the current behavior must always handle the next dequeued message, there is no scanning the mailbox for the next matching one. Failure to handle a message will typically be treated as a failure, unless this behavior is overridden.

3.6. ChildrenEach actor is potentially a supervisor: if it creates children for delegating sub-tasks, it will automatically supervise them. The list of children is maintained within the actor’s context and the actor has access to it. Modifications to the list are done by creating (context.actorOf(...)) or stopping (context.stop(child)) children and these actions are reflected immediately. The actual creation and termination actions happen behind the scenes in an asynchronous way, so they do not “block” their supervisor.

3.7. Supervisor StrategyThe final piece of an actor is its strategy for handling faults of its children. Fault handling is then done transparently by Akka, some predefined strategies for each incoming failure. As this strategy is fundamental to how an actor system is structured, it cannot be changed once an actor has been created.Considering that there is only one such strategy for each actor, this means that if different strategies apply to the various children of an actor, the children should be grouped beneath intermediate supervisors with matching strategies, preferring once more the structuring of actor systems according to the splitting of tasks into sub-tasks.

3.8. When an Actor TerminatesOnce an actor terminates, i.e. fails in a way which is not handled by a restart, stops itself or is stopped by its supervisor, it will free up its resources, draining all remaining messages from its mailbox into the system’s “dead letter mailbox” which will forward them to the EventStream as DeadLetters. The mailbox is then replaced within the actor reference with a system mailbox, redirecting all new messages to the EventStream as DeadLetters. This is done on a best effort basis, though, so do not rely on it in order to construct “guaranteed delivery”.The reason for not just silently dumping the messages was inspired by our tests: we register the TestEventListener on the event bus to which the dead letters are forwarded, and that will log a warning

16

for every dead letter received—this has been very helpful for deciphering test failures more quickly. It is conceivable that this feature may also be of use for other purposes.

3.9. Creating ActorsAn actor system is typically started by creating actors beneath the guardian actor using theActorSystem.actorOf method and then using ActorContext.actorOf from within the created actors to spawn the actor tree. These methods return a reference to the newly created actor. Each actor has direct access (through its ActorContext) to references for its parent, itself and its children. These references may be sent within messages to other actors, enabling those to reply directly.One of the possibilities how a class can became actor class is by extending abstract class UntypedActor and implementing onRecieve method or by extending final class TypedActor.

3.9.1. Untyped Actor creationActors in Java are implemented by extending the UntypedActor class and implementing the onReceive method. This method takes the message as a parameter.

import akka.actor.UntypedActor;import akka.event.Logging;import akka.event.LoggingAdapter;public class MyUntypedActor extends UntypedActor {

LoggingAdapter log = Logging.getLogger(getContext().system(), this);

public void onReceive(Object message) throws Exception {if (message instanceof String) {

log.info("Received String message: {}", message);

getSender().tell(message, getSelf());} else

unhandled(message);}

}

3.9.2. PropsProps is a configuration class to specify options for the creation of actors, think of it as an immutable and thus freely shareable recipe for creating an actor including associated deployment information (e.g. which dispatcher to use, see more below). Here are some examples of how to create a Props instance.

17

import akka.actor.Props;import akka.japi.Creator;static class MyActorC implements Creator<MyActor> {

@Override public MyActor create() {return new MyActor("...");

}}Props props1 = Props.create(MyUntypedActor.class);Props props2 = Props.create(MyActor.class, "...");Props props3 = Props.create(new MyActorC());

The second line shows how to pass constructor arguments to the Actor being created. The presence of a matching constructor is verified during construction of the Props object, resulting in an IllegalArgumentEception if no or multiple matching constructors are found. The third line demonstrates the use of a Creator. The creator class must be static, which is verified during Props construction. The type parameter’s upper bound is used to determine the produced actor class, falling back to Actor if fully erased. An example of a parametric factory could be:

static class ParametricCreator<T extends MyActor> implements Creator<T> {

@Override public T create() {// ... fabricate actor here}

}

3.9.3. Typed Actors creationAkka Typed Actors is an implementation of the Actieve Objects pattern. Typed Actors consist of 2 “parts”, a public interface and an implementation. The advantage of Typed Actors vs. Actors is that with TypedActors you have a static contract, and don’t need to define your own messages, the downside is that it places some limitations on what you can do and what you can’t, i.e. you can’t use become/unbecome. Typed Actors are implemented using JDK Proxies which provide a pretty easy-worked API to intercept method calls. Just as with regular Akka Untyped Actors, Typed Actors process one call at a time.

Typed actors are nice for bridging between actor systems (the “inside”) and non-actor code (the “outside”), because they allow you to write normal OO-looking code on the outside. Think of them like doors: their practicality lies in interfacing between private sphere and the public, but you don’t want that many doors inside your house. A bit more background: TypedActors can very easily be abused as RPC, and that is an abstraction which is wellknown to be leaky. Hence TypedActors are not what we think of first when we talk about making highly scalable concurrent software easier to

18

write correctly. They have their niche, use them sparingly.

To create a Typed Actor you need to have one or more interfaces, and one implementation.

import akka.actor.TypedActor;import akka.actor.*;import akka.japi.*;import akka.dispatch.Futures;import scala.concurrent.Await;import scala.concurrent.Future;import scala.concurrent.duration.Duration;import java.util.concurrent.TimeUnit;

public interface Squarer {// typed actor iface methods ...}

class SquarerImpl implements Squarer {private String name;public SquarerImpl() {

this.name = "default";}public SquarerImpl(String name) {

this.name = name;}// typed actor impl methods ...

}

The most trivial way of creating a Typed Actor instance of our Squarer:

Squarer mySquarer = TypedActor.get(system).typedActorOf(new TypedProps<SquarerImpl>(Squarer.class, SquarerImpl.class));

First type is the type of the proxy, the second type is the type of the implementation. If you need to call a specific constructor you do it like this:

Squarer otherSquarer = TypedActor.get(system).typedActorOf(new TypedProps<SquarerImpl>(Squarer.class,

new Creator<SquarerImpl>() {public SquarerImpl create() { return new SquarerImpl("foo"); }}),"name");

4. Application

Our application for presentation of our integration runs on Glassfish server. It is a classic Maven Enterprise application consisting of three modules. One module is for the logic of the application and the other module is a web application with simple JSP pages and servlet for interaction as a presentation layer. Third module is just

19

enterprise archive (EAR), which is used for packageing one or more modules into a single archive so that the deployment of the various modules onto an application server happens simultaneously and coherently. It also contains XML files called deployment descriptors which describe how to deploy the modules. Application gets a number from input and sums it to a list of numbers. The initial list consist of three numbers from one to three. Application is designed to use Java EE komponets and Akka framework.

It consist of the following classes: SummingSingleton, Web, SumActor, ListHandler, LogActor.

SummingSingleton class, starts itself on the startup of the application by makeing only one instance of itself and never creates m ore instancies. This feature is secured by annotations @Startup and @Singleton. This class initialize actros Actor and Log and creates class ListHandler. SummingSingleton also manages summing users input with our list of numbers from ListHandler.

Next class is Web servlet, whitch responds to requirements from adjusted Glassfish server. User inputs a number into the JSP pages. Servlet process this number and sends it to class SumActor.After succesful summing of this number this operation will be loged and server outputs our list with numbers sumed by our input number. JSP page with showing output consists also of a return button to inputing another number.

SumActor class manages summing a number into the list of numbers. Always when this class gets a number it updates its list of numbers from ListHandler class and uses static method sum from SummingSingleton class. This method has two parameters. The first parameter is te current list in ListHandler type and the second is a number which has to be summed. This method returns a list of numbers of ListHandler type with updated summed numbers. To every number in the list will be summed the user input number. This class extends UntypedActor class, implements onRecive method and therefor is an actror class.

ListHandler is a class with only one attribute, list of numbers, which

20

it can modify with methods of this class. It contains a default constructor without parametersa and get, set methods for list of numbers attribute. ListHandler is annotated as @Stateless.

LogActor class is an actor class, whereas extending UntypedActor class from Akka framework. This class has to log every summing operation performed on list. After every successful summing SumActor class sends a message to LogActor class, which logs with Logging class from Akka framework. Another option would be to use SLF4J.

Following picture represents how the classes communicate.

Adding our class CDIExtension, which implements Extension class, this application musnt create its own ActorSystem when a developer wants to create an actor, but the ActorSystem is created by our extension.

5. CDI extension

The third theme of CDI is integration. The CDI services are integrated into the very core of the Java EE platform. Even EJB

21

session beans can take advantage of the dependency injection, event bus, and contextual lifecycle management that CDI provides.

CDI is also designed to work in concert with technologies outside of the platform by providing integration points into the Java EE platform via an SPI. This SPI positions CDI as the foundation for a new ecosystem of portable extensions and integration with existing frameworks and technologies. The CDI services will be able to reach a diverse collection of technologies, such as business process management (BPM) engines, existing web frameworks and de facto standard component models. Of course, The Java EE platform will never be able to standardize all the interesting technologies that are used in the world of Java application development, but CDI makes it easier to use the technologies which are not yet part of the platform seamlessly within the Java EE environment.

We're about to see how to take full advantage of the Java EE platform in an application that uses CDI. We'll also briefly meet a set of SPIs that are provided to support portable extensions to CDI. You might not ever need to use these SPIs directly, but don't take them for granted. You will likely be using them indirectly, every time you use a third-party extension, such as Seam.

Portable ExtensionPortability is one of greatest advantages of the Java platform. It represents the concept that from one application to another, from one application-server vendor to another, and from one job to another, knowledge is freely transferable; the same skills, technologies, and designs can be used with assurance that there are always multiple choices for business solutions. Portable Extensions are usable on any Servlet container, application-server, or Java runtime; in a sense, learn once, run anywhere - the same promise that Java guarantees.

CDI is intended to be a foundation for frameworks, extensions and integration with other technologies. Therefore, CDI exposes a set of SPIs for the use of developers of portable extensions to CDI. A portable extension may integrate with the container by:

• Providing its own beans, interceptors and decorators to the container

• Injecting dependencies into its own objects using the dependency injection service

• Providing a context implementation for a custom scope• Augmenting or overriding the annotation-based metadata

with metadata from some other source

22

Creating an ExtensionThe first step in creating a portable extension is to write a class that implements Extension. This marker interface does not define any methods, but it's needed to satisfy the requirements of Java SE's service provider architecture.

import javax.enterprise.inject.spi.Extension;

class MyExtension implements Extension { ... }

Next, we need to register our extension as a service provider by creating a file named META-INF/services/javax.enterprise.inject.spi.Extension, which contains the name of our extension class: org.mydomain.extension.MyExtension

Container lifecycle eventsDuring the initialization process, the container fires a series of events, including:• BeforeBeanDiscovery• ProcessAnnotatedType• ProcessInjectionTarget and ProcessProducer• ProcessBean and ProcessObserverMethod• AfterBeanDiscovery• AfterDeploymentValidation

In fact, the extension can do a lot more than just observe. The extension is permitted to modify the container's metamodel and more. Here's a very simple example:

class MyExtension implements Extension {<T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat){//tell the container to ignore the type if it is annotated @Ignoreif ( pat.getAnnotatedType().isAnnotionPresent(Ignore.class) )

pat.veto();}}

The observer method may inject a BeanManager.

<T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat, BeanManager beanManager) { ... }

The BeanManager objectThe nerve center for extending CDI is the BeanManager object. The

23

BeanManager interface lets us obtain beans, interceptors, decorators, observers and contexts programmatically. Any bean or other Java EE component which supports injection can obtain an instance of BeanManager via injection:

@Inject BeanManager beanManager;

Java EE components may obtain an instance of BeanManager from JNDI by looking up the name java:comp/BeanManager. Any operation of BeanManager may be called at any time during the execution of the application.

public interface BeanManager {public Object getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx);public Object getInjectableReference(InjectionPoint ij, CreationalContext<?> ctx);public <T> CreationalContext<T> createCreationalContext(Contextual<T> contextual);public Set<Bean<?>> getBeans(Type beanType, Annotation... qualifiers);public Set<Bean<?>> getBeans(String name);public Bean<?> getPassivationCapableBean(String id);public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans);public void validate(InjectionPoint injectionPoint);public void fireEvent(Object event, Annotation... qualifiers);public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers);public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers);public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings);public boolean isScope(Class<? extends Annotation> annotationType);public boolean isNormalScope(Class<? extends Annotation> annotationType);public boolean isPassivatingScope(Class<? extends Annotation> annotationType);public boolean isQualifier(Class<? extends Annotation> annotationType);public boolean isInterceptorBinding(Class<? extends Annotation> annotationType);public boolean isStereotype(Class<? extends Annotation> annotationType);public Set<Annotation> getInterceptorBindingDefinition(Class<? extends Annotation> bindingType);public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype);public Context getContext(Class<? extends Annotation> scopeType);public ELResolver getELResolver();public ExpressionFactory wrapExpressionFactory(ExpressionFactory expressionFactory);public <T> AnnotatedType<T> createAnnotatedType(Class<T> type);public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type);

}

The Bean interfaceInstances of the interface Bean represent beans. There is an instance of Bean registered with the BeanManager object for every bean in the application. There are even Bean objects representing interceptors, decorators and producer methods.

The Bean interface makes it possible for a portable extension to provide support for new kinds of beans, beyond those defined by

24

the CDI specification. For example, we could use the Bean interface to allow objects managed by another framework to be injected into beans.

public interface Bean<T> extends Contextual<T> {public Set<Type> getTypes();public Set<Annotation> getQualifiers();public Class<? extends Annotation> getScope();public String getName();public Set<Class<? extends Annotation>> getStereotypes();public Class<?> getBeanClass();public boolean isAlternative();public boolean isNullable();public Set<InjectionPoint> getInjectionPoints();

}

The InjectionTarget interface The first thing that a framework developer is going to look for in the portable extension SPI is a way to inject CDI beans into objects which are not under the control of CDI. The InjectionTarget interface makes this very easy.

The Context interfaceThe Context interface supports addition of new scopes to CDI, or extension of the built-in scopes to new environments.

public interface Context {public Class<? extends Annotation>

getScope();public <T> T get(Contextual<T> contextual,

CreationalContext<T> creationalContext);

public <T> T get(Contextual<T> contextual);boolean isActive();

}

For example, we might implement Context to add a business process scope to CDI, or to add support for the conversation scope to an application that uses Wicket.

6. Akka module

Akka is very modular and consists of several JARs containing different features.

• akka-actor – Classic Actors, Typed Actors, IO Actor etc. • akka-agent – Agents, integrated with Scala STM • akka-camel – Apache Camel integration

25

• akka-cluster – Cluster membership management, elastic routers.

• akka-kernel – Akka microkernel for running a bare-bones mini application server

• akka-osgi – base bundle for using Akka in OSGi containers, containing the akka-actor classes

• akka-osgi-aries – Aries blueprint for provisioning actor systems

• akka-remote – Remote Actors • akka-slf4j – SLF4J Logger (event bus listener) • akka-testkit – Toolkit for testing Actor systems • akka-zeromq – ZeroMQ integration

In addition to these stable modules there are several which are on their way into the stable core but are still marked “experimental” at this point. This does not mean that they do not function as intended, it primarily means that their API has not yet solidified enough in order to be considered frozen. You can help accelerating this process by giving feedback on these modules on our mailing list.

• akka-channels-experimental – Typed Channels on top of untyped Actors, using Scala 2.10 macros

• akka-contrib – an assortment of contributions which may or may not be moved into core modules.

The filename of the actual JAR is for example akka-actor_2.10-2.3-SNAPSHOT.jar (and analog for the other modules).

Microkernel

The purpose of the Akka Microkernel is to offer a bundling mechanism so that you can distribute an Akka application as a single payload, without the need to run in a Java Application Server or manually having to create a launcher script. To run an application with the microkernel you need to create a Bootable class that handles the startup and shutdown the application.Put your application jar in the deploy directory to have it automatically loaded. To start the kernel use the scripts in the bin directory, passing the boot classes for your application

Akka ExtensionsIf you want to add features to Akka, there is a very elegant, but powerful mechanism for doing so. It’s called Akka Extensions and is comprised of 2 basic components: an Extension and an

26

ExtensionId. Extensions will only be loaded once per ActorSystem, which will be managed by Akka. You can choose to have your Extension loaded on-demand or at ActorSystem creation time through the Akka configuration. Details on how to make that happens are below, in the “Loading from Configuration” section.

7. Examples in Spring and Google Guice

7.1 Spring and integracion framevorkov AkkaAkkas integration with the Spring Framework supplies the Spring way of using the Typed Actor Java API and for CamelService configuration for Spring applications. It uses Spring’s custom namespaces to create Typed Actors, supervisor hierarchies and a CamelService in a Spring environment.

Example how to create Actors with the Spring framework: <akka:untyped-actor id="myActor" implementation="com.biz.MyActor" scope="singleton" autostart="false" depends-on="someBean"> <property name="aProperty" value="somePropertyValue"/> <property name="aDependency" ref="someBeanOrActorDependency"/></akka:untyped-actor>

Supported scopes are singleton and prototype. Dependencies and properties are set with Springs <property/> element. A dependency can be either a <akka:untyped-actor/> or a regular <bean/>.Get the Actor from the Spring context:

ApplicationContext context = new ClassPathXmlApplicationContext("akka-spring-config.xml");ActorRef actorRef =(ActorRef)context.getBean("myActor");

7.2 Google Guice and integracion framevorkov AkkaAkka Actors are strictly enforced to be instantiated in a certain way. First of all, Akka Actors are wrapped in an ActorRef. This reference has no reference to the underlying Actor type. An ActorRef is an ActorRef is an ActorRef. So to differentiate them we must use annotations. Not wanting to make a new annotation for each, but with the provided @Named annotation. This leads to a injection of:

class WeaveCompiler @Inject() ( @Named("WeaveActor") val weaveActor:ActorRef ) {

27

That satisfies the first half of the binding:bind(classOf[ActorRef].annotatedWith( Names.named("WeaveActor") )

But now we need our ActorRef. We can't let Guice do it for us since we have an Actor and it needs an ActorRef. We use a provider. .toProvider( new TypeLiteral[ActorProvider[WeaveActor]](){})

So TypeLiteral is provided by Guice and takes care of that type. WeaveActor is an Actor that extends akka.actor.Actorimport com.google.inject._import akka.actor._

class ActorProvider[T <: Actor] @Inject() ( val m:TypeLiteral[T], val injector:Injector ) extends Provider[ActorRef] { def get = { Actor.actorOf( injector.getInstance( Key.get( m ) ) ).start }}

Because of how akka actors works the Actor object must be created inside a call to actorOf. The provider gets the TypeLiteral for the actor injected with the Injector from Guice. Then it uses those to get an instance of the Actor from the Injector inside the call to actorOf. Then it starts the actor and returns the ActorRef.

28

8. Conclusion

All in all, the purpouse of this work was to make it easier to create actors and allowing them to use Java EE 6 componets inside of actor classes. I hope that this integration helps to develop large scaleable applications which will last and work properly for some time. Our integration consists of two parts, which together making it possible to use Akka and Java together easier than before. The portable extension allows Java to create Akkas actors easier and the Akka module allows actors to use Java components.

Now we see how Akka framework can be integrated into Java EE and we can build applications using this integration. Moreover, not only we can use our integration, but if we understand the extension, we can integrate any framework with Java EE just by creating own extension and modify it so as it will behave as we need. As it is written in Weld Reference [4] „Context and Dependency was created to be a foundation for frameworks, extensions and integration with other technologies.“ so the CDI exposes with a set of developer-friendly SPIs. By experimenting with portable extensions we can manage the application container and its beans so we can integrate with any third-party framework.

However using our work will result in slightly increasing time spent when creating actors, I believe that everyone who will read this thesis will understand the way of creating integrations with Java and will be able to create some when needed with any other framework. Understanding the way how beans are injected and how we can change their behaviour is much more worth than just useing some code to make developement easier. Every integration is in some way similar to some already created one. They have common the connecting of two or more functionalities. So nowadays it isn't hard to even find other integrations like this one and modify it to work with your own application.

29

9. Reference

[1] King Gavin, JSR 299: Contexts and Dependency Injection for the JavaTM EE platform [online], 10.12.2009 [cit. 30.12.2013]. Available on: <https://jcp.org/en/jsr/detail?id=299/>

[2] Akka Java Documentation [online] 23.10.2013 [cit. 30.12.2013]. Available on: <http://akka.io/docs/>

[3] King Gavin, Muir Pete, Allen Dan, Allen David, [online], Weld Reference, [cit 30.12.2013]. Available on: < http://weld.cdi-spec.org/documentation/>

30