Java tutorial
/* * Copyright (c) 2015-2016. Ventu.io, Oleg Sklyar and contributors, distributed under the MIT license. */ package io.ventu.rpc.integration.rest; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.ventu.rpc.RemoteInvoker; import io.ventu.rpc.exception.ApiException; import io.ventu.rpc.exception.EncodingException; import io.ventu.rpc.rest.HttpRestInvoker; import io.ventu.rpc.rest.exception.HttpException; import io.ventu.rpc.util.Validator; import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerResponse; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static org.junit.Assert.assertEquals; /** * The tests is explicitly put into a different package from the implementation to test the client * under "real-life" conditions. */ public class TestRestInvocationRoundtrip { @Rule public ExpectedException exception = ExpectedException.none(); private static Vertx vertx = Vertx.vertx(); private static HttpServer server; public static class Req { public int value; protected Req() { } public Req(int value) { this.value = value; } } public static class Res { public int value; protected Res() { } public Res(int value) { this.value = value; } } public static class Unsupported { public int value; protected Unsupported() { } public Unsupported(int value) { this.value = value; } } public static class Invalid { protected int value; public Invalid(int value) { this.value = value; } } @BeforeClass public static void init() throws InterruptedException { server = vertx.createHttpServer(); server.requestHandler(request -> { HttpServerResponse response = request.response(); try { if (!"123".equals(request.headers().get("APIKEY"))) { response.setStatusCode(401).end(); return; } Object res; if (request.uri().endsWith("Unsupported")) { res = new Invalid(123); } else { res = new Res(29); } response.putHeader("Content-type", "application/json") .end(new ObjectMapper().writeValueAsString(res)); } catch (JsonProcessingException ex) { response.setStatusCode(500).end(); } }); server.listen(23332); Thread.sleep(500); } @AfterClass public static void teardown() { server.close(); } @Test public void invoke_basicRoundtrip_success() throws InterruptedException, TimeoutException, ExecutionException { RemoteInvoker invoker = HttpRestInvoker.host("localhost").port(23332).ssl(false).header("APIKEY", "123") .build(); try { CompletableFuture<Res> future = invoker.invoke(new Req(25), Res.class); Res res = future.get(500, TimeUnit.MILLISECONDS); assertEquals(29, res.value); } finally { invoker.close().get(500, TimeUnit.MILLISECONDS); } } @Test public void invoke_basicRoundtrip_server401_error() throws InterruptedException, TimeoutException, ExecutionException { RemoteInvoker invoker = HttpRestInvoker.host("localhost").port(23332).ssl(false).build(); try { CompletableFuture<Res> future = invoker.invoke(new Req(25), Res.class); exception.expect(ExecutionException.class); future.get(500, TimeUnit.MILLISECONDS); } catch (ExecutionException ex) { HttpException cause = (HttpException) ex.getCause(); assertEquals(401, cause.getStatusCode()); throw ex; } finally { invoker.close().get(500, TimeUnit.MILLISECONDS); } } @Test public void invoke_basicRoundtrip_server500_error() throws InterruptedException, TimeoutException, ExecutionException { RemoteInvoker invoker = HttpRestInvoker.host("localhost").port(23332).header("APIKEY", "123").ssl(false) .build(); try { CompletableFuture<Res> future = invoker.invoke(new Unsupported(25), Res.class); exception.expect(ExecutionException.class); future.get(500, TimeUnit.MILLISECONDS); } catch (ExecutionException ex) { HttpException cause = (HttpException) ex.getCause(); assertEquals(500, cause.getStatusCode()); throw ex; } finally { invoker.close().get(500, TimeUnit.MILLISECONDS); } } @Test public void invoke_basicRoundtrip_responseValidator_error() throws InterruptedException, TimeoutException, ExecutionException { RemoteInvoker invoker = HttpRestInvoker.host("localhost").port(23332).header("APIKEY", "123").ssl(false) .responseValidator(new Validator() { @Override public <RS> void validate(RS value) throws ApiException, IllegalArgumentException { throw new ApiException("boom"); } }).build(); try { CompletableFuture<Res> future = invoker.invoke(new Req(25), Res.class); exception.expect(ExecutionException.class); future.get(500, TimeUnit.MILLISECONDS); } catch (ExecutionException ex) { ApiException cause = (ApiException) ex.getCause(); assertEquals("boom", cause.getMessage()); throw ex; } finally { invoker.close().get(500, TimeUnit.MILLISECONDS); } } @Test public void invoke_invalidRequest_error() throws InterruptedException, TimeoutException, ExecutionException { RemoteInvoker invoker = HttpRestInvoker.host("localhost").port(23332).ssl(false).build(); try { CompletableFuture<Res> future = invoker.invoke(new Invalid(25), Res.class); exception.expect(ExecutionException.class); future.get(500, TimeUnit.MILLISECONDS); } catch (ExecutionException ex) { EncodingException cause = (EncodingException) ex.getCause(); assertEquals( "Failed to encode JSON: No serializer found for class io.ventu.rpc.integration.rest.TestRestInvocationRoundtrip$Invalid and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )", cause.getMessage()); throw ex; } finally { invoker.close().get(500, TimeUnit.MILLISECONDS); } } }