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<String> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .getForEntity(baseUrl + "sayHi?name=Mike", String.class);
+ ResponseEntity<String> 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<String> responseEntity = restTemplate
.getForEntity(baseUrl, String.class);
assertThat(responseEntity.getStatusCode(), is(OK));
assertThat(responseEntity.getBody(), is("Welcome home"));
+
+ ListenableFuture<ResponseEntity<String>> listenableFuture =
asyncRestTemplate.getForEntity(baseUrl, String.class);
+ ResponseEntity<String> futureResponse = listenableFuture.get();
+ assertThat(futureResponse.getStatusCode(), is(OK));
+ assertThat(futureResponse.getBody(), is("Welcome home"));
}
@Test
- public void ableToQueryAtNonRootPath() {
+ public void ableToQueryAtNonRootPath() throws Exception {
ResponseEntity<String> responseEntity = restTemplate
.getForEntity(baseUrl + "french/bonjour?name=Mike", String.class);
assertThat(responseEntity.getStatusCode(), is(OK));
assertThat(responseEntity.getBody(), is("Bonjour Mike"));
+
+ ListenableFuture<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .getForEntity(baseUrl + "french/bonjour?name=Mike", String.class);
+ ResponseEntity<String> futureResponse = listenableFuture.get();
+ assertThat(futureResponse.getStatusCode(), is(OK));
+ assertThat(futureResponse.getBody(), is("Bonjour Mike"));
}
@Test
- public void ableToPostMap() {
+ public void ableToPostMap() throws Exception {
Map<String, User> users = new HashMap<>();
users.put("user1", userOfNames("name11", "name12"));
users.put("user2", userOfNames("name21", "name22"));
@@ -139,6 +169,17 @@ public void ableToPostMap() {
Map<String, User> body = responseEntity.getBody();
assertArrayEquals(body.get("user1").getNames(), new String[] {"name11",
"name12"});
assertArrayEquals(body.get("user2").getNames(), new String[] {"name21",
"name22"});
+
+ ListenableFuture<ResponseEntity<Map<String, User>>> listenableFuture =
asyncRestTemplate
+ .exchange(codeFirstUrl + "testUserMap",
+ POST,
+ jsonRequest(users),
+ reference);
+ ResponseEntity<Map<String, User>> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .postForEntity(codeFirstUrl + "textPlain", entity, String.class);
+ ResponseEntity<String> 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<ResponseEntity<byte[]>> listenableFuture =
asyncRestTemplate
+ .postForEntity(codeFirstUrl + "bytes",
+ jsonRequest(RestObjectMapper.INSTANCE.writeValueAsBytes(body)),
+ byte[].class);
+ ResponseEntity<byte[]> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .postForEntity(codeFirstUrl + "upload",
+ new HttpEntity<>(map, headers),
+ String.class);
+ ResponseEntity<String> 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<ResponseEntity<String>> listenableFuture =
cseAsyncRestTemplate
+ .postForEntity("cse://springmvc-tests/codeFirstSpringmvc/upload",
+ new HttpEntity<>(map, headers),
+ String.class);
+ ResponseEntity<String> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .postForEntity(codeFirstUrl + "uploadWithoutAnnotation",
+ new HttpEntity<>(map, headers),
+ String.class);
+ ResponseEntity<String> 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<ResponseEntity<Date>> listenableFuture = asyncRestTemplate
+ .postForEntity(codeFirstUrl + "addDate?seconds={seconds}",
+ new HttpEntity<>(body, headers),
+ Date.class,
+ seconds);
+ ResponseEntity<Date> dateResponseEntity = listenableFuture.get();
+ assertThat(dateResponseEntity.getBody(),
is(Date.from(date.plusSeconds(seconds).toInstant())));
}
@Test
- public void ableToDeleteWithQueryString() {
+ public void ableToDeleteWithQueryString() throws Exception {
ResponseEntity<String> responseEntity = restTemplate.exchange(codeFirstUrl
+ "addstring?s=a&s=b",
HttpMethod.DELETE,
null,
String.class);
assertThat(responseEntity.getBody(), is("ab"));
+ ListenableFuture<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .exchange(codeFirstUrl + "addstring?s=a&s=b", HttpMethod.DELETE, null,
String.class);
+ ResponseEntity<String> 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<ResponseEntity<Boolean>> listenableFuture =
asyncRestTemplate
+ .getForEntity(codeFirstUrl + "istrue", boolean.class);
+ ResponseEntity<Boolean> futureResponse = listenableFuture.get();
+ assertThat(futureResponse.getBody(), is(true));
}
@Test
- public void putsEndWithPathParam() {
+ public void putsEndWithPathParam() throws Exception {
ResponseEntity<String> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .exchange(codeFirstUrl + "sayhi/{name}", PUT, null, String.class,
"world");
+ ResponseEntity<String> 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<String> responseEntity = restTemplate
.exchange(codeFirstUrl + "sayhi/{name}/v2", PUT, null, String.class,
"world");
assertThat(jsonOf(responseEntity.getBody(), String.class), is("world sayhi
2"));
+ ListenableFuture<ResponseEntity<String>> 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<ResponseEntity<String>> 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<String, String> 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<ResponseEntity<Person>> listenableFuture =
asyncRestTemplate
+ .postForEntity(codeFirstUrl + "sayhello", jsonRequest(personFieldMap),
Person.class);
+ ResponseEntity<Person> 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<String, String> 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<ResponseEntity<Integer>> listenableFuture =
asyncRestTemplate
+ .postForEntity(codeFirstUrl + "add", new HttpEntity<>(params,
headers), Integer.class);
+ ResponseEntity<Integer> futureResponse = listenableFuture.get();
+ assertThat(futureResponse.getBody(), is(8));
}
@Test
- public void ableToExchangeCookie() {
+ public void ableToExchangeCookie() throws Exception {
Map<String, String> params = new HashMap<>();
params.put("a", "5");
@@ -376,10 +502,20 @@ public void ableToExchangeCookie() {
params);
assertThat(result.getBody(), is(2));
+
+ ListenableFuture<ResponseEntity<Integer>> 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<ResponseEntity<Integer>> listenableFuture =
asyncRestTemplate
+ .getForEntity(controllerUrl + "add?a={a}&b={b}",
+ Integer.class,
+ 3,
+ 4);
+ ResponseEntity<Integer> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .postForEntity(controllerUrl + "sayhello/{name}",
+ null,
+ String.class,
+ "world");
+ ResponseEntity<String> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .postForEntity(controllerUrl + "saysomething?prefix={prefix}",
+ jsonRequest(input),
+ String.class,
+ "hello");
+ ResponseEntity<String> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate
+ .getForEntity(controllerUrl + "sayhi?name=world",
+ String.class);
+ ResponseEntity<String> 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<ResponseEntity<String>> listenableFuture =
asyncRestTemplate.exchange(controllerUrl + "sayhei",
+ GET,
+ requestEntity,
+ String.class);
+// ResponseEntity<String> responseEntity = listenableFuture.get();
+ listenableFuture.addCallback(
+ new ListenableFutureCallback<ResponseEntity<String>>() {
+ @Override
+ public void onFailure(Throwable ex) {
+ }
+
+ @Override
+ public void onSuccess(ResponseEntity<String> result) {
+ assertThat(jsonOf(result.getBody(), String.class), is("hei
world"));
+ }
+ }
+ );
+
}
private <T> HttpEntity<T> 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<String, List<String>> 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<ClientHttpResponse> invoke(Object[] args) {
+ Invocation invocation = prepareInvocation(args);
+ invocation.getHandlerContext().put(RestConst.CONSUMER_HEADER,
this.getHeaders());
+ CompletableFuture<ClientHttpResponse> clientHttpResponseCompletableFuture
= doAsyncInvoke(invocation);
+ return new
CompletableToListenableFutureAdapter(clientHttpResponseCompletableFuture);
+ }
+
+ protected CompletableFuture<ClientHttpResponse> doAsyncInvoke(Invocation
invocation) {
+ CompletableFuture<ClientHttpResponse> 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<ClientHttpResponse> 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<T> implements AsyncRequestCallback {
+ private HttpEntity<T> requestBody;
+
+ CseAsyncRequestCallback(HttpEntity<T> 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 <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T>
requestBody) {
+ return new CseAsyncRequestCallback(requestBody);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T>
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<Invocation> holder = new Holder<>();
+ CseAsyncClientHttpRequest client =
+ new CseAsyncClientHttpRequest(URI.create(
+ "cse://app:test/" +
CseAsyncClientHttpRequestTest.SpringmvcImpl.class.getSimpleName() + "/bytes"),
+ HttpMethod.POST) {
+ @Override
+ protected CompletableFuture<ClientHttpResponse>
doAsyncInvoke(Invocation invocation) {
+ CompletableFuture<ClientHttpResponse> 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<ClientHttpResponse>
doAsyncInvoke(Invocation invocation) {
+ CompletableFuture<ClientHttpResponse> completableFuture = new
CompletableFuture<>();
+ completableFuture.complete(new CseClientHttpResponse(response));
+ return completableFuture;
+ }
+ };
+ ListenableFuture<ClientHttpResponse> future = client.executeAsync();
+ future.addCallback(
+ new ListenableFutureCallback<ClientHttpResponse>() {
+ @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<ResponseEntity<String>> responseEntityListenableFuture =
cseAsyncRestTemplate
+ .postForEntity("cse://springmvc/springmvchello/sayhi?name=Java
Chassis", null, String.class);
+ ResponseEntity<String> responseEntity =
responseEntityListenableFuture.get();
+ System.out.println("AsyncRestTemplate Consumer sayHi services: " +
responseEntity.getBody());
+
+ HttpEntity<Person> entity = new HttpEntity<>(person);
+ ListenableFuture<ResponseEntity<String>> listenableFuture =
cseAsyncRestTemplate
+ .exchange("cse://springmvc/springmvchello/sayhello", HttpMethod.POST,
entity, String.class);
+// ResponseEntity<String> responseEntity1 = listenableFuture.get();
+// System.out.println("AsyncRestTemplate Consumer sayHello services: " +
responseEntity1.getBody());
+
+ listenableFuture.addCallback(
+ new ListenableFutureCallback<ResponseEntity<String>>() {
+ @Override
+ public void onFailure(Throwable ex) {
+ LOG.error("AsyncResTemplate Consumer catched exception when
sayHello, ",ex);
+ }
+ @Override
+ public void onSuccess(ResponseEntity<String> 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:
[email protected]
With regards,
Apache Git Services