Akka - AbstractBehaviorWithStash? - java

is there a way to start out an Akka Typed Behavior with a stash in Java? The reason is simple, during the first stage, the Behavior waits for a certain kind of message, initializes itself with it and should stash() every other message until it got that message, then unstash() them and proceed as normal.
With functional, this is easily doable, sure, but is there a way to do so with AbstractBehavior and it's createReceive() method, because that one doesn't allow me to return a stashed Behavior via Behaviors.withStash( stash -> ...), since it expects a Receive ?

In the OO API, I would expect that the approach would be to inject the stash through constructor args from a static create method.
// Apologies if this Java is atrocious
public class ActorWithAStash extends AbstractBehavior<ActorWithAStash.Command> {
public static Behavior<Command> create() {
Behaviors.setup(context ->
Behaviors.withStash(100, stash ->
new ActorWithAStash(context, stash)
)
);
}
public interface Command;
private ActorWithAStash(ActorContext<Command> context, StashBuffer<Command> stash) {
this.context = context;
this.stash = stash;
}
private ActorContext<Command> context;
private StashBuffer<Command> stash;
}

Related

Can ActorContext (getContext()) be passed outside the Actor to create child actors?

I want to have an ActorFactory class as below
public class SampleActorFactory {
// Simple create method
public createActor(AbstractActor.ActorContext actorContext, Props props) {
return actorContext.actorOf(props);
}
// other complex create methods
...
}
Is it ok to create a child actor using the above factory class, or is this considered a bad practice? If considered bad practice, then why?
eg:
public class SampleActor extends AbstractActor {
private final SampleActorFactory sampleActorFactory;
#Override
public Receive createReceive() {
return receiveBuilder()
.match(SampleData.class, sampleData -> {
Props sampleProps = getSampleProps(...);
ActorRef childActor = sampleActorFactory.createActor(getContext(), sampleProps);
})
.build();
}
}
I don't see anything wrong with that approach, you should be able to access context outside of actor system. But.... generally to create an actor, you just need one line of code as below. With your code, you have to write two lines of code (one for Props and other one to call your createActor() method) where ever you create an actor. Other than implementing a factory method, if you achieve any additional benefit from it, you can go for it.
ActorRef demoActor = getContext().system().actorOf(Props.create(MyDemoActor.class, prop1, prop2);

How to create some sort of event framework in java?

I don't have a GUI (my classes are part of a Minecraft Mod). I wanted to be able to mimic C# event framework: A class declares events and lets others subscribe to them.
My first approach was to create a class called EventArgs and then do something like this:
public class EventArgs
{
public boolean handled;
}
#FunctionalInterface
public interface IEventHandler<TEvtArgs extends EventArgs>
{
public void handle(Object source, TEvtArgs args);
}
public class Event<TEvtArgs extends EventArgs>
{
private final Object owner;
private final LinkedList<IEventHandler<TEvtArgs>> handlers = new LinkedList<>();
public Event(Object owner)
{
this.owner = owner;
}
public void subscribe(IEventHandler<TEvtArgs> handler)
{
handlers.add(handler);
}
public void unsubscribe(IEventHandler<TEvtArgs> handler)
{
while(handlers.remove(handler));
}
public void raise(TEvtArgs args)
{
for(IEventHandler<TEvtArgs> handler : handlers)
{
handler.handle(owner, args);
if(args.handled)
break;
}
}
}
Then a class would do something like this:
public class PropertyChangedEvtArgs extends EventArgs
{
public final Object oldValue;
public final Object newValue;
public PropertyChangedEvtArgs(final Object oldValue, final Object newValue)
{
this.oldValue = oldValue;
this.newValue = newValue;
}
}
public class SomeEventPublisher
{
private int property = 0;
private final Random rnd = new Random();
public final Event<PropertyChangedEvtArgs> PropertyChanged = new Event<>(this);
public void raiseEventOrNot(int value)
{
if(rnd.nextBoolean())//just to represent the fact that the event is not always raised
{
int old = property;
property = value;
PropertyChanged.raise(new PropertyChangedEvtArgs("old(" + old + ")", "new(" + value + ")"));
}
}
}
public class SomeSubscriber
{
private final SomeEventPublisher eventPublisher = new SomeEventPublisher();
public SomeSubscriber()
{
eventPublisher.PropertyChanged.subscribe(this::handlePropertyAChanges);
}
private void handlePropertyAChanges(Object source, PropertyChangedEvtArgs args)
{
System.out.println("old:" + args.oldValue);
System.out.println("new:" + args.newValue + "\n");
}
public void someMethod(int i)
{
eventPublisher.raiseEventOrNot(i);
}
}
public class Main
{
private static final SomeSubscriber subscriber = new SomeSubscriber();
public static void main(String[] args)
{
for(int i = 0; i < 10; ++i)
{
subscriber.someMethod(i);
}
}
}
The biggest problem with this naïve approach is that it breaks proper encapsullation by exposing raise as public. I can't see a way around it, and maybe my whole pattern is wrong. I would like some ideas.
There's also a related problem: I would like the events to be raised immediately after the method raising them returns. Is there a way to synchronize this using threads or some other construct? The caller code, of course, can't be involved in the task of synchronization. It has to be completely transparent to it.
The best thing to do here is to avoid implementing your own event framework in the first place, and instead rely on some existing library. Out of the box Java provides EventListener, and at a minimum you can follow the patterns documented there. Even for non-GUI applications most of this advice applies.
Going beyond the JDK Guava provides several possible options, depending on your exact use case.
The most likely candidate is EventBus, which:
allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other).
Or ListenableFuture (and ListeningExecutorService) which:
allows you to register callbacks to be executed once [a task submitted to an Executor] is complete, or if the computation is already complete, immediately. This simple addition makes it possible to efficiently support many operations that the basic Future interface cannot support.
Or the Service API which:
represents an object with an operational state, with methods to start and stop. For example, webservers, RPC servers, and timers can implement the Service interface. Managing the state of services like these, which require proper startup and shutdown management, can be nontrivial, especially if multiple threads or scheduling is involved.
This API similarly lets you register listeners to respond to state changes in your services.
Even if none of these options directly work for your use case, take a look at Guava's source code for examples of event-driven behavior and listeners you can try to emulate.

Better design for initialization within constructor

I have a class that looks something like this which acts as factory for clients based on credentials retrieved from credentials service. It builds clients one time and returns that on every call.
public class ClientFactory {
private CredentialService credentialService;
private ClientA clientA;
public ClientFactory(CredentialService credentialService){
this.credentialService = credentialService;
//initialization in constructor
this.clientA = buildClientA(credentialService.getCredentials());
}
public ClientA getClientA(){
return clientA;
}
/** Build new ClientA using crendentials*/
private ClientA buildClientA(String credentials){
return new ClientA(credentials);
}
}
Issue that I see with this is line 2 in the constructor which basically start using dependency 'credentialService' to initialize other dependencies immediately. If some other developer moves around order of code in constructor, it will start failing. Other option is too change method getClientA() to this.
public ClientA getClientA(){
if(clientA == null) {
this.clientA = buildClientA(credentialService.getCredentials());
}
return clientA;
}
But it has thread safety issues. Is there a better way to design above class which avoids concerns I highlighted above?
Thanks
Well,
this.clientA = buildClientA(credentialService.getCredentials()); relies on the parameter credentialService passed to the constructor, not on the member this.credentialService. Therefore, the order of the initializations doesn't matter.
BTW, just to be safe and avoid confustion, I wouldn't use the same name for the parameter of the constructor and the member.
Just don't save off a reference to theCredentialService as an instance variable, and continue passing credentialService.getCredentials() to bulldClientA. You are already not using the instance variable credentialService.
What you call ClientFactory looks like it's really just a ClientA. So why not have a factory that depends on the credentials and share a reference to a ClientA if you want to avoid creating extra ClientA objects?
public class ClientFactory {
private final CredentialService credentialService;
public ClientFactory(CredentialService credentialService){
this.credentialService = credentialService;
}
public ClientA newClientA(String credentials){
return new ClientA(credentials);
}
}
If you want to have a pool of clients potentially, you can share a Supplier<ClientA> instead.
Supplier<ClientA> simpleSupplier = Suppliers.ofInstance(ClientFactory.newClientA()); // guava
Supplier<ClientA> allNewSupplier = () -> ClientFactory.newClientA(); // java 8 lambda
ClientA cachedClient = simpleSupplier.get();
ClientA newClient = allNewSupplier.get();

what's a good pattern for registering a Class to execute a specific task later on?

I'm writing a test suite, and I'm thinking about how to mock certain request/response flows. For example, I want to test a method that makes multiple RESTful calls:
getCounts() {
...
Promise<Integer> count1 = getCount1();
Promise<Integer> count2 = getCount2();
// returns a DataModel containing all counts when the Promises redeem
}
getCount1() {
...
Request<Foo> request = new Request<Foo>();
sendRequest(request);
...
}
getCount2() {
...
Request<Bar> request = new Request<Bar>();
sendRequest(request);
...
}
sendRequest(Request<T> request) {...}
However, each getCount() method creates a different Request<T> object, where <T> describes the type of request being made in regards to the count being retrieved. This means I can't simply "mock" the sendRequest() method since it is being called with a different type each time.
I was thinking about an approach where I register a "handler"... when sendRequest() is called, it determines which handler to call, and the handler would know the appropriate type of mock data to return. The registration would be something like storing the handler class type or an instance of the handler class along with the mock data it needs, and when sendRequest() is called, it would look for and invoke the correct handler.
However, I'm not sure if this a good pattern, and I'm wondering if there is a better way of approaching this problem. What is a good pattern for registering a Class or a particular method to execute a specific task later on?
Hard to answer without more context, but the general approach is to use Inversion Of Control (IOC). For example, put the getCountXXX methods into a class of their own, which may be a good idea for better reuse, readability, encapsulation, testability, etc:
public class CountFetcher {
getCount1() { ... }
getCount2() { ... }
}
The original code now gets an instance of CountFetcher using whatever "injection" mechanism is available to you. Simplest is just a constructor:
public class Counter {
private final CountFetcher fetcher;
public Counter(CountFetcher fetcher) {
this.fetcher = fetcher;
}
public getCounts() {
Promise<Integer> count1 = fetcher.getCount1();
Promise<Integer> count2 = fetcher.getCount2();
...
}
}
In your production code, you instantiate Counter with a real CountFetcher. In test code, you inject a mock version of CountFetcher which can have each individual getCountXXX method return whatever you want:
public class MockCountFetcher extends CountFetcher {
#Override
getCount1() { return mockCount1; }
}
public class TestCounter {
#Test
public void smokeTest() {
CountFetcher mockFetcher = new MockCountFetcher();
Counter counter = new Counter(mockFetcher);
assertEquals(someExpectedValue, counter.getCounts());
}
}

How to properly test with mocks Akka actors in Java?

I'm very new with Akka and I'm trying to write some unit tests in Java. Consider the following actor:
public class Worker extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof Work) {
Work work = (Work) message;
Result result = new Helper().processWork(work);
getSender().tell(result, getSelf());
} else {
unhandled(message);
}
}
}
What is the proper way to intercept the call new Helper().processWork(work)? On a side note, is there any recommended way to achieve dependency injection within Akka actors with Java?
Thanks in advance.
Your code is already properly testable:
you can test your business logic separately, since you can just instantiate your Helper outside of the actor
once you are sure that the Helper does what it is supposed to do, just send some inputs to the actor and observe that the right replies come back
Now if you need to have a “mocked” Worker to test some other component, just don’t use a Worker at all, use a TestProbe instead. Where you would normally get the ActorRef of the Worker, just inject probe.getRef().
So, how to inject that?
I’ll assume that your other component is an Actor (because otherwise you won’t have trouble applying whatever injection technique you normally use). Then there are three basic choices:
pass it in as constructor argument
send it within a message
if the actor creates the ref as its child, pass in the Props, possibly in an alternative constructor
The third case is probably what you are looking at (I’m guessing based on the actor class’ name):
public class MyParent extends UntypedActor {
final Props workerProps;
public MyParent() {
workerProps = new Props(...);
}
public MyParent(Props p) {
workerProps = p;
}
...
getContext().actorOf(workerProps, "worker");
}
And then you can inject a TestProbe like this:
final TestProbe probe = new TestProbe(system);
final Props workerMock = new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new UntypedActor() {
#Override
public void onReceive(Object msg) {
probe.getRef().tell(msg, getSender());
}
};
}
});
final ActorRef parent = system.actorOf(new Props(new UntypedActorFactory() {
public UntypedActor create() {
return new MyParent(workerMock);
}
}), "parent");

Categories