├── project └── build.properties ├── activator.properties ├── .gitignore ├── LICENSE ├── src └── main │ └── java │ └── HelloAkka.java └── tutorial └── index.html /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.1 2 | -------------------------------------------------------------------------------- /activator.properties: -------------------------------------------------------------------------------- 1 | name=hello-akka-java8 2 | title=Hello Akka (Java 8) 3 | description=This simple Akka application uses Java 8 and Lambdas for a concise Reactive programming model with Actors. 4 | tags=akka,java,java8 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *# 2 | *.iml 3 | *.ipr 4 | *.iws 5 | *.pyc 6 | *.tm.epoch 7 | *.vim 8 | *-shim.sbt 9 | .idea/ 10 | /project/plugins/project 11 | project/boot 12 | target/ 13 | /logs 14 | .cache 15 | .classpath 16 | .project 17 | .settings -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 Typesafe, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /src/main/java/HelloAkka.java: -------------------------------------------------------------------------------- 1 | import akka.actor.*; 2 | import akka.japi.pf.ReceiveBuilder; 3 | import scala.PartialFunction; 4 | import scala.concurrent.duration.Duration; 5 | import scala.runtime.BoxedUnit; 6 | 7 | import java.io.Serializable; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class HelloAkka { 11 | public static class Greet implements Serializable { 12 | public static final long serialVersionUID = 1; 13 | } 14 | 15 | public static class WhoToGreet implements Serializable { 16 | public static final long serialVersionUID = 1; 17 | public final String who; 18 | public WhoToGreet(String who) { 19 | this.who = who; 20 | } 21 | } 22 | 23 | public static class Greeting implements Serializable { 24 | public static final long serialVersionUID = 1; 25 | public final String message; 26 | public Greeting(String message) { 27 | this.message = message; 28 | } 29 | } 30 | 31 | public static class Greeter extends AbstractActor { 32 | String greeting = ""; 33 | 34 | public Greeter() { 35 | receive(ReceiveBuilder. 36 | match(WhoToGreet.class, message -> greeting = "hello, " + message.who). 37 | match(Greet.class, message -> sender().tell(new Greeting(greeting), self())). 38 | build()); 39 | } 40 | } 41 | 42 | public static void main(String[] args) { 43 | // Create the 'helloakka' actor system 44 | final ActorSystem system = ActorSystem.create("helloakka"); 45 | 46 | // Create the 'greeter' actor 47 | final ActorRef greeter = system.actorOf(Props.create(Greeter.class), "greeter"); 48 | 49 | // Create the "actor-in-a-box" 50 | final Inbox inbox = Inbox.create(system); 51 | 52 | // Tell the 'greeter' to change its 'greeting' message 53 | greeter.tell(new WhoToGreet("akka"), ActorRef.noSender()); 54 | 55 | // Ask the 'greeter for the latest 'greeting' 56 | // Reply should go to the "actor-in-a-box" 57 | inbox.send(greeter, new Greet()); 58 | 59 | // Wait 5 seconds for the reply with the 'greeting' message 60 | Greeting greeting1 = (Greeting) inbox.receive(Duration.create(5, TimeUnit.SECONDS)); 61 | System.out.println("Greeting: " + greeting1.message); 62 | 63 | // Change the greeting and ask for it again 64 | greeter.tell(new WhoToGreet("typesafe"), ActorRef.noSender()); 65 | inbox.send(greeter, new Greet()); 66 | Greeting greeting2 = (Greeting) inbox.receive(Duration.create(5, TimeUnit.SECONDS)); 67 | System.out.println("Greeting: " + greeting2.message); 68 | 69 | // after zero seconds, send a Greet message every second to the greeter with a sender of the GreetPrinter 70 | ActorRef greetPrinter = system.actorOf(Props.create(GreetPrinter.class)); 71 | system.scheduler().schedule(Duration.Zero(), Duration.create(1, TimeUnit.SECONDS), greeter, new Greet(), system.dispatcher(), greetPrinter); 72 | } 73 | 74 | public static class GreetPrinter extends AbstractActor { 75 | @Override public PartialFunction receive() { 76 | return ReceiveBuilder. 77 | match(Greeting.class, message -> System.out.println(message.message)). 78 | build(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tutorial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello Akka Java 8 4 | 5 | 6 | 7 |
8 |

You've just created a simple Akka application! Now lets explore the code and make some changes.

9 |

10 | In short, Akka is a toolkit and runtime for building highly concurrent, 11 | distributed, and fault-tolerant event-driven applications on the JVM. Akka can be used with both Java 12 | and Scala. One of the most powerful features of Akka is its 13 | Actor Model of concurrency, which you will learn more about in this tutorial. 14 |

15 | 16 |

Source code

17 | 18 |

19 | The HelloAkka.java file is the whole 20 | application in this example. 21 |

22 |

23 | The sample in this tutorial is pretty simple; it consists of a Greeter Actor who holds 24 | onto the latest defined greeting string and can respond to two actions; set a new greeting 25 | string and return the latest greeting string. 26 |

27 |

28 | Next let's get started. 29 |

30 |
31 | 32 |
33 |

Define our Messages

34 |

35 | An Actor does not have a public API in terms of methods that you can invoke. Instead its public 36 | API is defined through messages that the actor handles. Messages can be of arbitrary 37 | type (any subtype of Object in Java). This means that we 38 | can send boxed primitive values (such as String, Integer, 39 | Boolean etc.) as messages or plain data structures like arrays and 40 | collection types. However, since the messages are the Actor's public API, you should define 41 | messages with good names and rich semantic and domain specific meaning, even if it's just wrapping 42 | your data type. This will make it easier to use, understand and debug actor-based systems. 43 |

44 |

45 | Now we want to define three different messages; 46 |

51 |

52 |

53 | Let's start by defining the messages (we are putting them inside an outer HelloAkka class, 55 | containing our full sample). It is very important that the messages we create are immutable (meaning that 56 | they cannot be changed), if not we run the risk of accidentally sharing state between two different Actors 57 | which will violate the Actor Model. In this sample we will not use any remoting, but it is a good practice to 58 | always mark your messages as Serializable since then you will not run in to any runtime issues if 59 | you decide to scale out (on to multiple nodes) with Akka but forget to go back and reimplement your messages. 60 |


 61 | public static class Greet implements Serializable {}
 62 | 
 63 | public static class WhoToGreet implements Serializable {
 64 |     public final String who;
 65 |     public WhoToGreet(String who) {
 66 |         this.who = who;
 67 |     }
 68 | }
 69 | 
 70 | public static class Greeting implements Serializable {
 71 |     public final String message;
 72 |     public Greeting(String message) {
 73 |         this.message = message;
 74 |     }
 75 | }
 76 |         
77 |

78 |
79 | 80 |
81 |

Define our Actor

82 | 83 |

84 | The Actor is the unit of execution in Akka. Actors are object-oriented in the sense that they encapsulate 85 | state and behavior, but they have much stronger isolation than regular objects in Java. The Actor 86 | model prevents sharing state between Actors and the only way to observe another actor's state is by sending 87 | it a message asking for it. Actors are extremely lightweight, they are only constrained by memory of which 88 | they consume only a few hundred bytes each — this means you can easily create millions of concurrent 89 | Actors in a single application. Their strong isolation principles together with the event-driven model (that 90 | we will talk about later on) and location transparency makes it easy to solve hard concurrency and scalability 91 | problems in an intuitive way. 92 |

93 |

94 | To create an Actor that uses Lambdas define a class that extends AbstractActor and implement the 95 | receive() method. It is in the receive() method that you define the behavior; how 96 | the Actor should react to the different messages it receives. An Actor can have — and often has — 97 | state. Accessing or mutating the internal state of an Actor is fully thread safe since protected by the Actor model. 98 |

99 |

100 | So, let's now create a Greeter Actor with a single variable greeting as its state, holding on to the latest 101 | defined greeting, and in its receive() method let's add the behavior for how it should react upon receiving 102 | the WhoToGreet and the Greet messages. 103 |

104 |

105 | Let's start by creating our Actor in Java (you can find the code in the HelloAkka.java file): 107 |


108 | public static class Greeter extends AbstractActor {
109 |     String greeting = "";
110 | 
111 |     @Override public PartialFunction>Object, BoxedUnit< receive() {
112 |         return ReceiveBuilder.
113 |             match(WhoToGreet.class, message -> greeting = "hello, " + message.who).
114 |             match(Greet.class, message -> sender().tell(new Greeting(greeting), self())).
115 |             build();
116 |     }
117 | }
118 |         
119 |

120 |

121 | Actors like this one are "untyped" in the sense that the type of message received is not restricted—it is 122 | Object as shown above. There are also typed actors, but we will 123 | not concern ourselves with those now, the normal actors are the untyped ones. 124 |

125 |

126 | Don't worry about the sender(), tell(..) and self() API calls, 127 | we will get to that soon when we talk about sending and replying to messages. 128 |

129 |
130 | 131 |
132 |

Create our Actor

133 | 134 |

135 | So far we have defined our Actor and its messages. Now let's create an instance of this actor. In Akka you can't 136 | create an instance of an Actor the regular way using new, instead you create it using a factory. What is 137 | returned from this factory is not an instance of the Actor itself but an ActorRef pointing to our actor 138 | instance. 139 |

140 |

141 | This level of indirection adds a lot of power and flexibility. It enables for example location transparency 142 | meaning that the ActorRef can, while retaining the same semantics, represent an instance of the running actor 143 | in-process or on a remote machine. I.e. location doesn't matter. This also means that the runtime can if needed 144 | optimize the system by changing an actor's location or the application's topology while it is running. Another 145 | thing that this level of indirection enables is the "let it crash" model of failure management in which the 146 | system can heal itself by crashing and restarting faulty actors. 147 |

148 |

149 | This factory in Akka is the ActorSystem and is to some extent similar to Spring's BeanFactory 150 | in that it also acts as a container for your Actors, managing their life-cycles etc. You create an Actor through the 151 | actorOf factory method. This method takes a configuration object called Props and a name. 152 | Actor (and ActorSystem) names are important in Akka, you use them for example when looking Actors up as well as when you 153 | configure them in the configuration 154 | file, so you should take your time giving your Actors good names. 155 |

156 |

157 | This is the code that we have to write in Java: 158 |


159 | final ActorSystem system = ActorSystem.create("helloakka");
160 | final ActorRef greeter = system.actorOf(Props.create(Greeter.class), "greeter");
161 |         
162 |

163 |

164 | Now we have a running instance of a Greeter actor. Next we will learn how to communicate with it. 165 |

166 |
167 | 168 |
169 |

Tell the Actor (to do something)

170 | 171 |

172 | All communication with Actors is done through asynchronous message passing. This is what makes Actors 173 | reactive and event driven. An Actor doesn't do anything unless it's been told to do something, and you 174 | tell it to do something by sending the message. Sending a message asynchronously means that the sender 175 | does not stick around waiting for the message to be processed by the recipient actor. Instead the Actor 176 | hands the message off by putting it on the recipient's mailbox and is then free to do something more 177 | important than waiting for the recipient to react on the message. The actor's mailbox is essentially a 178 | message queue and has ordering semantics, this guarantees that the ordering of multiple messages sent 179 | from the same Actor is preserved, while they can be interleaved with the messages sent by another actor. 180 |

181 |

182 | You might be wondering what the Actor is doing when it is not processing messages, i.e. doing actual work? 183 | It is in a suspended state in which it does not consume any resources apart from memory. 184 |

185 |

186 | You tell an Actor to do something by passing in a message into the tell method on the 187 | ActorRef. This method puts the message on the actor's mailbox and then returns immediately. 188 |

189 |

190 |

greeter.tell(new WhoToGreet("akka"), ActorRef.noSender());
191 |

192 |
193 | 194 |
195 |

Replying to an Actor

196 | 197 |

The 'self' reference

198 | 199 |

200 | Sometimes the the communication pattern is not just a one-way style of communication but instead lends 201 | itself towards request-reply. One explicit way of doing that is by adding a reference of yourself as part 202 | of the message so the receiver can use that reference to send a reply back to you. This is such a common 203 | scenario that it is directly supported by Akka; for every message you send you have the option of passing 204 | along the sender reference (the Actor's ActorRef). If you are sending a message from within 205 | an Actor then you have access to your own ActorRef through self reference, please 206 | note that you should never use this. You can access the self reference through the 207 | self() method. 208 |

209 |

210 |


211 | // From within an Actor
212 | greeter.tell(new Greet(), self());
213 |         
214 |

215 |

216 | If you choose not to pass in a sender reference into the tell method, or forget it, then a reference to 217 | the 'dead-letter' Actor will be used. The 'dead-letter' Actor is where all unhandled messages end up, and 218 | you can use Akka's Event Bus to subscribe on them. 219 |

220 | 221 |

The 'sender' reference

222 | 223 |

224 | This sender reference will then be available in the receiver Actor when it's processing the message. Since 225 | each message is paired with its unique sender reference, the "current" sender reference will change with each 226 | new message you process. So if you for some reason need to use a specific sender reference later then you have 227 | to hold on to it, storing it away in a member field or similar. In Java you can access it using the 228 | sender() method. 229 |

230 |

231 |


232 | // From within the Greeter Actor
233 | sender().tell(new Greeting(greeting), self());
234 |         
235 |

236 |
237 | 238 |
239 |

Using Inbox

240 | 241 |

242 | Most real-world Actor applications make use of more than one Actor. The inventor of the Actor Model, 243 | Carl Hewitt, recently said in an interview that; "One Actor is no Actor. Actors come in systems." 244 | This is important wisdom. To truly leverage the Actor Model you should use lots of Actors. Every hard 245 | problem in Actor programming can be solved by adding more Actors; by breaking down the problem into 246 | subtasks and delegate by handing them to new Actors. 247 |

248 |

249 | However, for simplicity we are just using a single Actor in this sample. This means that if we communicate 250 | with this single actor from a main program then we have no sender, since we are 251 | not communicating with the Actor from within another Actor. Luckily Akka has a nice solution to this problem; 252 | Inbox. 253 |

254 |

255 | Inbox allows you to create an "actor-in-a-box", i.e. it contains an Actor which can be used as a puppet 256 | for sending messages to other Actors and receiving their replies. You can create an Inbox using 257 | Inbox.create and send messages from it using inbox.send. The internal Actor will just 258 | put any message it receives into a queue from which it can be retrieved by calling inbox.receive; 259 | if the queue is empty then that call will block until a message becomes available. Pretty simple. 260 |

261 |

262 | As you probably know, blocking is something that can really inhibit performance and scalability, and that 263 | you should use very sparingly and with care. That said, we are making use of it in this sample since it 264 | simplifies the sample and makes it very easy to follow the message flow. 265 |

266 |

267 | Now let's complete this tutorial by writing the driver code that will exercise our Greeter Actor. 268 |

269 |

270 |


271 | // Create an "actor-in-a-box"
272 | final Inbox inbox = Inbox.create(system);
273 | 
274 | // Tell the 'greeter' to change its 'greeting' message
275 | greeter.tell(new WhoToGreet("akka"), ActorRef.noSender());
276 | 
277 | // Ask the 'greeter for the latest 'greeting'
278 | // Reply should go to the mailbox
279 | inbox.send(greeter, new Greet());
280 | 
281 | // Wait 5 seconds for the reply with the 'greeting' message
282 | Greeting greeting = (Greeting) inbox.receive(Duration.create(5, "seconds"));
283 | System.out.println("Greeting: " + greeting.message);
284 |         
285 |

286 |
287 | 288 |
289 |

Run the App

290 | 291 |

292 | Congratulations!!! 293 |

294 |

295 | Now you have almost completed the tutorial and written a simple Akka application. If you have not looked 296 | at the full sample then now is a good time to do so: 297 | HelloAkka.java 298 |

299 |

300 | Let's have some fun and run it. 301 |

302 |

303 | In Run select Start (if the app is not already running). Feel free to modify, compile and re-run the sample. 304 |

305 |
306 | 307 |
308 |

Next Steps

309 | 310 |

311 | The Akka Documentation explains each one of the topics covered 312 | in this tutorial in great depth, and much much more. Check out the 313 | Java Manual for more information 314 | using Akka with Java and Lambdas. 315 |

316 |

317 | The Akka Team blog; Let It Crash has a lot of articles and 318 | can be a good additional source of information.
319 |

320 |

321 | If you have questions don't hesitate to post them to the 322 | akka-user Google Group.
323 |

324 |
325 | 326 | 327 | --------------------------------------------------------------------------------