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 2018/08/17 02:23:50 UTC
[incubator-servicecomb-java-chassis] 01/10: [SCB-847]Provide a way
to decode user's custom error data
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 8e8a3ec9aaa7390048af04d9717224465d250899
Author: liubao <ba...@huawei.com>
AuthorDate: Wed Aug 15 18:53:51 2018 +0800
[SCB-847]Provide a way to decode user's custom error data
---
.../error/CustomExceptionToResponseConverter.java | 47 ++++++++++++++++++++
.../demo/edge/business/error/ErrorData.java | 40 +++++++++++++++++
.../demo/edge/business/error/ErrorService.java | 46 ++++++++++++++++++++
.../edge/business/error/IllegalStateErrorData.java | 50 ++++++++++++++++++++++
...vocation.exception.ExceptionToResponseConverter | 18 ++++++++
.../servicecomb/demo/edge/consumer/Consumer.java | 28 ++++++++++++
.../edge/service/CustomResponseMetaMapper.java | 46 ++++++++++++++++++++
.../demo/edge/service/IllegalStateErrorData.java | 50 ++++++++++++++++++++++
....swagger.invocation.response.ResponseMetaMapper | 18 ++++++++
.../invocation/response/ResponseMetaMapper.java | 28 ++++++++++++
.../swagger/invocation/response/ResponsesMeta.java | 29 ++++++++++++-
11 files changed, 398 insertions(+), 2 deletions(-)
diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToResponseConverter.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToResponseConverter.java
new file mode 100644
index 0000000..fd2ccd9
--- /dev/null
+++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToResponseConverter.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.demo.edge.business.error;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+import org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+
+public class CustomExceptionToResponseConverter implements ExceptionToResponseConverter<IllegalStateException> {
+ @Override
+ public Class<IllegalStateException> getExceptionClass() {
+ return IllegalStateException.class;
+ }
+
+ @Override
+ public int getOrder() {
+ return 100;
+ }
+
+ @Override
+ public Response convert(SwaggerInvocation swaggerInvocation, IllegalStateException e) {
+ IllegalStateErrorData data = new IllegalStateErrorData();
+ data.setId(500);
+ data.setMessage(e.getMessage());
+ data.setState(e.getMessage());
+ InvocationException state = new InvocationException(Status.INTERNAL_SERVER_ERROR, data);
+ return Response.failResp(state);
+ }
+}
diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorData.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorData.java
new file mode 100644
index 0000000..078c194
--- /dev/null
+++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorData.java
@@ -0,0 +1,40 @@
+/*
+ * 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.demo.edge.business.error;
+
+public class ErrorData {
+ private int id;
+
+ private String message;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java
new file mode 100644
index 0000000..8bdba9c
--- /dev/null
+++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java
@@ -0,0 +1,46 @@
+/*
+ * 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.demo.edge.business.error;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@RestSchema(schemaId = "error-v2")
+@RequestMapping(path = "/business/v2/error")
+public class ErrorService {
+ @RequestMapping(path = "/add", method = RequestMethod.GET)
+ public int add(int x, int y) {
+ if (x == 99) {
+ throw new NullPointerException("un expected NPE test.");
+ }
+ if (x == 88) {
+ ErrorData data = new ErrorData();
+ data.setId(12);
+ data.setMessage("not allowed id.");
+ throw new InvocationException(Status.FORBIDDEN, data);
+ }
+ if (x == 77) {
+ throw new IllegalStateException("77");
+ }
+ return x + y;
+ }
+}
diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/IllegalStateErrorData.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/IllegalStateErrorData.java
new file mode 100644
index 0000000..d771c7a
--- /dev/null
+++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/IllegalStateErrorData.java
@@ -0,0 +1,50 @@
+/*
+ * 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.demo.edge.business.error;
+
+public class IllegalStateErrorData {
+ private int id;
+
+ private String message;
+
+ private String state;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+}
diff --git a/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter b/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
new file mode 100644
index 0000000..9a43331
--- /dev/null
+++ b/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.demo.edge.business.error.CustomExceptionToResponseConverter
\ No newline at end of file
diff --git a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
index 7796de9..c5c22ea 100644
--- a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
+++ b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java
@@ -46,6 +46,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
public class Consumer {
@@ -88,6 +90,7 @@ public class Consumer {
testDependType();
testDownload();
testDownloadBigFile();
+ testErrorCode();
invoke("/v1/add", 2, 1, addV1Result);
invoke("/v1/add", 3, 1, addV1Result);
@@ -158,6 +161,31 @@ public class Consumer {
Assert.isNull(response.getField().getField(), "must be null");
}
+ protected void testErrorCode() {
+ String url = edgePrefix + "/v2/error/add";
+
+ int response = template.getForObject(url + "?x=2&y=3", Integer.class);
+ Assert.isTrue(response == 5, "not get 5.");
+
+ Map raw = template.getForObject(url + "?x=99&y=3", Map.class);
+ Assert.isTrue(raw.get("message").equals("Cse Internal Server Error"), "x99");
+
+ try {
+ raw = template.getForObject(url + "?x=88&y=3", Map.class);
+ Assert.isTrue(false, "x88");
+ } catch (HttpClientErrorException e) {
+ Assert.isTrue(e.getRawStatusCode() == 403, "x88");
+ Assert.isTrue(e.getResponseBodyAsString().equals("{\"id\":12,\"message\":\"not allowed id.\"}"), "x88");
+ }
+ try {
+ raw = template.getForObject(url + "?x=77&y=3", Map.class);
+ Assert.isTrue(false, "x77");
+ } catch (HttpServerErrorException e) {
+ Assert.isTrue(e.getRawStatusCode() == 500, "x77");
+ Assert.isTrue(e.getResponseBodyAsString().equals("{\"id\":500,\"message\":\"77\",\"state\":\"77\"}"), "x77");
+ }
+ }
+
protected void testDependType() {
String url = edgePrefix + "/v2/dependType";
diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java
new file mode 100644
index 0000000..c3eaa51
--- /dev/null
+++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java
@@ -0,0 +1,46 @@
+/*
+ * 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.demo.edge.service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.swagger.invocation.response.ResponseMeta;
+import org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper;
+
+import com.fasterxml.jackson.databind.type.SimpleType;
+
+public class CustomResponseMetaMapper implements ResponseMetaMapper {
+ private final static Map<Integer, ResponseMeta> CODES = new HashMap<>(1);
+
+ static {
+ ResponseMeta meta = new ResponseMeta();
+ meta.setJavaType(SimpleType.constructUnsafe(IllegalStateErrorData.class));
+ CODES.put(500, meta);
+ }
+
+ @Override
+ public int getOrder() {
+ return 100;
+ }
+
+ @Override
+ public Map<Integer, ResponseMeta> getMapper() {
+ return CODES;
+ }
+}
diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/IllegalStateErrorData.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/IllegalStateErrorData.java
new file mode 100644
index 0000000..017183f
--- /dev/null
+++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/IllegalStateErrorData.java
@@ -0,0 +1,50 @@
+/*
+ * 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.demo.edge.service;
+
+public class IllegalStateErrorData {
+ private int id;
+
+ private String message;
+
+ private String state;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+}
diff --git a/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper b/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper
new file mode 100644
index 0000000..d8a88a7
--- /dev/null
+++ b/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.demo.edge.service.CustomResponseMetaMapper
\ No newline at end of file
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
new file mode 100644
index 0000000..e357711
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/response/ResponseMetaMapper.java
@@ -0,0 +1,28 @@
+/*
+ * 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.Map;
+
+public interface ResponseMetaMapper {
+ default int getOrder() {
+ return 0;
+ }
+
+ Map<Integer, ResponseMeta> 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 09b96da..856e3f0 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
@@ -23,9 +23,11 @@ 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.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;
@@ -35,7 +37,12 @@ import io.swagger.models.Operation;
import io.swagger.models.Response;
public class ResponsesMeta {
- private static final JavaType COMMON_EXCEPTION_JAVATYPE = SimpleType.constructUnsafe(CommonExceptionData.class);
+ private static final JavaType COMMON_EXCEPTION_JAVA_TYPE = SimpleType.constructUnsafe(CommonExceptionData.class);
+
+ private static final JavaType OBJECT_JAVA_TYPE = SimpleType.constructUnsafe(Object.class);
+
+ private static final ResponseMetaMapper GLOBAL_DEFAULT_MAPPER = SPIServiceUtils
+ .getPriorityHighestService(ResponseMetaMapper.class);
private Map<Integer, ResponseMeta> responseMap = new HashMap<>();
@@ -46,6 +53,8 @@ public class ResponsesMeta {
// 如果不传return类型进来,完全以swagger为标准,会导致生成的class不等于return
public void init(SwaggerToClassGenerator swaggerToClassGenerator, Operation operation, Type returnType) {
initSuccessResponse(returnType);
+ initInternalErrorResponse();
+ initGlobalDefaultMapper();
for (Entry<String, Response> entry : operation.getResponses().entrySet()) {
if ("default".equals(entry.getKey())) {
@@ -62,7 +71,7 @@ public class ResponsesMeta {
if (defaultResponse == null) {
// swagger中没有定义default,加上default专用于处理exception
ResponseMeta responseMeta = new ResponseMeta();
- responseMeta.setJavaType(COMMON_EXCEPTION_JAVATYPE);
+ responseMeta.setJavaType(OBJECT_JAVA_TYPE);
defaultResponse = responseMeta;
}
@@ -74,6 +83,22 @@ public class ResponsesMeta {
responseMap.put(Status.OK.getStatusCode(), successResponse);
}
+ protected void initInternalErrorResponse() {
+ ResponseMeta internalErrorResponse = new ResponseMeta();
+ internalErrorResponse.setJavaType(COMMON_EXCEPTION_JAVA_TYPE);
+ responseMap.put(ExceptionFactory.CONSUMER_INNER_STATUS_CODE, internalErrorResponse);
+ responseMap.put(ExceptionFactory.PRODUCER_INNER_STATUS_CODE, internalErrorResponse);
+ }
+
+ protected void initGlobalDefaultMapper() {
+ if (GLOBAL_DEFAULT_MAPPER != null) {
+ Map<Integer, ResponseMeta> mappers = GLOBAL_DEFAULT_MAPPER.getMapper();
+ if (mappers != null) {
+ responseMap.putAll(mappers);
+ }
+ }
+ }
+
public ResponseMeta findResponseMeta(int statusCode) {
ResponseMeta responseMeta = responseMap.get(statusCode);
if (responseMeta == null) {