I am new here so forgive me if I am not familiar with standard operating procedure, but I have researched this topic at length and haven't found a lot of info.
I am trying to implement a client in a Java Http Servlet that can subscribe to a server-sent-event stream and parse data from that stream. Every time I have a client POST a request to my Http servlet, I need to pass on some data from that client to another server and then open an SSE listener, as that is how the other server will notify me it has data for me to hand back to the client.
It needs to be asynchronous and probably multi-threaded because I will have many requests from the client happening in a short time frame and I need to catch every event coming back from the server. The data I pass back from the server to the client can be large so I need threading so I don't miss new events coming in.
I am at a loss for where to start. I have tried implementing some of the example code using the Jersey SSE API (https://jersey.java.net/documentation/latest/sse.html) but when I implement their asynchronous SSE event handling example, the events coming in happen too fast for my handler to process all the data back to the client and the function gets called again from a new event before it finishes, or at least that's what seems to be happening.
Here is a synopsis of what I have written so far:
Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
WebTarget target = client.target("Target URL");
EventSource eventSource = new EventSource(target) {
#Override
public void onEvent(InboundEvent inboundEvent){
if ("in".equals(inboundEvent.getName())) {
//Check if the event is of the type we care about
//If it is, open an input stream to read the payload and store in a byte array via an HttpURLConnection object
//Open an output stream and stream the payload to a client via an HttpServletResponse Object - This never seems to happen
}
}
};
}
I know it's sloppy, I'm not as familiar with Java so I am just piecing things together so I apologize for that.
This gets called from within my servlet class but it never makes it to the point where I write to the output stream, I think because it's getting interrupted by another event coming in. If anyone has insight into how I can make this work, or another way to do it, I would greatly appreciate it. Thanks.
I recommend you the JEaSSE library (Java Easy Server-Sent Events): http://mvnrepository.com/artifact/info.macias/jeasse
You can find some usage examples here:
https://github.com/mariomac/jeasse
Related
I am investigating a quite strange problem. The project I'm working on uses Spring-remoting to invoke methods over http. From what I have gathered so far the following happens:
My client code executes a request to the server
The server starts handling the request, but is slow
25-30 seconds later, a new request comes in to the server
The second request finishes, the client continues its processing
A while later, the first request get completed, but the client no longer cares
Since my client code executes only one request to the Spring remoting client, and the client continuous on after the second invocation it receives is completed, I can only conclude that this occurs somewhere in the Spring remoting client.
The client uses AbstractHttpInvokerRequestExecutor to make the actual http-invocation, and this in turn uses SimpleHttpInvokerRequestExecutor to make the request. But, from what I can read, this has no mechanism to retry the requests. So now I'm quite stuck.
Can anyone think of what might cause this behaviour? (I have tried to keep the question clean, but I have more details if needed.)
Just an idea to give you some direction, not necessarily a solution. Use a third party Http client (not one from Spring) to see if it changes a behavior. That might help you to see if it is SimpleHttpInvokerRequestExecutor that is "guilty" of re-try or something else. Here is a very simple 3d party HttpClient: Provided in MgntUtils Open source library (written by me). Very simple in use. Take a look at Javadoc. Library itself provided as Maven artifacts and on Git (including source code and Javadoc). All in all your code may look like this:
private static void testHttpClient() {
HttpClient client = new HttpClient();
client.setContentType("application/json");
String content = null;
try {
content = client.sendHttpRequest("http://www.google.com/", HttpMethod.GET);
//content holds the response. Do your logic here
} catch (IOException e) {
//Error Handling is here
content = TextUtils.getStacktrace(e, false);
}
}
I have an application using MQTT implemented with the paho-mqtt-1.0.2 and I am using ActiveMQ as the broker. I have a class implementing the MqttCallback, what I am wondering is why does the client hang
#Override
messageArrived(...)
do work
mqtt.publish(TOPIC,PAYLOAD,2,false) <- here
I want to send a "response" message to the broker for the next step of the work to be done. Similar to this, I read in the docs for that callback function
It is possible to send a new message within an implementation of this callback (for example, a response to this message), but the implementation must not disconnect the client, as it will be impossible to send an acknowledgment for the message being processed, and a deadlock will occur.
Has anyone out there tried doing the above and get it to work?
I also tried using the MqttAsyncClient and that ended up with
"Error too many publishes in progress" leading to undelivered messages.
I know how to get around this issue, I'm not looking for workaround; I'm looking for receiving and publishing on the thread where messageArrived() gets executed.
Happy Hunting!
The application that I am working on has two parts. The server part runs on a Linux machine. The client part, an Android application, queries the server and gets necessary response. Both the parts are written in Java, use socket-based communication, and transfer textual data.
Right after sending the request, here is how the client receives the response:
public static String ReadAvailableTextFromSocket(BufferedReader input) throws IOException {
if (input.ready() == false) {
return null;
}
StringBuilder retVal = new StringBuilder();
while(input.ready()) {
char ch = (char) input.read();
retVal.append(ch);
}
return retVal.toString();
}
However, this doesn't seem to be that reliable. The input is not always ready because of server response time or transmission delays.
Looks like input.ready() is not the right way to wait for getting data.
I am wondering if there is a better way to accomplish this. Perhaps there is some standard practice that I could use.
Perhaps you should use Threads. Keep a listener thread in a while(true) loop that reads more data as it comes in, and simply buffers the data in a data structure (let's say a queue) shared with the main thread. That way, the main thread could simply dequeue data as needed. If the queue is empty, it can infer that no new data was received.
Edit: see this multithreaded chat server/client code as an example.
Here is how I solved this problem. As I am responsible for writing both, the client side as well as the server side, when a request comes to the server, the first line of information I send as the response is the number of bytes the client can expect. This way, the client first waits to read a line. Once the line is read, the client now knows how many bytes of data to expect from the server.
Hope this helps others.
Regards,Peter
I have made an client - server example using netty.
I have defined handlers for the server and the client.
Basically I connect with the client to the server and send some messages.
Every received message gets send back (with the content of the message being converted to upper case).
All the work on the received messages, on server and client-side, is done by the defined handlers.
But I would like to use, or better receive/accept, some of the messages directly in the client
not (just) in the handler. So my question is is it possible to have some listener to receive messages directly in the client-program and not in its handlers. The thin is I would like to access the received messages within the (executable) program (basically the class with a main method) that created a new client object, using something like a timer which (or a loop) which would periodically check for new messages.
I would appreciate if someone could help me with this issue. Or at least tell me if its even possible with netty .
You're looking to translate netty's event-based model into a polling model. A simple way to do that is to create a message queue:
//import java.util.concurrent.BlockingQueue;
//import java.util.concurrent.LinkedBlockingQueue;
BlockingQueue queue = new LinkedBlockingQueue();
You need to make the queue available to your handler as a constructor argument, and when a message arrives you put it into the queue:
// Your netty handler:
queue.put(message);
On the client end, you can poll the queue for messages:
// The polling loop in your program:
message = queue.poll(5, TimeUnit.SECONDS);
The BlockingQueue offers you the choice between waiting for a message to arrive (take()), waiting a certain amount of time for a message to arrive (poll(long, TimeUnit)), or merely checking whether any message is available right now (poll()).
From a design perspective, this approach kills the non-blocking IO advantage netty is supposed to give you. You could have used a normal Socket connection for the same net result.
How can I do long-polling using netty framework? Say for example I fetch http://localhost/waitforx
but waitforx is asynchronous because it has to wait for an event? Say for example it fetches something from a blocking queue(can only fetch when data in queue). When getting item from queue I would like to sent data back to client. Hopefully somebody can give me some tips how to do this.
Many thanks
You could write a response header first, and then send the body (content) later from other thread.
void messageReceived(...) {
HttpResponse res = new DefaultHttpResponse(...);
res.setHeader(...);
...
channel.write(res);
}
// In a different thread..
ChannelBuffer partialContent = ...;
channel.write(partialContent);
You can use netty-socketio project. It's implementation of Socket.IO server with long polling support. On web side you can use Socket.IO client javascript lib.
You could also do the following in [sfnrpc]: http://code.google.com/p/sfnrpc
Object object = RPCClient.getInstance().invoke("#URN1","127.0.0.1:6878","echo",true,60,"", objArr,classArr, sl);
The true causes communication to be synchronous.