package org.akka.essentials.stm.transactor.example; import static akka.actor.SupervisorStrategy.escalate; import static akka.actor.SupervisorStrategy.resume; import static akka.actor.SupervisorStrategy.stop; import java.util.concurrent.TimeUnit; import org.akka.essentials.stm.transactor.example.msg.AccountBalance; import org.akka.essentials.stm.transactor.example.msg.AccountCredit; import org.akka.essentials.stm.transactor.example.msg.AccountDebit; import org.akka.essentials.stm.transactor.example.msg.TransferMsg; import scala.concurrent.duration.Duration; import akka.actor.ActorRef; import akka.actor.AllForOneStrategy; import akka.actor.Props; import akka.actor.SupervisorStrategy; import akka.actor.SupervisorStrategy.Directive; import akka.actor.UntypedActor; import akka.actor.UntypedActorFactory; import akka.event.Logging; import akka.event.LoggingAdapter; import akka.japi.Function; import akka.transactor.Coordinated; import akka.transactor.CoordinatedTransactionException; import akka.util.Timeout; public class TransferActor extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); String fromAccount = "XYZ"; String toAccount = "ABC"; // sets the from account with initial balance of 5000 ActorRef from = context().actorOf(new Props(new UntypedActorFactory() { public UntypedActor create() { return new AccountActor(fromAccount, Float.parseFloat("5000")); } }), fromAccount); // sets the to account with initial balance of 1000 ActorRef to = context().actorOf(new Props(new UntypedActorFactory() { public UntypedActor create() { return new AccountActor(toAccount, Float.parseFloat("1000")); } }), toAccount); Timeout timeout = new Timeout(5, TimeUnit.SECONDS); @Override public void onReceive(Object message) throws Exception { if (message instanceof TransferMsg) { final TransferMsg transfer = (TransferMsg) message; final Coordinated coordinated = new Coordinated(timeout); coordinated.atomic(new Runnable() { public void run() { // credit amount - will always be successful to.tell(coordinated.coordinate(new AccountCredit(transfer .getAmtToBeTransferred()))); // debit amount - throws an exception if funds insufficient from.tell(coordinated.coordinate(new AccountDebit(transfer .getAmtToBeTransferred()))); } }); } else if (message instanceof AccountBalance) { AccountBalance accBalance = (AccountBalance) message; // check the account number and return the balance if (accBalance.getAccountNumber().equals(fromAccount)) { from.tell(accBalance, sender()); } if (accBalance.getAccountNumber().equals(toAccount)) { to.tell(accBalance, sender()); } } } // catch the exceptions and apply the right strategy, in this case resume() private static SupervisorStrategy strategy = new AllForOneStrategy(10, Duration.create("10 second"), new Function<Throwable, Directive>() { public Directive apply(Throwable t) { if (t instanceof CoordinatedTransactionException) { return resume(); } else if (t instanceof IllegalStateException) { return resume(); } else if (t instanceof IllegalArgumentException) { return stop(); } else { return escalate(); } } }); @Override public SupervisorStrategy supervisorStrategy() { return strategy; } }