You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2019/07/04 09:38:11 UTC
[servicecomb-java-chassis] 01/07: [SCB-1212[WIP][WEAK] response
mapper not depend on swagger class generation
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch weak-contract-type
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit e1d1c7db7b3f684a4c783d743da0c28a6871a9b1
Author: wujimin <wu...@huawei.com>
AuthorDate: Wed Jul 3 21:37:57 2019 +0800
[SCB-1212[WIP][WEAK] response mapper not depend on swagger class generation
---
.../invocation/response/ResponseMapperFactory.java | 10 +--
.../response/ResponseMapperFactorys.java | 19 +----
.../swagger/invocation/response/ResponseMeta.java | 63 --------------
.../invocation/response/ResponseMetaMapper.java | 4 +-
.../swagger/invocation/response/ResponsesMeta.java | 96 +++++++++++++---------
.../response/TestResponseMapperFactorys.java | 89 --------------------
.../invocation/response/TestResponsesMeta.java | 37 ++++-----
7 files changed, 83 insertions(+), 235 deletions(-)
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactory.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactory.java
index 70d8871..73a2f1a 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactory.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactory.java
@@ -18,18 +18,12 @@ package org.apache.servicecomb.swagger.invocation.response;
import java.lang.reflect.Type;
-import org.apache.servicecomb.swagger.invocation.converter.ConverterMgr;
-
public interface ResponseMapperFactory<MAPPER> {
default int getOrder() {
return 0;
}
- default void setConverterMgr(ConverterMgr converterMgr) {
- }
-
- boolean isMatch(Type swaggerType, Type providerType);
+ boolean isMatch(Type providerType);
- MAPPER createResponseMapper(ResponseMapperFactorys<MAPPER> factorys, Type swaggerType,
- Type providerType);
+ MAPPER createResponseMapper(ResponseMapperFactorys<MAPPER> factorys, Type providerType);
}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactorys.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactorys.java
index 92e95c6..9a37037 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactorys.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMapperFactorys.java
@@ -20,37 +20,26 @@ import java.lang.reflect.Type;
import java.util.List;
import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.swagger.invocation.converter.ConverterMgr;
public class ResponseMapperFactorys<MAPPER> {
private List<ResponseMapperFactory<MAPPER>> factorys;
- public ResponseMapperFactorys(Class<? extends ResponseMapperFactory<MAPPER>> factoryCls, ConverterMgr converterMgr) {
- this(factoryCls);
- this.setConverterMgr(converterMgr);
- }
-
@SuppressWarnings("unchecked")
public ResponseMapperFactorys(Class<? extends ResponseMapperFactory<MAPPER>> factoryCls) {
factorys = (List<ResponseMapperFactory<MAPPER>>) SPIServiceUtils.getSortedService(factoryCls);
}
- public void setConverterMgr(ConverterMgr converterMgr) {
- factorys.forEach(factory -> factory.setConverterMgr(converterMgr));
- }
-
- public MAPPER createResponseMapper(Type swaggerType, Type providerType) {
+ public MAPPER createResponseMapper(Type providerType) {
for (ResponseMapperFactory<MAPPER> factory : factorys) {
- if (!factory.isMatch(swaggerType, providerType)) {
+ if (!factory.isMatch(providerType)) {
continue;
}
- return factory.createResponseMapper(this, swaggerType, providerType);
+ return factory.createResponseMapper(this, providerType);
}
throw new IllegalStateException(
- String.format("can not find response mapper for %s and %s, this should never happened.",
- swaggerType.getTypeName(),
+ String.format("can not find response mapper for %s, this should never happened.",
providerType.getTypeName()));
}
}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMeta.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMeta.java
deleted file mode 100644
index 3aade01..0000000
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMeta.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.swagger.invocation.response;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.servicecomb.swagger.converter.SwaggerToClassGenerator;
-
-import com.fasterxml.jackson.databind.JavaType;
-
-import io.swagger.models.Response;
-import io.swagger.models.properties.Property;
-
-public class ResponseMeta {
- /**
- * swagger中定义的statusCode与java类型的映射,方便consumer端transport将码流转换为具体的类型
- */
- private JavaType javaType;
-
- private Map<String, JavaType> headers = new HashMap<>();
-
- public void init(SwaggerToClassGenerator swaggerToClassGenerator, Response response) {
- if (javaType == null) {
- javaType = swaggerToClassGenerator.convert(response.getResponseSchema());
- }
-
- if (response.getHeaders() == null) {
- return;
- }
- for (Entry<String, Property> entry : response.getHeaders().entrySet()) {
- JavaType headerJavaType = swaggerToClassGenerator.convert(entry.getValue());
- headers.put(entry.getKey(), headerJavaType);
- }
- }
-
- public JavaType getJavaType() {
- return javaType;
- }
-
- public void setJavaType(JavaType javaType) {
- this.javaType = javaType;
- }
-
- public Map<String, JavaType> getHeaders() {
- return headers;
- }
-}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMetaMapper.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMetaMapper.java
index e357711..8de01af 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMetaMapper.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMetaMapper.java
@@ -19,10 +19,12 @@ package org.apache.servicecomb.swagger.invocation.response;
import java.util.Map;
+import com.fasterxml.jackson.databind.JavaType;
+
public interface ResponseMetaMapper {
default int getOrder() {
return 0;
}
- Map<Integer, ResponseMeta> getMapper();
+ Map<Integer, JavaType> getMapper();
}
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponsesMeta.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponsesMeta.java
index 881cb81..2321eb3 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponsesMeta.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponsesMeta.java
@@ -16,7 +16,8 @@
*/
package org.apache.servicecomb.swagger.invocation.response;
-import java.lang.reflect.Type;
+import static io.swagger.util.ReflectionUtils.isVoid;
+
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -24,18 +25,43 @@ import java.util.Map.Entry;
import javax.ws.rs.core.Response.Status;
import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.swagger.converter.SwaggerToClassGenerator;
+import org.apache.servicecomb.swagger.converter.ConverterMgr;
import org.apache.servicecomb.swagger.invocation.context.HttpStatus;
import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.SimpleType;
-import com.fasterxml.jackson.databind.type.TypeFactory;
import io.swagger.models.Operation;
import io.swagger.models.Response;
-
+import io.swagger.models.Swagger;
+
+/**
+ * <pre>
+ * two Scenes:
+ * 1.consumer interface + swagger
+ * interface declare success response type
+ * and can declare exceptions response type by annotations
+ * consumer interface meta never changed and has high priority
+ *
+ * so, merge them to be one ResponsesMeta
+ *
+ * 2.restTemplate + swagger
+ * can only declare success response type
+ * and not stable
+ *
+ * so, will wrap swagger meta
+ *
+ * note:
+ * old version support: List<User> users = restTemplate.postForObject(...., List.class)
+ * in fact, in this time, type is determined by swagger meta
+ * new version:
+ * 1) if request response type is List/Set/Map, and there is element type defined, then use swagger type,
+ * 2) other times use request response type
+ * 3) compare to old version, add support of ParameterizedTypeReference
+ * </pre>
+ */
public class ResponsesMeta {
private static final JavaType COMMON_EXCEPTION_JAVA_TYPE = SimpleType.constructUnsafe(CommonExceptionData.class);
@@ -44,65 +70,61 @@ public class ResponsesMeta {
private static final ResponseMetaMapper GLOBAL_DEFAULT_MAPPER = SPIServiceUtils
.getPriorityHighestService(ResponseMetaMapper.class);
- private Map<Integer, ResponseMeta> responseMap = new HashMap<>();
+ private Map<Integer, JavaType> responseMap = new HashMap<>();
- private ResponseMeta defaultResponse;
+ private JavaType defaultResponse;
- // 最后一个参数returnType用于兼容场景
- // 历史版本中swagger中定义的return可能没定义class名,此时consumer与swagger接口是一致的
- // 如果不传return类型进来,完全以swagger为标准,会导致生成的class不等于return
- public void init(SwaggerToClassGenerator swaggerToClassGenerator, Operation operation, Type returnType) {
- initSuccessResponse(returnType);
- initGlobalDefaultMapper();
+ public void init(Swagger swagger, Operation operation) {
+ if (responseMap.isEmpty()) {
+ responseMap.put(Status.OK.getStatusCode(), OBJECT_JAVA_TYPE);
+ initGlobalDefaultMapper();
+ }
for (Entry<String, Response> entry : operation.getResponses().entrySet()) {
+ JavaType javaType = ConverterMgr.findJavaType(swagger, entry.getValue().getResponseSchema());
+
if ("default".equals(entry.getKey())) {
- defaultResponse = new ResponseMeta();
- defaultResponse.init(swaggerToClassGenerator, entry.getValue());
+ defaultResponse = javaType;
continue;
}
Integer statusCode = Integer.parseInt(entry.getKey());
- ResponseMeta responseMeta = responseMap.computeIfAbsent(statusCode, k -> new ResponseMeta());
- responseMeta.init(swaggerToClassGenerator, entry.getValue());
+ JavaType existing = responseMap.get(statusCode);
+ if (existing == null || !isVoid(javaType)) {
+ responseMap.put(statusCode, javaType);
+ }
}
- initInternalErrorResponse();
+ responseMap.putIfAbsent(ExceptionFactory.CONSUMER_INNER_STATUS_CODE, COMMON_EXCEPTION_JAVA_TYPE);
+ responseMap.putIfAbsent(ExceptionFactory.PRODUCER_INNER_STATUS_CODE, COMMON_EXCEPTION_JAVA_TYPE);
if (defaultResponse == null) {
// swagger中没有定义default,加上default专用于处理exception
- ResponseMeta responseMeta = new ResponseMeta();
- responseMeta.setJavaType(OBJECT_JAVA_TYPE);
-
- defaultResponse = responseMeta;
+ defaultResponse = OBJECT_JAVA_TYPE;
}
}
- protected void initSuccessResponse(Type returnType) {
- ResponseMeta successResponse = new ResponseMeta();
- successResponse.setJavaType(TypeFactory.defaultInstance().constructType(returnType));
- responseMap.put(Status.OK.getStatusCode(), successResponse);
- }
-
- protected void initInternalErrorResponse() {
- ResponseMeta internalErrorResponse = new ResponseMeta();
- internalErrorResponse.setJavaType(COMMON_EXCEPTION_JAVA_TYPE);
- responseMap.putIfAbsent(ExceptionFactory.CONSUMER_INNER_STATUS_CODE, internalErrorResponse);
- responseMap.putIfAbsent(ExceptionFactory.PRODUCER_INNER_STATUS_CODE, internalErrorResponse);
+ public void cloneTo(ResponsesMeta target) {
+ target.defaultResponse = defaultResponse;
+ target.responseMap.putAll(responseMap);
}
protected void initGlobalDefaultMapper() {
if (GLOBAL_DEFAULT_MAPPER != null) {
- Map<Integer, ResponseMeta> mappers = GLOBAL_DEFAULT_MAPPER.getMapper();
+ Map<Integer, JavaType> mappers = GLOBAL_DEFAULT_MAPPER.getMapper();
if (mappers != null) {
responseMap.putAll(mappers);
}
}
}
- public ResponseMeta findResponseMeta(int statusCode) {
- ResponseMeta responseMeta = responseMap.get(statusCode);
- if (responseMeta == null) {
+ public Map<Integer, JavaType> getResponseMap() {
+ return responseMap;
+ }
+
+ public JavaType findResponseType(int statusCode) {
+ JavaType responseType = responseMap.get(statusCode);
+ if (responseType == null) {
if (HttpStatus.isSuccess(statusCode)) {
return responseMap.get(Status.OK.getStatusCode());
}
@@ -110,6 +132,6 @@ public class ResponsesMeta {
return defaultResponse;
}
- return responseMeta;
+ return responseType;
}
}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponseMapperFactorys.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponseMapperFactorys.java
deleted file mode 100644
index bd6f61d..0000000
--- a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponseMapperFactorys.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.swagger.invocation.response;
-
-import java.util.List;
-
-import org.apache.servicecomb.swagger.invocation.Response;
-import org.apache.servicecomb.swagger.invocation.converter.Converter;
-import org.apache.servicecomb.swagger.invocation.converter.ConverterMgr;
-import org.apache.servicecomb.swagger.invocation.converter.impl.ConverterSame;
-import org.apache.servicecomb.swagger.invocation.response.consumer.CompletableFutureConsumerResponseMapperFactory;
-import org.apache.servicecomb.swagger.invocation.response.consumer.ConsumerResponseMapper;
-import org.apache.servicecomb.swagger.invocation.response.consumer.ConsumerResponseMapperFactory;
-import org.apache.servicecomb.swagger.invocation.response.consumer.CseResponseConsumerResponseMapperFactory;
-import org.apache.servicecomb.swagger.invocation.response.consumer.DefaultConsumerResponseMapper;
-import org.apache.servicecomb.swagger.invocation.response.consumer.DefaultConsumerResponseMapperFactory;
-import org.apache.servicecomb.swagger.invocation.response.consumer.OptionalConsumerResponseMapperFactory;
-import org.hamcrest.Matchers;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import mockit.Deencapsulation;
-
-public class TestResponseMapperFactorys {
- ResponseMapperFactorys<ConsumerResponseMapper> consumerResponseMapperFactorys =
- new ResponseMapperFactorys<>(ConsumerResponseMapperFactory.class);
-
- List<ResponseMapperFactory<ConsumerResponseMapper>> factorys =
- Deencapsulation.getField(consumerResponseMapperFactorys, "factorys");
-
- ConverterMgr converterMgr = new ConverterMgr();
-
- @Before
- public void setup() {
- consumerResponseMapperFactorys.setConverterMgr(converterMgr);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void construct() {
- Assert.assertThat(factorys,
- Matchers.containsInAnyOrder(Matchers.instanceOf(CseResponseConsumerResponseMapperFactory.class),
- Matchers.instanceOf(CompletableFutureConsumerResponseMapperFactory.class),
- Matchers.instanceOf(DefaultConsumerResponseMapperFactory.class),
- Matchers.instanceOf(OptionalConsumerResponseMapperFactory.class)));
- }
-
- @Test
- public void setConverterMgr() {
- DefaultConsumerResponseMapperFactory mapper = (DefaultConsumerResponseMapperFactory) factorys.stream()
- .filter(m -> m instanceof DefaultConsumerResponseMapperFactory)
- .findFirst()
- .get();
- Assert.assertSame(converterMgr, Deencapsulation.getField(mapper, "converterMgr"));
- }
-
- @Test
- public void createResponseMapper_default() {
- ConsumerResponseMapper mapper = consumerResponseMapperFactorys.createResponseMapper(String.class, String.class);
- Assert.assertThat(mapper, Matchers.instanceOf(DefaultConsumerResponseMapper.class));
-
- Converter converter = Deencapsulation.getField(mapper, "converter");
- Assert.assertSame(ConverterSame.getInstance(), converter);
- }
-
- @Test
- public void createResponseMapper_cseResponse() {
- ConsumerResponseMapper mapper = consumerResponseMapperFactorys.createResponseMapper(String.class, Response.class);
-
- Response response = Response.ok(null);
- Object result = mapper.mapResponse(response);
- Assert.assertSame(response, result);
- }
-}
diff --git a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponsesMeta.java b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponsesMeta.java
index f6077ce..219bb0c 100644
--- a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponsesMeta.java
+++ b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/response/TestResponsesMeta.java
@@ -16,12 +16,12 @@
*/
package org.apache.servicecomb.swagger.invocation.response;
-import org.apache.servicecomb.swagger.converter.SwaggerToClassGenerator;
-import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator;
-import org.apache.servicecomb.swagger.generator.core.unittest.UnitTestSwaggerUtils;
+import org.apache.servicecomb.swagger.generator.SwaggerGenerator;
import org.junit.Assert;
import org.junit.Test;
+import com.fasterxml.jackson.databind.JavaType;
+
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ResponseHeader;
@@ -44,33 +44,26 @@ public class TestResponsesMeta {
@Test
public void test() {
- SwaggerGenerator generator = UnitTestSwaggerUtils.generateSwagger(ResponseMetaImpl.class);
- Swagger swagger = generator.getSwagger();
+ Swagger swagger = SwaggerGenerator.generate(ResponseMetaImpl.class);
Operation operation = swagger.getPath("/add").getPost();
- SwaggerToClassGenerator swaggerToClassGenerator = new SwaggerToClassGenerator(new ClassLoader() {
- }, swagger, "ms.sid");
ResponsesMeta meta = new ResponsesMeta();
- meta.init(swaggerToClassGenerator, operation, int.class);
+ meta.init(swagger, operation);
- ResponseMeta resp = meta.findResponseMeta(200);
- // Response currently is based on return type not swagger type
- Assert.assertEquals(int.class, resp.getJavaType().getRawClass());
+ JavaType resp = meta.findResponseType(200);
+ Assert.assertEquals(Integer.class, resp.getRawClass());
- resp = meta.findResponseMeta(201);
- // Response currently is based on return type not swagger type. For this test case there is one problem need to discuss.
- // If SUCCESS family, do we should use OK response type?
- Assert.assertEquals(int.class, resp.getJavaType().getRawClass());
+ resp = meta.findResponseType(201);
+ Assert.assertEquals(Integer.class, resp.getRawClass());
- resp = meta.findResponseMeta(400);
- Assert.assertEquals(String.class, resp.getJavaType().getRawClass());
+ resp = meta.findResponseType(400);
+ Assert.assertEquals(String.class, resp.getRawClass());
- resp = meta.findResponseMeta(401);
- Assert.assertEquals(Long.class, resp.getJavaType().getRawClass());
- Assert.assertEquals(Integer.class, resp.getHeaders().get("h1").getRawClass());
+ resp = meta.findResponseType(401);
+ Assert.assertEquals(Long.class, resp.getRawClass());
- resp = meta.findResponseMeta(500);
+ resp = meta.findResponseType(500);
// changed to Object for new version to keep user defined error data not lose and can be parsed.
- Assert.assertEquals(Object.class, resp.getJavaType().getRawClass());
+ Assert.assertEquals(Object.class, resp.getRawClass());
}
}