protected RequestMessage createRequestMessage(String method, Object parameter) { RequestMessage requestMessage = new RequestMessage(); requestMessage.setId(String.valueOf(nextRequestId.incrementAndGet())); requestMessage.setMethod(method); requestMessage.setParams(parameter); return requestMessage; }
protected Message createMessage(String jsonrpc, Either<String, Number> id, String method, Object params, Object responseResult, ResponseError responseError) throws JsonParseException { if (id != null && method != null) { RequestMessage message = new RequestMessage(); message.setJsonrpc(jsonrpc); message.setRawId(id); message.setMethod(method); message.setParams(params); return message; } else if (id != null) { ResponseMessage message = new ResponseMessage(); message.setJsonrpc(jsonrpc); message.setRawId(id); if (responseError != null) message.setError(responseError); else message.setResult(responseResult); return message; } else if (method != null) { NotificationMessage message = new NotificationMessage(); message.setJsonrpc(jsonrpc); message.setMethod(method); message.setParams(params); return message; } else { throw new JsonParseException("Unable to identify the input message."); } }
@Override protected DebugResponseMessage createResponseMessage(RequestMessage requestMessage) { DebugResponseMessage responseMessage = new DebugResponseMessage(); responseMessage.setResponseId(nextSeqId.incrementAndGet()); responseMessage.setRawId(requestMessage.getRawId()); responseMessage.setMethod(requestMessage.getMethod()); return responseMessage; }
@Override public CompletableFuture<Object> request(String method, Object parameter) { CompletableFuture<Object> completableFuture = new CompletableFuture<Object>(); requests.put(init(new RequestMessage(), it -> { it.setMethod(method); it.setParams(parameter); }), completableFuture); return completableFuture; }
@Test public void testRequest1() { TestEndpoint endp = new TestEndpoint(); TestMessageConsumer consumer = new TestMessageConsumer(); RemoteEndpoint endpoint = new RemoteEndpoint(consumer, endp); endpoint.consume(init(new RequestMessage(), it -> { it.setId("1"); it.setMethod("foo"); it.setParams("myparam"); })); Entry<RequestMessage, CompletableFuture<Object>> entry = endp.requests.entrySet().iterator().next(); entry.getValue().complete("success"); assertEquals("foo", entry.getKey().getMethod()); assertEquals("myparam", entry.getKey().getParams()); ResponseMessage responseMessage = (ResponseMessage) consumer.messages.get(0); assertEquals("success", responseMessage.getResult()); assertEquals(Either.forLeft("1"), responseMessage.getRawId()); }
@Test public void testEnumParamNull() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<MyEnum>>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [1, 2, null],\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(Arrays.asList(MyEnum.A, MyEnum.B, null), parameters); }
try { future = localEndpoint.request(requestMessage.getMethod(), requestMessage.getParams()); } catch (Throwable throwable) { final String messageId = requestMessage.getId(); synchronized (receivedRequestMap) { receivedRequestMap.put(messageId, future); String message = "The request (id: " + messageId + ", method: '" + requestMessage.getMethod() + "') has been cancelled"; ResponseError errorObject = new ResponseError(ResponseErrorCode.RequestCancelled, message, null); responseMessage = createErrorResponseMessage(requestMessage, errorObject);
@Test public void testRequestValidation() { ReflectiveMessageValidator validator = new ReflectiveMessageValidator(); RequestMessage message = new RequestMessage(); message.setId("1"); message.setParams(new Object()); try { validator.consume(message); Assert.fail(); } catch (MessageIssueException e) { Assert.assertEquals("The accessor 'RequestMessage.getMethod()' must return a non-null value. Path: $.method", e.getMessage()); } }
@Test public void testNullResponse() throws InterruptedException, ExecutionException { LogMessageAccumulator logMessages = new LogMessageAccumulator(); try { logMessages.registerTo(GenericEndpoint.class); Endpoint endpoint = ServiceEndpoints.toEndpoint(this); Map<String, JsonRpcMethod> methods = ServiceEndpoints.getSupportedMethods(LanguageServer.class); MessageJsonHandler handler = new MessageJsonHandler(methods); List<Message> msgs = new ArrayList<>(); MessageConsumer consumer = (message) -> { msgs.add(message); }; RemoteEndpoint re = new RemoteEndpoint(consumer, endpoint); RequestMessage request = new RequestMessage(); request.setId("1"); request.setMethod("shutdown"); re.consume(request); Assert.assertEquals("{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"result\":null}", handler.serialize(msgs.get(0))); msgs.clear(); shutdownReturn = new Object(); re.consume(request); Assert.assertEquals("{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"result\":{}}", handler.serialize(msgs.get(0))); } finally { logMessages.unregister(); } }
@Test public void testRequest() { TestEndpoint endp = new TestEndpoint(); TestMessageConsumer consumer = new TestMessageConsumer(); RemoteEndpoint endpoint = new DebugRemoteEndpoint(consumer, endp); endpoint.consume(new RequestMessage() {{ setId("1"); setMethod("foo"); setParams("myparam"); }}); Entry<RequestMessage, CompletableFuture<Object>> entry = endp.requests.entrySet().iterator().next(); entry.getValue().complete("success"); assertEquals("foo", entry.getKey().getMethod()); assertEquals("myparam", entry.getKey().getParams()); assertEquals("success", ((ResponseMessage)consumer.messages.get(0)).getResult()); }
@Override public String resolveMethod(String requestId) { synchronized (sentRequestMap) { PendingRequestInfo requestInfo = sentRequestMap.get(requestId); if (requestInfo != null) { return requestInfo.requestMessage.getMethod(); } } return null; }
@Override public boolean cancel(boolean mayInterruptIfRunning) { sendCancelNotification(requestMessage.getRawId()); return super.cancel(mayInterruptIfRunning); } };
/** * Send a request to the remote endpoint. */ @Override public CompletableFuture<Object> request(String method, Object parameter) { final RequestMessage requestMessage = createRequestMessage(method, parameter); final CompletableFuture<Object> result = new CompletableFuture<Object>() { @Override public boolean cancel(boolean mayInterruptIfRunning) { sendCancelNotification(requestMessage.getRawId()); return super.cancel(mayInterruptIfRunning); } }; synchronized(sentRequestMap) { // Store request information so it can be handled when the response is received sentRequestMap.put(requestMessage.getId(), new PendingRequestInfo(requestMessage, result)); } try { // Send the request to the remote service out.consume(requestMessage); } catch (Exception exception) { // The message could not be sent, e.g. because the communication channel was closed result.completeExceptionally(exception); } return result; }
@Test public void testRequest2() { TestEndpoint endp = new TestEndpoint(); TestMessageConsumer consumer = new TestMessageConsumer(); RemoteEndpoint endpoint = new RemoteEndpoint(consumer, endp); endpoint.consume(init(new RequestMessage(), it -> { it.setId(1); it.setMethod("foo"); it.setParams("myparam"); })); Entry<RequestMessage, CompletableFuture<Object>> entry = endp.requests.entrySet().iterator().next(); entry.getValue().complete("success"); assertEquals("foo", entry.getKey().getMethod()); assertEquals("myparam", entry.getKey().getParams()); ResponseMessage responseMessage = (ResponseMessage) consumer.messages.get(0); assertEquals("success", responseMessage.getResult()); assertEquals(Either.forRight(1), responseMessage.getRawId()); }
@Test public void testEnumParam() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<MyEnum>>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [1, 2, 3],\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(Arrays.asList(MyEnum.A, MyEnum.B, MyEnum.C), parameters); }
try { future = localEndpoint.request(requestMessage.getMethod(), requestMessage.getParams()); } catch (Throwable throwable) { final String messageId = requestMessage.getId(); synchronized (receivedRequestMap) { receivedRequestMap.put(messageId, future); String message = "The request (id: " + messageId + ", method: '" + requestMessage.getMethod() + "') has been cancelled"; ResponseError errorObject = new ResponseError(ResponseErrorCode.RequestCancelled, message, null); responseMessage = createErrorResponseMessage(requestMessage, errorObject);
@Override public String resolveMethod(String requestId) { synchronized (sentRequestMap) { PendingRequestInfo requestInfo = sentRequestMap.get(requestId); if (requestInfo != null) { return requestInfo.requestMessage.getMethod(); } } return null; }
@Override public boolean cancel(boolean mayInterruptIfRunning) { sendCancelNotification(requestMessage.getRawId()); return super.cancel(mayInterruptIfRunning); } };
/** * Send a request to the remote endpoint. */ @Override public CompletableFuture<Object> request(String method, Object parameter) { final RequestMessage requestMessage = createRequestMessage(method, parameter); final CompletableFuture<Object> result = new CompletableFuture<Object>() { @Override public boolean cancel(boolean mayInterruptIfRunning) { sendCancelNotification(requestMessage.getRawId()); return super.cancel(mayInterruptIfRunning); } }; synchronized(sentRequestMap) { // Store request information so it can be handled when the response is received sentRequestMap.put(requestMessage.getId(), new PendingRequestInfo(requestMessage, result)); } try { // Send the request to the remote service out.consume(requestMessage); } catch (Exception exception) { // The message could not be sent, e.g. because the communication channel was closed result.completeExceptionally(exception); } return result; }