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 <[email protected]> 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) {
