I'm sure that if you have used jsonrpc4j (outside a spring container) you will recognise the following standard pattern.
public class MyServletJsonRpc extends HttpServlet {
private MyService myService;
private JsonRpcServer jsonRpcServer;
@Override
protected void doPost(HttpServletRequest request
, HttpServletResponse response) throws IOException {
jsonRpcServer.handle(request, response);
}
@Override
public void init(ServletConfig config) {
myService = new MyServiceImpl();
jsonRpcServer = new JsonRpcServer(myService, MyService.class);
jsonRpcServer.set...
}
I am trying to create a log file containing all the JSON requests and JSON responses. i.e. I'd like to log the incoming JSON RPC request before it is deserialised and log the out going request just after it is serialised.
I've been reading through the code and there doesn't seem to be a nice easy way of doing this. Can anyone help?
The solution I have come up with (which works) uses a decorate of sorts but I'm not happy with it:
public class MyServletJsonRpc extends HttpServlet {
private MyService myService;
private JsonRpcServer jsonRpcServer;
@Override
protected void doPost(HttpServletRequest request
, HttpServletResponse response) throws IOException {
jsonRpcServer.handle(request, response);
}
@Override
public void init(ServletConfig config) {
myService = new MyServiceImpl();
ObjectMapper mapper = new MyObjectMapper(null, null, null);
jsonRpcServer = new MyJsonRpcServer(mapper, myService, null);
jsonRpcServer.set...
}
}
Using the following 2 overloaded classes:
class MyObjectMapper extends ObjectMapper {
private static final Logger L = LoggerFactory.getLogger(MyObjectMapper.class);
public MyObjectMapper(JsonFactory jf, DefaultSerializerProvider sp, DefaultDeserializationContext dc) {
super(jf, sp, dc);
}
@Override
public void writeValue(OutputStream out, Object value) throws IOException, JsonGenerationException,
JsonMappingException {
super.writeValue(out, value);
L.info("Out: " + writeValueAsString(value));
}
}
and
class MyJsonRpcServer extends JsonRpcServer {
private static final Logger L = LoggerFactory.getLogger(MyJsonRpcServer.class);
public MyJsonRpcServer(ObjectMapper mapper, Object handler, Class<?> remoteInterface) {
super(mapper, handler, remoteInterface);
}
@Override
public void handleNode(JsonNode node, OutputStream ops) throws IOException {
L.info("In: " + (node == null ? "(null)" : node.toString()));
super.handleNode(node, ops);
}
}
I think this looks and feels like a bit of a nasty hack. Is there a better way of doing this?
The library supports the use of an InvocationListener
: https://github.com/briandilley/jsonrpc4j/blob/master/src/main/java/com/googlecode/jsonrpc4j/InvocationListener.java
you can add it to the server in your servlets init()
method and all invocations will go through it.
here's the setter: https://github.com/briandilley/jsonrpc4j/blob/cfdaea92fedf7b43be9d93420df168fe69a5a4fa/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java#L994
So just call server.setInvocationListener
and you're good to go.