June 24, 2016 | Software Consultancy
Akka has been designed with a Java API from the very first version. Though widely adopted, as a Java developer I think Akka has been mainly a Scala thing… until recently. Things are changing and Akka is moving to a proper Java 8 support.
WRITTEN BY
Due to Java syntax limitations, the Java API built over the Scala implementation was, at least, clumsy. With version 2.3.0 (on March 2014) Akka introduced a Java 8 API, called lambda support. More recently (Akka 2.4.2, on February 2016) they started replacing scala.concurrent.Future
with java.util.concurrent.CompletableFuture
.
Let’s walk through some of the improvements that are making Akka much more Java developer friendly.
AbstractActor
and receive
message loopActors may now extend AbstractActor
, and implement message handling logic in a receive(...)
block, defined inside the constructor.
// New Java 8 API version
public class Barista extends AbstractLoggingActor {
private Barista() {
final CoffeeMachine coffeeMachine = new CoffeeMachine();
log().info("The coffee machine is ready");
receive(
match(Order.class, order -> {
log().info("Received an order for {}", order);
final Coffee coffee = coffeeMachine.prepare(order.type);
log().info("Your {} is ready", coffee);
sender().tell(coffee, self());
})
.matchAny(this::unhandled)
.build()
);
}
public static Props props() {
return Props.create(Barista.class, () -> new Barista());
}
}
This clearly mimics Scala pattern matching. It pushes Java syntax to the limit (I still cannot convince my IntelliJ to format the receive block properly…), to create a sort of DSL, but the result is pretty clear. Much, much better than the verbosity of the pre-Java8 interface:
// Old Java API version
public class OldBarista extends UntypedActor {
private LoggingAdapter log = Logging.getLogger(getContext().system(), this);
private final CoffeeMachine coffeeMachine;
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof Order) {
Order order = (Order) message;
log.info("Received an order for {}", order);
Coffee coffee = coffeeMachine.prepare(order.type);
log.info("Your {} is ready", coffee);
getSender().tell(coffee, getSelf());
} else {
unhandled(message);
}
}
public static Props props() {
return Props.create(new Creator() {
private static final long serialVersionUID = 1L;
@Override
public OldBarista create() throws Exception {
return new OldBarista();
}
});
}
private OldBarista() {
coffeeMachine = new CoffeeMachine();
log.info("The coffee machine is ready");
}
}
In my example above, I extended AbstractLoggingActor
, instead of <a href="http://doc.akka.io/japi/akka/2.4.7/akka/actor/AbstractActor.html">AbstractActor</a>
, just to avoid creating the LoggingAdapter
.
become
and unbecome
To change the message handling behaviour dynamically you have to create one or more PartialFunction<Object,BoxedUnit>
defining different behaviours. The syntax is no different from defining the main behaviour in a receive(...)
block:
// New Java 8 API
private PartialFunction<Object, BoxedUnit> behaviour =
match(Order.class, order -> {
// ... process order ...
})
The former interface forced you to create an anonymous class, with the usual clutter:
// Old Java API
Procedure
Note that pipe(...)
method here is from akka.pattern.Patterns
, while in the previous example it was from the newer akka.pattern.PatternsCS
.
[Updated after publishing]
With a prompt reaction, Akka team has added support for CircuitBreakers using CompletableFuture
. It will be probably included in the next Akka release.
Thanks, Konrad!
Code examples
Code examples used in this post (and a bit more): https://github.com/opencredo/akka-java8-examples
Wrapping up
Akka is moving to a proper Java 8 interface. In this article, I just skimmed some of the changes to the Java API. More have been introduced, radically changing the interface. For example, all the Akka Persistence event-sourcing support have been rewritten.
As of today (Akka version 2.4.7), the migration is not complete. The lambda support is still marked as experimental, so you may still expect breaking changes even through minor releases. I think Lightbend (formerly Typesafe), the company governing Akka development, is steering toward Java and improvements of Akka Java API are a direct consequence. From a Java developer point of view, these improvements are making Akka much more friendly that it used to be.
As a Java developer, you may still see Scala under the hood. Akka is written in Scala. Akka authors think in Scala, so the Java 8 interface looks very Scala-like. Some of the syntax choices appear quirky, to the eye of a Java developer.
But, after all, this is useful. The more similar the two interface are, the easier is for Java developer to use the Akka community content, answer, blogposts, examples, mostly written in Scala.
This blog is written exclusively by the OpenCredo team. We do not accept external contributions.
Agile India 2022 – Systems Thinking for Happy Staff and Elated Customers
Watch Simon Copsey’s talk from the Agile India Conference on “Systems Thinking for Happy Staff and Elated Customers.”Lean-Agile Delivery & Coaching Network and Digital Transformation Meetup
Watch Simon Copsey’s talk from the Lean-Agile Delivery & Coaching Network and Digital Transformation Meetup on “Seeing Clearly in Complexity” where he explores the Current…When Your Product Teams Should Aim to be Inefficient – Part 2
Many businesses advocate for efficiency, but this is not always the right goal. In part one of this article, we explored how product teams can…