From dev-return-3402-archive-asf-public=cust-asf.ponee.io@servicecomb.apache.org Wed Apr 4 09:46:00 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 3399D18064F for ; Wed, 4 Apr 2018 09:45:59 +0200 (CEST) Received: (qmail 49167 invoked by uid 500); 4 Apr 2018 07:45:58 -0000 Mailing-List: contact dev-help@servicecomb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@servicecomb.apache.org Delivered-To: mailing list dev@servicecomb.apache.org Received: (qmail 49156 invoked by uid 99); 4 Apr 2018 07:45:57 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Apr 2018 07:45:57 +0000 From: GitBox To: dev@servicecomb.apache.org Subject: [GitHub] wujimin closed pull request #594: [SCB-379] support AsyncRestTemplate Message-ID: <152282795721.28005.12549279256413447465.gitbox@gitbox.apache.org> Date: Wed, 04 Apr 2018 07:45:57 -0000 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit wujimin closed pull request #594: [SCB-379] support AsyncRestTemplate URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/594 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java b/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java index 1d2e1baa8..a00dbbe9d 100644 --- a/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java +++ b/integration-tests/springmvc-tests/src/test/java/org/apache/servicecomb/demo/springmvc/tests/SpringMvcIntegrationTestBase.java @@ -50,6 +50,7 @@ import org.apache.servicecomb.demo.compute.Person; import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.provider.springmvc.reference.async.CseAsyncRestTemplate; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; @@ -65,6 +66,9 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; +import org.springframework.web.client.AsyncRestTemplate; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import org.springframework.web.client.UnknownHttpStatusCodeException; @@ -78,6 +82,8 @@ private final RestTemplate restTemplate = new RestTemplate(); + private final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(); + private final String codeFirstUrl = baseUrl + "codeFirstSpringmvc/"; private final String controllerUrl = baseUrl + "springmvc/controller/"; @@ -85,11 +91,12 @@ static void setUpLocalRegistry() { ClassLoader loader = Thread.currentThread().getContextClassLoader(); URL resource = loader.getResource("registry.yaml"); + assert resource != null; System.setProperty(LOCAL_REGISTRY_FILE_KEY, resource.getPath()); } @Test - public void ableToQueryAtRootBasePath() { + public void ableToQueryAtRootBasePath() throws Exception { ResponseEntity responseEntity = restTemplate .getForEntity(baseUrl + "sayHi?name=Mike", String.class); @@ -101,28 +108,51 @@ public void ableToQueryAtRootBasePath() { assertThat(responseEntity.getStatusCode(), is(OK)); assertThat(responseEntity.getBody(), is("Hi 小 强")); + + //integration test for AsyncRestTemplate + ListenableFuture> listenableFuture = asyncRestTemplate + .getForEntity(baseUrl + "sayHi?name=Mike", String.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getStatusCode(), is(OK)); + assertThat(futureResponse.getBody(), is("Hi Mike")); + + listenableFuture = asyncRestTemplate.getForEntity(baseUrl + "sayHi?name={name}", String.class, "小 强"); + futureResponse = listenableFuture.get(); + assertThat(futureResponse.getStatusCode(), is(OK)); + assertThat(futureResponse.getBody(), is("Hi 小 强")); } @Test - public void ableToQueryAtRootPath() { + public void ableToQueryAtRootPath() throws Exception { ResponseEntity responseEntity = restTemplate .getForEntity(baseUrl, String.class); assertThat(responseEntity.getStatusCode(), is(OK)); assertThat(responseEntity.getBody(), is("Welcome home")); + + ListenableFuture> listenableFuture = asyncRestTemplate.getForEntity(baseUrl, String.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getStatusCode(), is(OK)); + assertThat(futureResponse.getBody(), is("Welcome home")); } @Test - public void ableToQueryAtNonRootPath() { + public void ableToQueryAtNonRootPath() throws Exception { ResponseEntity responseEntity = restTemplate .getForEntity(baseUrl + "french/bonjour?name=Mike", String.class); assertThat(responseEntity.getStatusCode(), is(OK)); assertThat(responseEntity.getBody(), is("Bonjour Mike")); + + ListenableFuture> listenableFuture = asyncRestTemplate + .getForEntity(baseUrl + "french/bonjour?name=Mike", String.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getStatusCode(), is(OK)); + assertThat(futureResponse.getBody(), is("Bonjour Mike")); } @Test - public void ableToPostMap() { + public void ableToPostMap() throws Exception { Map users = new HashMap<>(); users.put("user1", userOfNames("name11", "name12")); users.put("user2", userOfNames("name21", "name22")); @@ -139,6 +169,17 @@ public void ableToPostMap() { Map body = responseEntity.getBody(); assertArrayEquals(body.get("user1").getNames(), new String[] {"name11", "name12"}); assertArrayEquals(body.get("user2").getNames(), new String[] {"name21", "name22"}); + + ListenableFuture>> listenableFuture = asyncRestTemplate + .exchange(codeFirstUrl + "testUserMap", + POST, + jsonRequest(users), + reference); + ResponseEntity> futureResponse = listenableFuture.get(); + assertThat(futureResponse.getStatusCode(), is(OK)); + body = futureResponse.getBody(); + assertArrayEquals(body.get("user1").getNames(), new String[] {"name11", "name12"}); + assertArrayEquals(body.get("user2").getNames(), new String[] {"name21", "name22"}); } private User userOfNames(String... names) { @@ -148,19 +189,24 @@ private User userOfNames(String... names) { } @Test - public void ableToConsumeTextPlain() { + public void ableToConsumeTextPlain() throws Exception { String body = "a=1"; - String result = restTemplate.postForObject( codeFirstUrl + "textPlain", body, String.class); assertThat(jsonOf(result, String.class), is(body)); + + HttpEntity entity = new HttpEntity<>(body); + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "textPlain", entity, String.class); + ResponseEntity responseEntity = listenableFuture.get(); + assertThat(jsonOf(responseEntity.getBody(), String.class), is(body)); } @Test - public void ableToPostBytes() throws IOException { + public void ableToPostBytes() throws Exception { byte[] body = new byte[] {0, 1, 2}; byte[] result = restTemplate.postForObject( @@ -174,10 +220,21 @@ public void ableToPostBytes() throws IOException { assertEquals(1, result[1]); assertEquals(2, result[2]); assertEquals(3, result.length); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "bytes", + jsonRequest(RestObjectMapper.INSTANCE.writeValueAsBytes(body)), + byte[].class); + ResponseEntity responseEntity = listenableFuture.get(); + result = RestObjectMapper.INSTANCE.readValue(responseEntity.getBody(), byte[].class); + assertEquals(1, result[0]); + assertEquals(1, result[1]); + assertEquals(2, result[2]); + assertEquals(3, result.length); } @Test - public void ableToUploadFile() throws IOException { + public void ableToUploadFile() throws Exception { String file1Content = "hello world"; String file2Content = "bonjour"; String username = "mike"; @@ -195,10 +252,17 @@ public void ableToUploadFile() throws IOException { String.class); assertThat(result, is(file1Content + file2Content + username)); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "upload", + new HttpEntity<>(map, headers), + String.class); + ResponseEntity responseEntity = listenableFuture.get(); + assertThat(responseEntity.getBody(), is(file1Content + file2Content + username)); } @Test - public void ableToUploadFileFromConsumer() throws IOException { + public void ableToUploadFileFromConsumer() throws Exception { String file1Content = "hello world"; String file2Content = "bonjour"; String username = "mike"; @@ -216,10 +280,17 @@ public void ableToUploadFileFromConsumer() throws IOException { String.class); assertThat(result, is(file1Content + file2Content + username)); + AsyncRestTemplate cseAsyncRestTemplate = new CseAsyncRestTemplate(); + ListenableFuture> listenableFuture = cseAsyncRestTemplate + .postForEntity("cse://springmvc-tests/codeFirstSpringmvc/upload", + new HttpEntity<>(map, headers), + String.class); + ResponseEntity responseEntity = listenableFuture.get(); + assertThat(responseEntity.getBody(), is(file1Content + file2Content + username)); } @Test - public void ableToUploadFileWithoutAnnotation() throws IOException { + public void ableToUploadFileWithoutAnnotation() throws Exception { String file1Content = "hello world"; String file2Content = "bonjour"; String username = "mike"; @@ -237,10 +308,17 @@ public void ableToUploadFileWithoutAnnotation() throws IOException { String.class); assertThat(result, is(file1Content + file2Content + username)); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "uploadWithoutAnnotation", + new HttpEntity<>(map, headers), + String.class); + ResponseEntity responseEntity = listenableFuture.get(); + assertThat(responseEntity.getBody(), is(file1Content + file2Content + username)); } @Test - public void blowsUpWhenFileNameDoesNotMatch() throws IOException { + public void blowsUpWhenFileNameDoesNotMatch() throws Exception { String file1Content = "hello world"; String file2Content = "bonjour"; @@ -277,44 +355,71 @@ public void ableToPostDate() throws Exception { seconds); assertThat(result, is(Date.from(date.plusSeconds(seconds).toInstant()))); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "addDate?seconds={seconds}", + new HttpEntity<>(body, headers), + Date.class, + seconds); + ResponseEntity dateResponseEntity = listenableFuture.get(); + assertThat(dateResponseEntity.getBody(), is(Date.from(date.plusSeconds(seconds).toInstant()))); } @Test - public void ableToDeleteWithQueryString() { + public void ableToDeleteWithQueryString() throws Exception { ResponseEntity responseEntity = restTemplate.exchange(codeFirstUrl + "addstring?s=a&s=b", HttpMethod.DELETE, null, String.class); assertThat(responseEntity.getBody(), is("ab")); + ListenableFuture> listenableFuture = asyncRestTemplate + .exchange(codeFirstUrl + "addstring?s=a&s=b", HttpMethod.DELETE, null, String.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getBody(), is("ab")); } @Test - public void ableToGetBoolean() { + public void ableToGetBoolean() throws Exception { boolean result = restTemplate.getForObject(codeFirstUrl + "istrue", boolean.class); assertThat(result, is(true)); + + ListenableFuture> listenableFuture = asyncRestTemplate + .getForEntity(codeFirstUrl + "istrue", boolean.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getBody(), is(true)); } @Test - public void putsEndWithPathParam() { + public void putsEndWithPathParam() throws Exception { ResponseEntity responseEntity = restTemplate .exchange(codeFirstUrl + "sayhi/{name}", PUT, null, String.class, "world"); assertThat(responseEntity.getStatusCode(), is(ACCEPTED)); assertThat(jsonOf(responseEntity.getBody(), String.class), is("world sayhi")); + + ListenableFuture> listenableFuture = asyncRestTemplate + .exchange(codeFirstUrl + "sayhi/{name}", PUT, null, String.class, "world"); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getStatusCode(), is(ACCEPTED)); + assertThat(jsonOf(futureResponse.getBody(), String.class), is("world sayhi")); } @Test - public void putsContainingPathParam() { + public void putsContainingPathParam() throws Exception { ResponseEntity responseEntity = restTemplate .exchange(codeFirstUrl + "sayhi/{name}/v2", PUT, null, String.class, "world"); assertThat(jsonOf(responseEntity.getBody(), String.class), is("world sayhi 2")); + ListenableFuture> listenableFuture = asyncRestTemplate + .exchange(codeFirstUrl + "sayhi/{name}/v2", PUT, null, String.class, "world"); + responseEntity = listenableFuture.get(); + assertThat(jsonOf(responseEntity.getBody(), String.class), is("world sayhi 2")); } @Test - public void ableToPostWithHeader() { + public void ableToPostWithHeader() throws Exception { Person person = new Person(); person.setName("person name"); @@ -327,10 +432,15 @@ public void ableToPostWithHeader() { .postForEntity(codeFirstUrl + "saysomething", requestEntity, String.class); assertThat(jsonOf(responseEntity.getBody(), String.class), is("prefix prefix person name")); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "saysomething", requestEntity, String.class); + responseEntity = listenableFuture.get(); + assertThat(jsonOf(responseEntity.getBody(), String.class), is("prefix prefix person name")); } @Test - public void ableToPostObjectAsJson() { + public void ableToPostObjectAsJson() throws Exception { Map personFieldMap = new HashMap<>(); personFieldMap.put("name", "person name from map"); @@ -343,10 +453,21 @@ public void ableToPostObjectAsJson() { person = restTemplate.postForObject(codeFirstUrl + "sayhello", jsonRequest(input), Person.class); assertThat(person.toString(), is("hello person name from Object")); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "sayhello", jsonRequest(personFieldMap), Person.class); + ResponseEntity futureResponse = listenableFuture.get(); + person = futureResponse.getBody(); + assertThat(person.toString(), is("hello person name from map")); + + listenableFuture = asyncRestTemplate.postForEntity(codeFirstUrl + "sayhello", jsonRequest(input), Person.class); + futureResponse = listenableFuture.get(); + person = futureResponse.getBody(); + assertThat(person.toString(), is("hello person name from Object")); } @Test - public void ableToPostForm() { + public void ableToPostForm() throws Exception { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("a", "5"); params.add("b", "3"); @@ -357,10 +478,15 @@ public void ableToPostForm() { .postForObject(codeFirstUrl + "add", new HttpEntity<>(params, headers), Integer.class); assertThat(result, is(8)); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(codeFirstUrl + "add", new HttpEntity<>(params, headers), Integer.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getBody(), is(8)); } @Test - public void ableToExchangeCookie() { + public void ableToExchangeCookie() throws Exception { Map params = new HashMap<>(); params.put("a", "5"); @@ -376,10 +502,20 @@ public void ableToExchangeCookie() { params); assertThat(result.getBody(), is(2)); + + ListenableFuture> listenableFuture = asyncRestTemplate + .exchange(codeFirstUrl + "reduce?a={a}", + GET, + requestEntity, + Integer.class, + params); + result = listenableFuture.get(); + assertThat(result.getBody(), is(2)); + } @Test - public void getsEndWithRequestVariables() { + public void getsEndWithRequestVariables() throws Exception { int result = restTemplate.getForObject( controllerUrl + "add?a={a}&b={b}", Integer.class, @@ -387,10 +523,17 @@ public void getsEndWithRequestVariables() { 4); assertThat(result, is(7)); + ListenableFuture> listenableFuture = asyncRestTemplate + .getForEntity(controllerUrl + "add?a={a}&b={b}", + Integer.class, + 3, + 4); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(futureResponse.getBody(), is(7)); } @Test - public void postsEndWithPathParam() { + public void postsEndWithPathParam() throws Exception { String result = restTemplate.postForObject( controllerUrl + "sayhello/{name}", null, @@ -411,10 +554,26 @@ public void postsEndWithPathParam() { assertThat(result, is("hello 中 国")); restTemplate.setMessageConverters(convertersOld); + + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(controllerUrl + "sayhello/{name}", + null, + String.class, + "world"); + ResponseEntity futureResonse = listenableFuture.get(); + assertThat(jsonOf(futureResonse.getBody(), String.class), is("hello world")); + asyncRestTemplate.setMessageConverters(converters); + listenableFuture = asyncRestTemplate.postForEntity(controllerUrl + "sayhello/{name}", + null, + String.class, + "中 国"); + futureResonse = listenableFuture.get(); + assertThat(futureResonse.getBody(), is("hello 中 国")); + asyncRestTemplate.setMessageConverters(convertersOld); } @Test - public void ableToPostObjectAsJsonWithRequestVariable() { + public void ableToPostObjectAsJsonWithRequestVariable() throws Exception { Person input = new Person(); input.setName("world"); @@ -441,15 +600,39 @@ public void ableToPostObjectAsJsonWithRequestVariable() { assertThat(result, is("hello 中国")); restTemplate.setMessageConverters(convertersOld); + + input.setName("world"); + ListenableFuture> listenableFuture = asyncRestTemplate + .postForEntity(controllerUrl + "saysomething?prefix={prefix}", + jsonRequest(input), + String.class, + "hello"); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(jsonOf(futureResponse.getBody(), String.class), is("hello world")); + + asyncRestTemplate.setMessageConverters(converters); + input.setName("中国"); + listenableFuture = asyncRestTemplate.postForEntity(controllerUrl + "saysomething?prefix={prefix}", + jsonRequest(input), + String.class, + "hello"); + futureResponse = listenableFuture.get(); + assertThat(futureResponse.getBody(), is("hello 中国")); + asyncRestTemplate.setMessageConverters(convertersOld); } @Test - public void ensureServerWorksFine() { + public void ensureServerWorksFine() throws Exception { String result = restTemplate.getForObject( controllerUrl + "sayhi?name=world", String.class); assertThat(jsonOf(result, String.class), is("hi world [world]")); + ListenableFuture> listenableFuture = asyncRestTemplate + .getForEntity(controllerUrl + "sayhi?name=world", + String.class); + ResponseEntity futureResponse = listenableFuture.get(); + assertThat(jsonOf(futureResponse.getBody(), String.class), is("hi world [world]")); } @Test @@ -477,6 +660,25 @@ public void ableToSetCustomHeader() { String.class); assertThat(jsonOf(result.getBody(), String.class), is("hei world")); + + ListenableFuture> listenableFuture = asyncRestTemplate.exchange(controllerUrl + "sayhei", + GET, + requestEntity, + String.class); +// ResponseEntity responseEntity = listenableFuture.get(); + listenableFuture.addCallback( + new ListenableFutureCallback>() { + @Override + public void onFailure(Throwable ex) { + } + + @Override + public void onSuccess(ResponseEntity result) { + assertThat(jsonOf(result.getBody(), String.class), is("hei world")); + } + } + ); + } private HttpEntity jsonRequest(T body) { diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java index 2ff0ca571..947469d3d 100644 --- a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/CseClientHttpRequest.java @@ -17,7 +17,6 @@ package org.apache.servicecomb.provider.springmvc.reference; -import java.io.IOException; import java.io.OutputStream; import java.net.URI; import java.util.List; @@ -73,6 +72,34 @@ public CseClientHttpRequest(URI uri, HttpMethod method) { this.method = method; } + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + protected RequestMeta getRequestMeta() { + return requestMeta; + } + + protected void setRequestMeta(RequestMeta requestMeta) { + this.requestMeta = requestMeta; + } + + public void setUri(URI uri) { + this.uri = uri; + } + + public void setMethod(HttpMethod method) { + this.method = method; + } + + protected void setQueryParams(Map> queryParams) { + this.queryParams = queryParams; + } + public InvocationContext getContext() { return context; } @@ -101,12 +128,12 @@ public HttpHeaders getHeaders() { } @Override - public OutputStream getBody() throws IOException { + public OutputStream getBody() { return null; } @Override - public ClientHttpResponse execute() throws IOException { + public ClientHttpResponse execute() { path = findUriPath(uri); requestMeta = createRequestMeta(method.name(), uri); @@ -119,7 +146,7 @@ public ClientHttpResponse execute() throws IOException { return this.invoke(args); } - private RequestMeta createRequestMeta(String httpMetod, URI uri) { + protected RequestMeta createRequestMeta(String httpMetod, URI uri) { String microserviceName = uri.getAuthority(); ReferenceConfig referenceConfig = ReferenceConfigUtils.getForInvoke(microserviceName); @@ -142,7 +169,7 @@ protected String findUriPath(URI uri) { return uri.getRawPath(); } - private CseClientHttpResponse invoke(Object[] args) { + protected Invocation prepareInvocation(Object[] args) { Invocation invocation = InvocationFactory.forConsumer(requestMeta.getReferenceConfig(), requestMeta.getOperationMeta(), @@ -153,22 +180,26 @@ private CseClientHttpResponse invoke(Object[] args) { if (context != null) { invocation.addContext(context); } - invocation.getHandlerContext().put(RestConst.CONSUMER_HEADER, httpHeaders); + return invocation; + } + + private CseClientHttpResponse invoke(Object[] args) { + Invocation invocation = prepareInvocation(args); Response response = doInvoke(invocation); if (response.isSuccessed()) { return new CseClientHttpResponse(response); } - throw ExceptionFactory.convertConsumerException((Throwable) response.getResult()); + throw ExceptionFactory.convertConsumerException(response.getResult()); } protected Response doInvoke(Invocation invocation) { return InvokerUtils.innerSyncInvoke(invocation); } - private Object[] collectArguments() { + protected Object[] collectArguments() { HttpServletRequest mockRequest = new CommonToHttpServletRequest(requestMeta.getPathParams(), queryParams, httpHeaders, requestBody, requestMeta.getSwaggerRestOperation().isFormData()); return RestCodec.restToArgs(mockRequest, requestMeta.getSwaggerRestOperation()); diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequest.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequest.java new file mode 100644 index 000000000..1be86dc88 --- /dev/null +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequest.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import java.io.OutputStream; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.common.rest.RestConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.provider.consumer.InvokerUtils; +import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequest; +import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpResponse; +import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.AsyncClientHttpRequest; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.concurrent.CompletableToListenableFutureAdapter; +import org.springframework.util.concurrent.ListenableFuture; + +import io.netty.handler.codec.http.QueryStringDecoder; + +public class CseAsyncClientHttpRequest extends CseClientHttpRequest implements AsyncClientHttpRequest { + + CseAsyncClientHttpRequest() { + } + + CseAsyncClientHttpRequest(URI uri, HttpMethod method) { + this.setUri(uri); + this.setMethod(method); + } + + @Override + public OutputStream getBody() { + return null; + } + + @SuppressWarnings("unchecked") + private ListenableFuture invoke(Object[] args) { + Invocation invocation = prepareInvocation(args); + invocation.getHandlerContext().put(RestConst.CONSUMER_HEADER, this.getHeaders()); + CompletableFuture clientHttpResponseCompletableFuture = doAsyncInvoke(invocation); + return new CompletableToListenableFutureAdapter(clientHttpResponseCompletableFuture); + } + + protected CompletableFuture doAsyncInvoke(Invocation invocation) { + CompletableFuture completableFuture = new CompletableFuture<>(); + InvokerUtils.reactiveInvoke(invocation, (Response response) -> { + if (response.isSuccessed()) { + completableFuture.complete(new CseClientHttpResponse(response)); + } else { + completableFuture.completeExceptionally(response.getResult()); + } + }); + return completableFuture; + } + + + @Override + public ListenableFuture executeAsync() { + this.setPath(findUriPath(this.getURI())); + this.setRequestMeta(createRequestMeta(this.getMethod().name(), this.getURI())); + QueryStringDecoder queryStringDecoder = new QueryStringDecoder(this.getURI().getRawSchemeSpecificPart()); + this.setQueryParams(queryStringDecoder.parameters()); + Object[] args = this.collectArguments(); + return this.invoke(args); + } +} diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestFactory.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestFactory.java new file mode 100644 index 000000000..d27cf78bb --- /dev/null +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import java.net.URI; + +import org.springframework.http.HttpMethod; +import org.springframework.http.client.AsyncClientHttpRequest; +import org.springframework.http.client.AsyncClientHttpRequestFactory; + +public class CseAsyncClientHttpRequestFactory implements AsyncClientHttpRequestFactory { + @Override + public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) { + return new CseAsyncClientHttpRequest(uri, httpMethod); + } +} diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRequestCallback.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRequestCallback.java new file mode 100644 index 000000000..1ca4b4c2a --- /dev/null +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRequestCallback.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity; +import org.springframework.http.HttpEntity; +import org.springframework.http.client.AsyncClientHttpRequest; +import org.springframework.web.client.AsyncRequestCallback; + +public class CseAsyncRequestCallback implements AsyncRequestCallback { + private HttpEntity requestBody; + + CseAsyncRequestCallback(HttpEntity requestBody) { + this.requestBody = requestBody; + } + + @Override + public void doWithRequest(AsyncClientHttpRequest request) { + CseAsyncClientHttpRequest cseAsyncClientHttpRequest = (CseAsyncClientHttpRequest) request; + if (requestBody != null) { + cseAsyncClientHttpRequest.setRequestBody(requestBody.getBody()); + } + + if (!CseHttpEntity.class.isInstance(requestBody)) { + return; + } + + CseAsyncClientHttpRequest req = (CseAsyncClientHttpRequest) request; + CseHttpEntity entity = (CseHttpEntity) requestBody; + req.setContext(entity.getContext()); + } +} diff --git a/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java new file mode 100644 index 000000000..6f16f997e --- /dev/null +++ b/providers/provider-springmvc/src/main/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplate.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import java.lang.reflect.Type; +import java.util.Arrays; + +import org.apache.servicecomb.provider.springmvc.reference.CseUriTemplateHandler; +import org.springframework.http.HttpEntity; +import org.springframework.web.client.AsyncRequestCallback; +import org.springframework.web.client.AsyncRestTemplate; +import org.springframework.web.client.CseHttpMessageConverter; + +public class CseAsyncRestTemplate extends AsyncRestTemplate { + public CseAsyncRestTemplate() { + setMessageConverters(Arrays.asList(new CseHttpMessageConverter())); + setAsyncRequestFactory(new CseAsyncClientHttpRequestFactory()); + setUriTemplateHandler(new CseUriTemplateHandler()); + } + + @Override + @SuppressWarnings("unchecked") + protected AsyncRequestCallback httpEntityCallback(HttpEntity requestBody) { + return new CseAsyncRequestCallback(requestBody); + } + + @Override + @SuppressWarnings("unchecked") + protected AsyncRequestCallback httpEntityCallback(HttpEntity requestBody, Type responseType) { + return new CseAsyncRequestCallback(requestBody); + } +} \ No newline at end of file diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestFactoryTest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestFactoryTest.java new file mode 100644 index 000000000..ce10009a0 --- /dev/null +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestFactoryTest.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import java.net.URI; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.http.HttpMethod; + +public class CseAsyncClientHttpRequestFactoryTest { + @Test + public void testCseAsyncClientHttpRequestFactory() { + CseAsyncClientHttpRequestFactory cseAsyncClientHttpRequestFactory = new CseAsyncClientHttpRequestFactory(); + Assert.assertEquals(HttpMethod.GET, + cseAsyncClientHttpRequestFactory.createAsyncRequest(URI.create("/test"), HttpMethod.GET).getMethod()); + } +} \ No newline at end of file diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java new file mode 100644 index 000000000..4ae2bc703 --- /dev/null +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncClientHttpRequestTest.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import java.net.URI; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; + +import javax.xml.ws.Holder; + +import org.apache.servicecomb.common.rest.RestEngineSchemaListener; +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.core.CseContext; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.core.provider.consumer.ReferenceConfigUtils; +import org.apache.servicecomb.core.unittest.UnitTestMeta; +import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpResponse; +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.ServiceRegistry; +import org.apache.servicecomb.serviceregistry.registry.ServiceRegistryFactory; +import org.apache.servicecomb.swagger.invocation.Response; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +public class CseAsyncClientHttpRequestTest { + + @Before + public void setup() { + ReferenceConfigUtils.setReady(true); + } + + @After + public void teardown() { + ReferenceConfigUtils.setReady(false); + } + + @RequestMapping(path = "SpringmvcImpl") + static class SpringmvcImpl { + @RequestMapping(path = "/bytes", method = RequestMethod.POST) + public byte[] bytes(@RequestBody byte[] input) { + input[0] = (byte) (input[0] + 1); + return input; + } + } + + @Test + public void testNotReady() { + String exceptionMessage = "System is not ready for remote calls. " + + "When beans are making remote calls in initialization, it's better to " + + "implement " + BootListener.class.getName() + " and do it after EventType.AFTER_REGISTRY."; + ReferenceConfigUtils.setReady(false); + CseAsyncClientHttpRequest clientHttpRequest = new CseAsyncClientHttpRequest(URI.create("cse://app:test/"), + HttpMethod.POST); + try { + clientHttpRequest.executeAsync(); + } catch (IllegalStateException e) { + Assert.assertEquals(exceptionMessage, e.getMessage()); + } + } + + @Test + public void testNormal() { + ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); + serviceRegistry.init(); + RegistryUtils.setServiceRegistry(serviceRegistry); + UnitTestMeta meta = new UnitTestMeta(); + CseContext.getInstance() + .getSchemaListenerManager() + .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); + + SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.SpringmvcImpl.class); + CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta); + + Holder holder = new Holder<>(); + CseAsyncClientHttpRequest client = + new CseAsyncClientHttpRequest(URI.create( + "cse://app:test/" + CseAsyncClientHttpRequestTest.SpringmvcImpl.class.getSimpleName() + "/bytes"), + HttpMethod.POST) { + @Override + protected CompletableFuture doAsyncInvoke(Invocation invocation) { + CompletableFuture completableFuture = new CompletableFuture<>(); + holder.value = invocation; + completableFuture.complete(new CseClientHttpResponse(Response.ok("result"))); + return completableFuture; + } + }; + byte[] body = "abc".getBytes(); + client.setRequestBody(body); + client.executeAsync(); + Assert.assertArrayEquals(body, holder.value.getSwaggerArgument(0)); + } + + @Test + public void testFail() { + ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); + serviceRegistry.init(); + RegistryUtils.setServiceRegistry(serviceRegistry); + UnitTestMeta meta = new UnitTestMeta(); + CseContext.getInstance() + .getSchemaListenerManager() + .setSchemaListenerList(Arrays.asList(new RestEngineSchemaListener())); + + SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(CseAsyncClientHttpRequestTest.SpringmvcImpl.class); + CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(schemaMeta); + + Throwable error = new Error("failed"); + Response response = Response.createConsumerFail(error); + + CseAsyncClientHttpRequest client = + new CseAsyncClientHttpRequest(URI.create( + "cse://app:test/" + CseAsyncClientHttpRequestTest.SpringmvcImpl.class.getSimpleName() + "/bytes"), + HttpMethod.POST) { + @Override + protected CompletableFuture doAsyncInvoke(Invocation invocation) { + CompletableFuture completableFuture = new CompletableFuture<>(); + completableFuture.complete(new CseClientHttpResponse(response)); + return completableFuture; + } + }; + ListenableFuture future = client.executeAsync(); + future.addCallback( + new ListenableFutureCallback() { + @Override + public void onFailure(Throwable ex) { + Assert.assertSame(error, ex); + } + + @Override + public void onSuccess(ClientHttpResponse result) { + } + } + ); + } +} \ No newline at end of file diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRequestCallbackTest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRequestCallbackTest.java new file mode 100644 index 000000000..5a41a4d91 --- /dev/null +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRequestCallbackTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.http.HttpEntity; + +import mockit.Injectable; + +public class CseAsyncRequestCallbackTest { + @Test + public void testNormal() { + CseAsyncClientHttpRequest request = new CseAsyncClientHttpRequest(); + @SuppressWarnings("unchecked") + CseAsyncRequestCallback cb = new CseAsyncRequestCallback(null); + cb.doWithRequest(request); + Assert.assertEquals(null, request.getContext()); + } + + @Test + @SuppressWarnings("unchecked") + public void testHttpEntity(@Injectable HttpEntity entity) { + CseAsyncRequestCallback cb = new CseAsyncRequestCallback(entity); + CseAsyncClientHttpRequest request = new CseAsyncClientHttpRequest(); + cb.doWithRequest(request); + Assert.assertEquals(entity.getBody(), request.getBody()); + } + + @Test + @SuppressWarnings("unchecked") + public void testCseEntity(@Injectable CseHttpEntity entity) { + CseAsyncClientHttpRequest request = new CseAsyncClientHttpRequest(); + entity.addContext("c1", "c2"); + CseAsyncRequestCallback cb = new CseAsyncRequestCallback(entity); + cb.doWithRequest(request); + Assert.assertEquals(entity.getContext(), request.getContext()); + } +} \ No newline at end of file diff --git a/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplateTest.java b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplateTest.java new file mode 100644 index 000000000..3e5ce64cb --- /dev/null +++ b/providers/provider-springmvc/src/test/java/org/apache/servicecomb/provider/springmvc/reference/async/CseAsyncRestTemplateTest.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.provider.springmvc.reference.async; + +import org.junit.Assert; +import org.junit.Test; + +public class CseAsyncRestTemplateTest { + + @Test + public void testCseAsyncRestTemplate() { + Assert.assertEquals(CseAsyncRestTemplate.class, new CseAsyncRestTemplate().getClass()); + } +} \ No newline at end of file diff --git a/samples/springmvc-sample/springmvc-consumer/src/main/java/org/apache/servicecomb/samples/springmvc/consumer/SpringmvcConsumerMain.java b/samples/springmvc-sample/springmvc-consumer/src/main/java/org/apache/servicecomb/samples/springmvc/consumer/SpringmvcConsumerMain.java index 1571aa856..417cac64b 100644 --- a/samples/springmvc-sample/springmvc-consumer/src/main/java/org/apache/servicecomb/samples/springmvc/consumer/SpringmvcConsumerMain.java +++ b/samples/springmvc-sample/springmvc-consumer/src/main/java/org/apache/servicecomb/samples/springmvc/consumer/SpringmvcConsumerMain.java @@ -16,18 +16,28 @@ */ package org.apache.servicecomb.samples.springmvc.consumer; +import java.lang.invoke.MethodHandles; + import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.apache.servicecomb.foundation.common.utils.Log4jUtils; import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.provider.springmvc.reference.async.CseAsyncRestTemplate; import org.apache.servicecomb.samples.common.schema.Hello; import org.apache.servicecomb.samples.common.schema.models.Person; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.util.concurrent.ListenableFutureCallback; import org.springframework.web.client.RestTemplate; @Component public class SpringmvcConsumerMain { - + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static RestTemplate restTemplate = RestTemplateBuilder.create(); @RpcReference(microserviceName = "springmvc", schemaId = "springmvcHello") @@ -50,6 +60,33 @@ public static void main(String[] args) throws Exception { // POJO Consumer System.out.println("POJO consumer sayhi services: " + hello.sayHi("Java Chassis")); System.out.println("POJO consumer sayhello services: " + hello.sayHello(person)); + + //AsyncRestTemplate Consumer + CseAsyncRestTemplate cseAsyncRestTemplate = new CseAsyncRestTemplate(); + ListenableFuture> responseEntityListenableFuture = cseAsyncRestTemplate + .postForEntity("cse://springmvc/springmvchello/sayhi?name=Java Chassis", null, String.class); + ResponseEntity responseEntity = responseEntityListenableFuture.get(); + System.out.println("AsyncRestTemplate Consumer sayHi services: " + responseEntity.getBody()); + + HttpEntity entity = new HttpEntity<>(person); + ListenableFuture> listenableFuture = cseAsyncRestTemplate + .exchange("cse://springmvc/springmvchello/sayhello", HttpMethod.POST, entity, String.class); +// ResponseEntity responseEntity1 = listenableFuture.get(); +// System.out.println("AsyncRestTemplate Consumer sayHello services: " + responseEntity1.getBody()); + + listenableFuture.addCallback( + new ListenableFutureCallback>() { + @Override + public void onFailure(Throwable ex) { + LOG.error("AsyncResTemplate Consumer catched exception when sayHello, ",ex); + } + @Override + public void onSuccess(ResponseEntity result) { + System.out.println("AsyncRestTemplate Consumer sayHello services: " + result.getBody()); + } + } + ); + } public static void init() throws Exception { ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: users@infra.apache.org With regards, Apache Git Services