transfer data dynamically with netty - java

I've been learning Netty for a while, and from the Netty's tutorials(the MEAP book), almostly the examples are based on a fixed framework, like the EventLoop, Bootstrap, it seems that only the implementations of the handlers in the channelPipeline are the things we really should be concerned about.
Here I wanna design a simple chess game, based on a Server/Client mode, where two players are on different computers. And the background data I want to use Netty to transmit.(I just wanna practice using netty)
And in such a game, the front GUI detect the player put a chessman and then make some change to the data. Then, I need to deliver this data to the other player. And here comes the question.
I don't know how to implement a ChannelHandler in this situation, because in most examples, it seems that the data are not added dynamically by the handler. For instance, the data was created when channel was active by the method channelActive() or something else. All these methods was auto-invoked by Netty itself.
The only method I think is the write(). However, it seems that I have to call this method by myself if I implements this method, I don't know where I can get the parameter ChannelHandlerContext.
So, how to solve problems like this?
p.s.
I'm not so familiar with java network programming, nor the Netty. All the things I learn is based on the book, which I haven't finished reading yet. :)

Channel hander of Netty looks
package netty_sample;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
/**
* Server side action
*/
public class EchoServerHandler extends SimpleChannelHandler {
/**
* This method will be invoked when server recieved a message
*/
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) {
String msg = (String) event.getMessage(); // extract a message received
// You can write any code which handles the message, changes data, and create message for client, etc.
ctx.getChannel().write(someMessageToClient); // send back to client
}
}
As I understand, handler routine is invoked dynamically (in event-driven) when server received a message.
So code in the handler works dynamically, and you can write anything in the code.

Related

Reactor / WebFlux implement a reactive http news ticker

I have a request that is rather simple to formulate, but I cannot pull it of without leaking resources.
I want to return a response of type application/stream+json, featuring news events someone posted. I do not want to use Websockets, not because I don't like them, I just want to know how to do it with a stream.
For this I need to return a Flux<News> from my restcontroller, that is continuously fed with news, once someone posts any.
My attempt for this was creating a Publisher:
public class UpdatePublisher<T> implements Publisher<T> {
private List<Subscriber<? super T>> subscribers = new ArrayList<>();
#Override
public void subscribe(Subscriber<? super T> s) {
subscribers.add(s);
}
public void pushUpdate(T message) {
subscribers.forEach(s -> s.onNext(message));
}
}
And a simple News Object:
public class News {
String message;
// Constructor, getters, some properties omitted for readability...
}
And endpoints to publish news respectively get the stream of news
// ...
private UpdatePublisher<String> updatePublisher = new UpdatePublisher<>();
#GetMapping(value = "/news/ticker", produces = "application/stream+json")
public Flux<News> getUpdateStream() {
return Flux.from(updatePublisher).map(News::new);
}
#PutMapping("/news")
public void putNews(#RequestBody News news) {
updatePublisher.pushUpdate(news.getMessage());
}
This WORKS, but I cannot unsubscribe, or access any given subscription again - so once a client disconnects, the updatePublisher will just continue to push onto a growing number of dead channels - as I have no way to call the onCompleted() handler on the subscriptions.
TL;DL:
Can one push messages onto a possible endless Flux from a different thread and still terminate the Flux on demand without relying on a reset by peer exception or something along those lines?
You should never try to implement yourself the Publisher interface, as it boils down to getting the reactive streams implementation right. This is exactly the issue you're facing here.
Instead you should use one of the generator operators provided by Reactor itself (this is actually a Reactor question, nothing specific to Spring WebFlux).
In this case, Flux.create or Flux.push are probably the best candidates, given your code uses some type of event listener to push events down the stream. See the reactor project reference documentation on that.
Without more details, it's hard to give you a concrete code sample that solves your problem. Here are a few pointers though:
you might want to .share() the stream of events for all subscribers if you'd like some multicast-like communication pattern
pay attention to the push/pull/push+pull model that you'd like to have here; how is the backpressure supposed to work here? What if we produce more events that the subscribers can handle?
this model would only work on a single application instance. If you'd like this to work on multiple application instances, you might want to look into messaging patterns using a broker

Using netty with business logic

I'm not too experienced using netty and have a question about the documentation of ChannelPipeline. Here is what it is about exactly:
static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
...
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
// Tell the pipeline to run MyBusinessLogicHandler's event handler methods
// in a different thread than an I/O thread so that the I/O thread is not blocked by
// a time-consuming task.
// If your business logic is fully asynchronous or finished very quickly, you don't
// need to specify a group.
pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
I don't quite understand the MyBusinessLogicHandler class. Should it implement DuplexChannelHandler or something different? For instance, in my particular case I have the following class:
public class Packet{}
I want to decode some byte sequence into Packet, give to MyBusinessLogicHandler which produces some Packet. and then encode it into a byte stream again to send back to a client. I currently see it like this:
public class MyBusinessLogicHandler extends SimpleChannelInboundHandler<MyModel>{
public void channelRead0(ChannelHandlerContext ctx, Packet msg){
Packet rslt = null;
//Do some complicated business logic
ctx.write(rslt);
}
}
I'm not sure if it's a common way to do things in netty. Can you clarify please?
Yeap. That's totally fine and correct way for implementing MyBusinessLogicHandler. You don't need DuplexChannelHandler as in your pipeline you have already MyProtocolEncoder (that I suppose implements ChannelOutboundHandler).
So when you call ctx.write(rslt) you trigger write event for outbound handlers.
DuplexChannelHandler would be useful only in case you would like to implement both encoder and decoder in the same class. For example, you may do that by joining MyProtocolEncoder and MyProtocolDecoder.

How to execute asynchronous database insert in Actor's onReceive method?

I have a Play framework 2 application that also uses Akka. I have an Actor that receives messages from a remote system, the amount of such messages can be very huge. After a message is received, i log it into the database (using the built-in Ebean ORM) and then continue to process it. I don't care, how fast this database logging works, but it definitely should not block the further processing. Here is a simplified code sample:
public class MessageReceiver extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
if (message instanceof ServerMessage) {
ServerMessage serverMessage = (ServerMessage) message;
ServerMessageModel serverMessageModel = new ServerMessageModel(serverMessage);
serverMessageModel.save();
//now send the message to another actor for further processing
} else {
unhandled(message);
}
}
}
As i understand, database inserting is blocking in this realization, so it does not meet my needs. But i can't figure out how to make it unblocking. I've read about the Future class, but i can't get it to work, since it should return some value, and serverMessageModel.save(); returns void.I understand that writing a lot of messages one-by-one into the database is unefficient, but that is not the issue at the moment.
Am i right that this implementation is blocking? If it is, how can i make it run asynchronously?
Future solution seems good to me. I haven't used Futures from Java, but you can just return arbitrary Integer or String if you definitely need some return value.
Other option is to send that message to some other actor which would do the saving to the DB. Then you should make sure that the mailbox of that actor would not overfill.
Have you considered akka-persistence for this? Maybe that would suit your use-case.
If you wish to use Future - construct an Akka Future with a Callable (anonymous class), whose apply() will actually implement the db save code. You can actually put all of this (future creation and apply()) in your ServerMessageModel class -- maybe call it asynchSave(). Your Future maybe Future where status is the result of asynchSave...
public Future<Status> asyncSave(...) { /* should the params be ServerMessageModel? */
return future(new Callable<Status>() {
public Status call() {
/* do db work here */
}
}
In your onReceive you can go ahead with tell to the other actor. NOTE: if you want to make sure that you are firing the tell to the other actor after this future returns, then you could use Future's onSuccess.
Future<Status> f = serverMessageModel.asyncSave();
f.onSuccess(otherActor.tell(serverMessage, self());
You can also do failure handling... see http://doc.akka.io/docs/akka/2.3.4/java/futures.html for further details.
Hope that helps.
Persist actor state with Martin Krassers akka-persistence extension and my jdbc persistence provider akka persistence jdbc https://github.com/dnvriend/akka-persistence-jdbc

Desktop program communicating with server

I am in the process of moving the business logic of my Swing program onto the server.
What would be the most efficient way to communicate client-server and server-client?
The server will be responsible for authentication, fetching and storing data, so the program will have to communication frequently.
it depends on a lot of things. if you want a real answer, you should clarify exactly what your program will be doing and exactly what falls under your definition of "efficient"
if rapid productivity falls under your definition of efficient, a method that I have used in the past involves serialization to send plain old java objects down a socket. recently I have found that, in combination with the netty api, i am able to rapidly prototype fairly robust client/server communication.
the guts are fairly simple; the client and server both run Netty with an ObjectDecoder and ObjectEncoder in the pipeline. A class is made for each object designed to handle data. for example, a HandshakeRequest class and HandshakeResponse class.
a handshake request could look like:
public class HandshakeRequest extends Message {
private static final long serialVersionUID = 1L;
}
and a handshake response may look like:
public class HandshakeResponse extends Message {
private static final long serialVersionUID = 1L;
private final HandshakeResult handshakeResult;
public HandshakeResponse(HandshakeResult handshakeResult) {
this.handshakeResult = handshakeResult;
}
public HandshakeResult getHandshakeResult() {
return handshakeResult;
}
}
in netty, the server would send a handshake request when a client connects as such:
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel ch = e.getChannel();
ch.write(new HandshakeRequest();
}
the client receives the HandshakeRequest Object, but it needs a way to tell what kind of message the server just sent. for this, a Map<Class<?>, Method> can be used. when your program is run, it should iterate through the Methods of a class with reflection and place them in the map. here is an example:
public HashMap<Class<?>, Method> populateMessageHandler() {
HashMap<Class<?>, Method> temp = new HashMap<Class<?>, Method>();
for (Method method : getClass().getMethods()) {
if (method.getAnnotation(MessageHandler.class) != null) {
Class<?>[] methodParameters = method.getParameterTypes();
temp.put(methodParameters[1], method);
}
}
return temp;
}
this code would iterate through the current class and look for methods marked with an #MessageHandler annotation, then look at the first parameter of the method (the parameter being an object such as public void handleHandshakeRequest(HandshakeRequest request)) and place the class into the map as a key with the actual method as it's value.
with this map in place, it is very easy to receive a message and send the message directly to the method that should handle the message:
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
try {
Message message = (Message) e.getMessage();
Method method = messageHandlers.get(message.getClass());
if (method == null) {
System.out.println("No handler for message!");
} else {
method.invoke(this, ctx, message);
}
} catch(Exception exception) {
exception.printStackTrace();
}
}
there's not really anything left to it. netty handles all of the messy stuff allowing us to send serialized objects back and forth with ease. if you decide that you do not want to use netty, you can wrap your own protocol around java's Object Output Stream. you will have to do a little bit more work overall, but the simplicity of communication remains intact.
It's a bit hard to say which method is "most efficient" in terms of what, and I don't know your use cases, but here's a couple of options:
The most basic way is to simply use "raw" TCP-sockets. The upside is that there's nothing extra moving across the network and you create your protocol yourself, the latter being also a downside; you have to design and implement your own protocol for the communication, plus the basic framework for handling multiple connections in the server end (if there is a need for such).
Using UDP-sockets, you'll probably save a little latency and bandwidth (not much, unless you're using something like mobile data, you probably won't notice any difference with TCP in terms of latency), but the networking code is a bit harder task; UDP-sockets are "connectionless", meaning all the clients messages will end up in the same handler and must be distinguished from one another. If the server needs to keep up with client state, this can be somewhat troublesome to implement right.
MadProgrammer brought up RMI (remote method invocation), I've personally never used it, and it seems a bit cumbersome to set up, but might be pretty good in the long run in terms of implementation.
Probably one of the most common ways is to use http for the communication, for example via REST-interface for Web services. There are multiple frameworks (I personally prefer Spring MVC) to help with the implementation, but learning a new framework might be out of your scope for now. Also, complex http-queries or long urls could eat your bandwidth a bit more, but unless we're talking about very large amounts of simultaneous clients, this usually isn't a problem (assuming you run your server(s) in a datacenter with something like 100/100MBit connections). This is probably the easiest solution to scale, if it ever comes to that, as there're lots of load-balancing solutions available for web servers.

Java Message Distribution / Subscription?

I am creating a set of widgets in Java that decodes and displays messages received at a serial interface.
The message type is defined by a unique identifier.
Each widget is only interested in a particular identifier.
How to I program the application in a way to distribute the messages correctly to the relevant widgets?
If this is for a single app (i.e. a main and couple of threads), JMS is overkill.
The basics of this is a simple queue (of which Java has several good ones, BlockingQueue waving its hand in the back over there).
The serial port reads its data, formats a some relevant message object, and dumps it on a central Message Queue. This can be as simple as a BlockingQueue singleton.
Next, you'll need a queue listener/dispatcher.
This is a separate thread that sits on the queue, waiting for messages.
When it gets a message it then dispatches it to the waiting "widgets".
How it "knows" what widgets get what is up to you.
It can be a simple registration scheme:
String messageType = "XYZ";
MyMessageListener listener = new MyMessageListener();
EventQueueFactory.registerListener(messageType, listener);
Then you can do something like:
public void registerListener(String type, MessageListener listener) {
List<MessageListener> listeners = registrationMap.get(type);
if (listeners == null) {
listeneres = new ArrayList<MessageListener>();
registrationMap.put(type, listeners);
}
listeners.add(listener);
}
public void dispatchMessage(Message msg) {
List<MessageListener> listeners = registrationMap.get(type);
if (listeners != null) {
for(MessageListener listener : listeners) {
listener.send(msg);
}
}
}
Also, if you're using Swing, it has a whole suite of Java Bean property listeners and what not that you could leverage as well.
That's the heart of it. That should give you enough rope to keep you in trouble.
sounds like a jms topic/subscription. why reinvent the wheel?
One easy way to do this is to add each widget to a map by ID, and to provide each message to the widget by pulling it out of the map and calling some method on it. This means that each widget has to implement an interface that you can call to display the message. If the widgets are not in your control, then you can create a thin wrapper class (implementing an interface) and add this wrapper class -- with a widget -- to the map, one instance per ID.

Categories

Resources