I have a server application that listens on a ServerSocket for incoming queries. The clients submitting the queries expect to open a socket to the server, pass their query upstream, and then (possibly after a short period of time) read the response to their query from the same socket that they used to submit the query.
For this I am trying to use an ExecutorCompletionService. Different query classes are passed to different Callables, but all are expected to return a String as their result.
All of this is quite manageable until I reach the stage of actually trying to reply to the clients. The Future objects are currently all of type Future<String>, but I am unable to marry that result (the String) up to the appropriate Socket.
My solution is about to be to make all of my Callables be of type Callable<StringSocketPair> where StringSocketPair looks like;
public class StringSocketPair {
Socket sock;
String content;
}
But this all seems a little odd, as now I have to pass the Socket to the Callable constructor, so that it can return it alongside the String result from its call() method. All so that I can push the String onto the Socket in yet another thread which polls ExecutorCompletionService.take().
The other option is to use Runnables instead of Callables and have each Runnable task respond on its own Socket, but as I have a dozen or so query types, each has their own task object, and I’d rather not have to add a respondToClient() call of some kind to the end of every run() method for every task object.
There must be a simpler solution to what I would think is a fairly common setup?
Following the idea of using a
Runnable, you could use the Template Method Pattern to define the functionality for responding. This would prevent you from having to write that common code for every task as the common code would be placed in the abstract parent class which implements Runnable.Template Method Pattern:
Otherwise, you are probably right to change the Callable to return the tuple of response message and socket.