Java akka get common things to one place - java

I am using java akka framework. Some of my actors will do same thing in onreceive method. Is there a way to avoid this and get them to a common location. (May be using inheritance)
Problem in detail is like below.
In some actors it send an ack message based on a condition. This ack
is send to and external system by another actor.
This is duplicated in several classes.

Because an actor's Receive block is a partial function, you can chain Receive blocks with orElse. This is helpful for sharing behavior among actors and is described in the Scala version of the documentation, but you can do the same thing in Java.
The following is a simple example that uses inheritance, in which the common acking behavior is defined in a base class. However, you don't have to use inheritance and can define Receive blocks wherever you want to:
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class AckingActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
public static class Msg1 {}
public static class Ack {}
#Override
public Receive createReceive() {
return receiveBuilder()
.match(Msg1.class, m -> getSender().tell(new Ack(), getSelf()))
.matchAny(m -> log.info("unknown message"))
.build();
}
}
Actors that share the acking behavior can extend the base class:
import akka.actor.AbstractActor;
public class AckingProducer extends AckingActor {
private AbstractActor.Receive producerBehavior;
public AckingProducer() {
producerBehavior =
receiveBuilder()
.matchEquals("foo", m -> getSender().tell("bar", getSelf()))
.matchEquals("ping", m -> getSender().tell("pong", getSelf()))
.build();
}
#Override
public Receive createReceive() {
return producerBehavior.orElse(super.createReceive());
// ^ chain the Receive blocks with orElse
// e.g., behavior1.orElse(behavior2).orElse(behavior3)
}
}
You can chain an arbitrary number of Receive blocks. Note that if more than one partial function handles the same message, then the first one that matches (that is, the first Receive block in the orElse chain that matches) will handle the message.

Related

Passing data from object to parent in java

In my project I am trying to implement a event handling for my websocket instances. So I basically have 3 classes:
My AuthClient class which extends a WebsocketClient and has onMessage callback. In this onMessage method the websocket can enter different states like "hello", "pending_finish", "finish" and so on.
public class AuthClient extends WebSocketClient {
#Override
onMessage(String message) {
switch(message) ... // data events here
}
}
I am now trying to write a parent class called ClientManager where I want to store and manage multiple websockets.
// trying to receive data from specific data events for each client here
public class ClientManager {
private int maxClients;
private final Map<String, AuthClient> clients;
private final HashSet<String> tokens;
public ClientManager(HashSet<String> tokens, int maxClients) {
this.tokens = tokens;
this.maxClients = maxClients;
this.clients = new HashMap<>(maxClients);
}
}
My question is, how can I pass data which I receive from a WebsocketClient within this onMessage callback to my ClientManager? I need a solution that does not have any great performance loss.
I already tried implementing an interface with the events, but I don't quite get it to work with sharing data.
This looks like a good use case for an observer pattern.
Your observer would be your manager class and your observables would be your websocket clients. Any time you create a new websocket client, register your manager class instance with it using the registerObserver method. Then when you desire to forward a message from your websocket client to your manager, you can simply call the notifyObservers method to forward the request out to any registered observers. Take a look at the pattern info here:
https://www.baeldung.com/java-observer-pattern

Invoke RichSinkFunction from RichMapFunction in Flink

I have a sink which extends from RichSinkFunction that is caching some information.
When my process is finished, I want to update all that information that is cached so I want to force its invocation.
I can call that sink from an KeyedProcessAccumulatorFunction, calling it with the context of type ReadOnlyContext and it works.
public class PageAccumulateFunction implements KeyedProcessAccumulatorFunction{
public SessionAccumulator accumulate(
#NonNull Tuple2<CollectionMessage, PropertyInfo> value,
#NonNull SessionAccumulator accumulator,
#NonNull KeyedBroadcastProcessFunction.ReadOnlyContext ctx) {
....
ctx.output(outputTag, message);
}
}
But in my RichMapFunction class, I can't invoke that sink. I can get a RuntimeContext object (but not a ReadOnlyContext), but I don't know if I can use it to invoke the RichSinkFunction sink.
public class SessionMapper extends RichMapFunction<SessionAccumulator, GenericRecord>{
public GenericRecord map(SessionAccumulator sessionAccumulator) {
....
RuntimeContext ctx = getRuntimeContext();
....
}
}
Any idea?
Only process functions can use side outputs (which you write to via ctx.output).
A MapFunction automatically sends the return value of its map method downstream (toward the sink). It works this way because a map is a one-to-one mapping from inputs to outputs. Most other function types (e.g., process functions, flatmaps) are passed a Collector you can use to send events downstream.

Implement RPC with underlying request/response protocol (JSON-RPC on SIP)

Look at the following use case.
I have a client (Java) application, which wants to get/set the state of another, remote application (C). The communication between them is done via SIP, which is run in another thread.
The SIP interface can do the following:
sendMessage
onRequest
I have two ideas for the architecture:
RPC (JSON-RPC)
Define a class which does the marshalling/unmarshalling for JSONRPCRequests and JSONRPCResponse (http://software.dzhuvinov.com/json-rpc-2.0-base.html)
Define a Invoker class, which has something like a call(server, name, arguments) method.
In the Invoker class, the name and arguments are put into a JSONRPCRequest and sent via the SIP layer sendMessage
Now comes my problem. How do i actually get the right back to the caller? The control flow is now:
The onRequest method is called, but I do now know whether it is the answer to my previous call. What i do is putting all responses reaching my server into a Map, and just poll that list in the Invoker.
A rough sketch might be;
Invoker (provides API to client)
class Invoker {
private Channel channel;
public Invoker(Channel channel) { this.channel = channel; }
public Object call(String server, String name, Object .. args) {
JSONRPCRequest req = ...;
channel.sendMessage(server, req.toString());
while( ! channel.hasResponse(req.id()) {
Thread.sleep(42);
}
return channel.getResponse(req.id()).result();
}
}
Channel (interface to messenger):
class Channel {
private Map<Object, JSONRPCResponse> responses = new //;
private Sip sip = new Sip() {
public void onRequest(String msg) {
JSONRPCResponse response = JSONRPCResponse.parse(msg);
responses.put(msg.id(), response);
}
};
public void sendMessage(String server, String message) {
sip.sendMessage();
}
public boolean hasResponse onRequest(Object id) {
responses.hasKey(id);
}
public JSONRPCResponse getResponse(Object id) {
responses.get(id);
responses.delete(id);
}
}
SIP (messenger itself):
abstract class Sip {
public void sendMessage(String msg) {
// SIP magic
}
public abstract void onRequest(String msg);
}
Is there a better way to do that? My biggest problems/code smells are:
the blocking in Invoker
the protocol is in Invoker, maybe I want to switch marshalling to something else
the map as mean to get the correct response for a request
the SIP abstract method looks strange
No error handling
No timeout
Message Passing
Is there an easy way to get rid of RPC, and implement something like RPC with just message passing? Any hints for pattern are welcome. I do not need the code itself, I am totally fine with just architecture. I tried to google for message passing implementations, and how they actually change state with it, but I did not find anything useful. How to implement timeout/ error handling?
Any good books/literature on that topic is also welcome, as I never programmed such distributed stuff.
Any other ideas on which protocol to use inside SIP to change state is welcome, too, as RPC was my initial thought, and I did not find anything other useful.
The code will not compile, I guess, it was just to visualize my idea.
Define a service interface that has meaningful (for the us case) methods. Instead of using blocking calls, have the client supply a ResponseHandler that will be invoked when the operation is complete:
interface ResponseHandler {
void onComplete(Response response);
void onError(Throwable error);
}
interface SomeService {
void set(String attribute, Object value, ResponsHandler responseHandler);
void get(String attribute, ResponseHandler responseHandler);
}
The implementation of the Service interface can use any suitable protocol, but it has to correlate requests with responses in order to invoke the correct callbacks.

Handling received message in running thread

I have Threads that listens to incoming HTTP messages , i want to enable other developer that use my code to be able to use the messages that i received in any time. I saw in some mobile OS you can implement class and override onRecive function to receive the messages .
is this the right architecture to use in this case? if yes how could i implemented and if its not what is the best way to do it.
You can have a interface which another develoepr can implement and register with your code to be notified when a new message etc has arrived. There are any number of ways this can be achieved.
You could use the built in Observable class. or you could do something like this.
public interface Listener<T> {
public void onEvent(T t);
}
public class Listenable<T> {
private final List<Listener<T>> list = new CopyOnWriteArrayList<Listener<T>>();
public void register(Listener<T> listener) {
if (!list.contains(listener)) list.add(listener);
}
public void unregister(Listener<T> listener) {
list.remove(listener);
}
public void onEvent(T t) {
for (Listener<T> tListener : list)
tListener.onEvent(t);
}
}
The caller could implement the Listener interface or provide an object which does. It then registers this with the Listenable. The listenable can notify all registered listeners.
Take a look at the Observer Pattern.
You can have an interface called MessageListener:
public interface MessageListener{
void onMessage(String message);
}
Users of your library will create their own MessageListeners and will implement the onMessage method which defines what should be done when a message is received. They will also set (or register) this MessageListener with your "threads" before they are started.
Now whenever your thread gets a message, it will notify the listener(s) registered with it by calling the onMessage method.

How to avoid using this in a constructor

I have this situation:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class MessageReceiver
{
MessageListener listener;
public MessageReceiver(MessageListener listener, other arguments...)
{
this.listener = listener;
}
loop()
{
Message message = nextMessage();
listener.onMessageReceipt(message);
}
}
and I want to avoid the following pattern: (Using the this in the Client constructor)
class Client implements MessageListener
{
MessageReceiver receiver;
MessageSender sender;
public Client(...)
{
receiver = new MessageReceiver(this, other arguments...);
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
The reason why i need the above functionality is because i want to call the sender inside the onMessageReceipt() function, for example to send a reply. But I dont want to pass the sender into a listener, so the only way I can think of is containing the sender in a class that implements the listener, hence the above resulting Client implementation. Is there a way to achive this without the use of 'this' in the constructor? It feels bizare and i dont like it, since i am passing myself to an object(MessageReceiver) before I am fully constructed. On the other hand, the MessageReceiver is not passed from outside, it is constructed inside, but does this 'purifies' the bizarre pattern?
I am seeking for an alternative or an assurance of some kind that this is safe, or situations on which it might backfire on me.
The Client's dependencies (such as MessageReceiver) could be injected into it rather than having the Client know how to construct the MessageReceiver:
Client client = new Client(...);
MessageReceiver rcvr = new MessageReceiver(client, ...);
client.setMessageReceiver(rcvr);
However I would suggest looking into breaking the circular dependency between these two classes, it sounds as if something is off in your design.
The real reason why passing this to another class in the first class's constructor is a bad practice is because you are allowing a reference to this to escape before it is fully constructed.
It wont backfire on you as long as this is never referenced before construction. However, you should never rely on that assumption. Concurrency is a big factor here, as well as the contract for the code you pass it to.
Since Client is a MessageReceiver, why not make it one?
public Client extends MessageReceiver implements MessageListener{
/* ... */
}
I don't see where the MessageReceiver is used, so at the moment you could write the code without MessageReceiver like this and it would be effectively the same:
interface MessageListener
{
void onMessageReceipt(Message message);
}
class Client implements MessageListener
{
MessageSender sender;
public Client(...)
{
sender = new Sender(...);
}
.
.
.
#Override
public void onMessageReceipt(Message message)
{
if(Message.isGood())
sender.send("Congrtulations");
else
sender.send("Boooooooo");
}
}
I think a standard publish-subscribe or Observer pattern is probably what you need - but it's hard to tell without understanding the subtleties of the problem that you are trying to solve.

Categories

Resources