You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by wu...@apache.org on 2018/04/04 07:45:58 UTC
[incubator-servicecomb-java-chassis] branch master updated: SCB-379
support AsyncRestTemplate
This is an automated email from the ASF dual-hosted git repository.
wujimin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new 8a77e34 SCB-379 support AsyncRestTemplate
8a77e34 is described below
commit 8a77e34365e786462b74826c724d10f0e735d5fe
Author: lijasonvip <li...@huawei.com>
AuthorDate: Wed Mar 14 16:16:40 2018 +0800
SCB-379 support AsyncRestTemplate
Signed-off-by: lijasonvip <li...@huawei.com>
---
.../tests/SpringMvcIntegrationTestBase.java | 248 +++++++++++++++++++--
.../springmvc/reference/CseClientHttpRequest.java | 47 +++-
.../reference/async/CseAsyncClientHttpRequest.java | 83 +++++++
.../async/CseAsyncClientHttpRequestFactory.java | 31 +++
.../reference/async/CseAsyncRequestCallback.java | 47 ++++
.../reference/async/CseAsyncRestTemplate.java | 47 ++++
.../CseAsyncClientHttpRequestFactoryTest.java | 33 +++
.../async/CseAsyncClientHttpRequestTest.java | 159 +++++++++++++
.../async/CseAsyncRequestCallbackTest.java | 55 +++++
.../reference/async/CseAsyncRestTemplateTest.java | 29 +++
.../springmvc/consumer/SpringmvcConsumerMain.java | 39 +++-
11 files changed, 786 insertions(+), 32 deletions(-)
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 1d2e1ba..a00dbbe 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.common.rest.codec.RestObjectMapper;
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.HttpMessageConverter;
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 @@ public class SpringMvcIntegrationTestBase {
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 @@ public class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 @@ public class SpringMvcIntegrationTestBase {
}
@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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
.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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
.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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 class SpringMvcIntegrationTestBase {
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 2ff0ca5..947469d 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 class CseClientHttpRequest implements ClientHttpRequest {
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 class CseClientHttpRequest implements ClientHttpRequest {
}
@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 class CseClientHttpRequest implements ClientHttpRequest {
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 @@ public class CseClientHttpRequest implements ClientHttpRequest {
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 @@ public class CseClientHttpRequest implements ClientHttpRequest {
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 0000000..1be86dc
--- /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 0000000..d27cf78
--- /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 0000000..1ca4b4c
--- /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 0000000..6f16f99
--- /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 0000000..ce10009
--- /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 0000000..4ae2bc7
--- /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 0000000..5a41a4d
--- /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 0000000..3e5ce64
--- /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 1571aa8..417cac6 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 class SpringmvcConsumerMain {
// 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 {
--
To stop receiving notification emails like this one, please contact
wujimin@apache.org.