3

I have a web application built using nodejs. The backend is calling several java command lines to answer queries. Those java programs are relying on models that are quite huge (around 50Mo), and for each java command line executed the model needs to be reloaded. In the end, most of the answer time is spent on loading these models in RAM.

What I would like to do is to set-up a java server along with the nodejs one, and make those two servers communicate. The java server would keep the models in RAM and handle all the java processing. The problem is that node is asynchronous and I would like to fire a callback when my java server ended processing the data. Do you know any good way to do this? Would it be possible to send some sort of POST request from node to java on localhost?

EDIT:

Ok since jfriend00 and Pelit Mamani answered me I've made some progress. I decided to go with jfriend00's solution to use socket.io. Here is exactly what I would like to do (here in javascript):

  • I have a server (the one that I would like to have in Java, here in javascript)

    var http = require('http');
    
    console.log('Creating HTTP server');
    
    var server = http.createServer(function(req, res){
    });
    
    var io = require('socket.io').listen(server);
    
    io.sockets.on('connection', function(socket) { 
    
        console.log('Client connected.');
    
        // Disconnect listener
        socket.on('disconnect', function() {
            console.log('Client disconnected.');
        });
    
        socket.on('myEvent', function (data, fn) {
            console.log(data);
            console.log('\tSending answer ...');
            fn('\tI am the answer');
        });
    });
    
    server.listen(8080);
    
  • And I have a client (in my case it will be my nodejs server):

    // Connect to server
    var io = require('socket.io-client')
    var socket = io.connect('http://localhost:8080');
    
    socket.on('connect', function () {
    
        console.log('Connected!\n\tSending query ...');
    
        socket.emit('myEvent', '\tI am the query', function (data) {
          console.log(data); 
        });
    
    });
    

The client send a query, the server answer the query, simple. I'm using netty-socketio to implement the server part in java. Here is what I have right now:

import java.io.UnsupportedEncodingException;

import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.Transport;
import com.corundumstudio.socketio.listener.*;

public class App {

    public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {

        Configuration config = new Configuration();
        config.setHostname("localhost");
        config.setPort(8080);

        final SocketIOServer server = new SocketIOServer(config);

        server.addConnectListener(new ConnectListener() {
            @Override
            public void onConnect(SocketIOClient client) {
                System.out.println("client connected !: "+client.toString());
            }
        });

        server.addEventListener("myEvent", String.class, new DataListener<String>() {
            @Override
            public void onData(final SocketIOClient client, String data, final AckRequest ackRequest) {
                System.out.println("myEvent triggered");

                System.out.println("Here is the query from the client: \n"+data);

                ackRequest.sendAckData("I am the answer from the Server!");
            }
        });

        server.addDisconnectListener(new DisconnectListener() {
            @Override
            public void onDisconnect(SocketIOClient client) {
                System.out.println("client disconnected !: "+client.toString());
            }
        });

        server.start();
        System.out.println("server started");

        Thread.sleep(20000);//Integer.MAX_VALUE);

        server.stop();
        System.out.println("server stopped");
    }

}

When running this server with my javascript client, everything is working:

  • On the client side:

    Connected!
        Sending query ...
    I am the answer from the Server!
    
  • On the server side:

    server started
    client connected !: com.corundumstudio.socketio.transport.NamespaceClient@ecac7898
    myEvent triggered
    Here is the query from the client: 
        I am the query
    client disconnected !: com.corundumstudio.socketio.transport.NamespaceClient@ecac7898
    

But I don't think AckRequest should be used to send data like that. I will probably change for another implementation. To be continued...

user3091275
  • 1,013
  • 2
  • 11
  • 27
  • 1
    The nodejs server and Java server can communicate asynchronously with any common networking technology (http request, socket.io message, your own custom TCP protocol, etc...). I don't understand why you think the async nature of nodejs causes an issue for you as all networking is already async anyway. You just have the Java server send a message back to the nodejs server when it is done processing and the nodejs server can then call some callback that was previously registered. – jfriend00 Jun 07 '15 at 07:54
  • The point where I am confused is on how my java server send a message back to node and trigger some callback. This is my first web app, first nodejs server and first java server, if you could point me towards some sample code it would be much appreciated. – user3091275 Jun 07 '15 at 08:39
  • 2
    As I said, there are a variety of communication mechanisms you can use. A relatively simple message-based solution would be a socket.io connection between the two. Then, you can just send a message from nodejs server to the Java process when you want to initiate some action and then the Java server sends a message back when it has finished. There are multiple socket.io implementations for Java [here](http://stackoverflow.com/questions/5972267/standalone-socket-io-server-in-java) and [here](https://www.google.com/search?q=java+websocket+server+example). – jfriend00 Jun 07 '15 at 16:06
  • And, an example of using a nodejs server as the socket.io client to connect to another socket.io server [here](http://stackoverflow.com/questions/8837236/how-to-connect-two-node-js-servers-with-websockets). – jfriend00 Jun 07 '15 at 16:07

1 Answers1

1
  1. If you use http or tcp, the fact that node.js is asynchronous doesn't prevent the java side from working "synchronously"... e.g. if you have a standard Servlet that reads a request and writes a reply (on the same thread) , it would still translate to standard asynchronous code on node.js side. It would send the request, then get a callback when java answers...

  2. As a side note, you might also want to have a look on asynchronous Queuing protocols such as Rabbit MQ, but that goes beyond the basic requirements you described. E.g. it depends on how reliable you need the communication to be, what happens if the java server crashes, etc.

Pelit Mamani
  • 2,321
  • 2
  • 13
  • 11
  • Thanks for your answer. I am very new to all this, I already tried using TCP. With TCP, when my java server receive data, he has no clue who sent it, all the data is presented as a big stream and I can have multiple requests concatenated. I need to split my data and queue it before processing it synchronously. When the processing is done, I want to fire a specific callback, but I have no clue who sent the data, due to the asynchronous behavior of node I cannot identify a process by observing the order in which I received the data. I have no clue how to fire the appropriate callback. – user3091275 Jun 07 '15 at 08:59
  • It's hard to be accurate without exact code, but it boils down to either of 2 options: (1) if your java works synchronously, meaning the request connection (through which client sent its request) remains open awaiting a reply, then it's up to you to make sure your internal code has access to the response output stream of that same connection. E.g propagate it throughout your internal methods (2) If you use some asynchronous protocol such as Rabbit, meaning your request connection might be lost - then you'll have no choice but to change the design so that you know the origin of the request. – Pelit Mamani Jun 07 '15 at 09:17