liubao68 closed pull request #627: [SCB-292] chassis support standard parameter 
validation
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/627
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
index 819249d49..77ce21b88 100644
--- 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
+++ 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java
@@ -22,6 +22,7 @@
 
 import com.netflix.client.DefaultLoadBalancerRetryHandler;
 import com.netflix.client.RetryHandler;
+import com.netflix.client.Utils;
 import com.netflix.loadbalancer.IRule;
 import com.netflix.loadbalancer.RoundRobinRule;
 
@@ -33,6 +34,14 @@
   }
 
   class MyCustomHandler extends DefaultLoadBalancerRetryHandler {
+    @Override
+    public boolean isRetriableException(Throwable e, boolean sameServer) {
+      if (retryEnabled) {
+        return Utils.isPresentAsCause(e, getRetriableExceptions());
+      }
+      return false;
+    }
+
     public MyCustomHandler(int retrySameServer, int retryNextServer, boolean 
retryEnabled) {
       super(retrySameServer, retryNextServer, retryEnabled);
     }
diff --git 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
index 5047a878b..5e63c2ddc 100644
--- 
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
+++ 
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java
@@ -21,6 +21,7 @@
 import java.util.Map;
 
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response.Status;
 
 import org.apache.servicecomb.common.rest.codec.RestObjectMapper;
 import org.apache.servicecomb.core.CseContext;
@@ -28,9 +29,11 @@
 import org.apache.servicecomb.demo.DemoConst;
 import org.apache.servicecomb.demo.TestMgr;
 import org.apache.servicecomb.demo.compute.Person;
+import org.apache.servicecomb.demo.validator.Student;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.common.utils.Log4jUtils;
 import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
@@ -57,6 +60,7 @@ public static void run() throws Exception {
     CodeFirstRestTemplate codeFirstClient = new CodeFirstRestTemplateJaxrs();
     codeFirstClient.testCodeFirst(templateNew, "jaxrs", "/codeFirstJaxrs/");
     testCompute(templateNew);
+    testValidator(templateNew);
   }
 
   private static void testCompute(RestTemplate template) throws Exception {
@@ -76,6 +80,24 @@ private static void testCompute(RestTemplate template) 
throws Exception {
     }
   }
 
+  private static void testValidator(RestTemplate template) throws Exception {
+    String microserviceName = "jaxrs";
+    for (String transport : DemoConst.transports) {
+      
CseContext.getInstance().getConsumerProviderManager().setTransport(microserviceName,
 transport);
+      TestMgr.setMsg(microserviceName, transport);
+
+      String cseUrlPrefix = "cse://" + microserviceName + "/validator/";
+
+      testValidatorAddSuccess(template, cseUrlPrefix);
+      testValidatorAddFail(template, cseUrlPrefix);
+      testValidatorSayHiSuccess(template, cseUrlPrefix);
+      testValidatorSayHiFail(template, cseUrlPrefix);
+      testValidatorExchangeSuccess(template, cseUrlPrefix);
+      testValidatorExchangeFail(template, cseUrlPrefix);
+    }
+  }
+
+
   private static void testGet(RestTemplate template, String cseUrlPrefix) {
     Map<String, String> params = new HashMap<>();
     params.put("a", "5");
@@ -147,4 +169,85 @@ private static void testRawJsonParam(RestTemplate 
template, String cseUrlPrefix)
     TestMgr.check("hello Tom",
         template.postForObject(cseUrlPrefix + "/compute/testrawjson", 
jsonPerson, String.class));
   }
+
+  private static void testValidatorAddFail(RestTemplate template, String 
cseUrlPrefix) {
+    Map<String, String> params = new HashMap<>();
+    params.put("a", "5");
+    params.put("b", "3");
+    boolean isExcep = false;
+    try {
+      template.postForObject(cseUrlPrefix + "add", params, Integer.class);
+    } catch (InvocationException e) {
+      isExcep = true;
+      TestMgr.check(400, e.getStatus().getStatusCode());
+      TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase());
+      TestMgr.check(
+          "CommonExceptionData 
[message=[ConstraintViolationImpl{interpolatedMessage='must be greater than or 
equal to 20', propertyPath=add.arg1, rootBeanClass=class 
org.apache.servicecomb.demo.jaxrs.server.Validator, 
messageTemplate='{javax.validation.constraints.Min.message}'}]]",
+          e.getErrorData());
+    }
+
+    TestMgr.check(true, isExcep);
+  }
+
+  private static void testValidatorAddSuccess(RestTemplate template, String 
cseUrlPrefix) {
+    Map<String, String> params = new HashMap<>();
+    params.put("a", "5");
+    params.put("b", "20");
+    int result = template.postForObject(cseUrlPrefix + "add", params, 
Integer.class);
+    TestMgr.check(25, result);
+  }
+
+  private static void testValidatorSayHiFail(RestTemplate template, String 
cseUrlPrefix) {
+    boolean isExcep = false;
+    try {
+      template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, 
String.class, "te");
+    } catch (InvocationException e) {
+      isExcep = true;
+      TestMgr.check(400, e.getStatus().getStatusCode());
+      TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase());
+      TestMgr.check(
+          "CommonExceptionData 
[message=[ConstraintViolationImpl{interpolatedMessage='length must be between 3 
and 2147483647', propertyPath=sayHi.arg0, rootBeanClass=class 
org.apache.servicecomb.demo.jaxrs.server.Validator, 
messageTemplate='{org.hibernate.validator.constraints.Length.message}'}]]",
+          e.getErrorData());
+    }
+    TestMgr.check(true, isExcep);
+  }
+
+  private static void testValidatorSayHiSuccess(RestTemplate template, String 
cseUrlPrefix) {
+    ResponseEntity<String> responseEntity =
+        template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, 
String.class, "world");
+    TestMgr.check(202, responseEntity.getStatusCode());
+    TestMgr.check("world sayhi", responseEntity.getBody());
+  }
+
+  private static void testValidatorExchangeFail(RestTemplate template, String 
cseUrlPrefix) {
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("Accept", MediaType.APPLICATION_JSON);
+    Student student = new Student();
+    student.setName("");
+    student.setAge(25);
+    boolean isExcep = false;
+    try {
+      HttpEntity<Student> requestEntity = new HttpEntity<>(student, headers);
+      template.exchange(cseUrlPrefix + "/sayhello",
+          HttpMethod.POST,
+          requestEntity,
+          Student.class);
+    } catch (InvocationException e) {
+      isExcep = true;
+      TestMgr.check(400, e.getStatus().getStatusCode());
+      TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase());
+      TestMgr.check(
+          "CommonExceptionData 
[message=[ConstraintViolationImpl{interpolatedMessage='must be less than or 
equal to 20', propertyPath=sayHello.arg0.age, rootBeanClass=class 
org.apache.servicecomb.demo.jaxrs.server.Validator, 
messageTemplate='{javax.validation.constraints.Max.message}'}]]",
+          e.getErrorData());
+    }
+    TestMgr.check(true, isExcep);
+  }
+
+  private static void testValidatorExchangeSuccess(RestTemplate template, 
String cseUrlPrefix) {
+    Student student = new Student();
+    student.setName("test");
+    student.setAge(15);
+    Student result = template.postForObject(cseUrlPrefix + "sayhello", 
student, Student.class);
+    TestMgr.check("hello test 15", result);
+  }
 }
diff --git a/demo/demo-jaxrs/jaxrs-server/pom.xml 
b/demo/demo-jaxrs/jaxrs-server/pom.xml
index af8de5619..0abb64f41 100644
--- a/demo/demo-jaxrs/jaxrs-server/pom.xml
+++ b/demo/demo-jaxrs/jaxrs-server/pom.xml
@@ -17,68 +17,69 @@
   -->
 
 <project
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";
-       xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
-       <modelVersion>4.0.0</modelVersion>
-       <parent>
-               <groupId>org.apache.servicecomb.demo</groupId>
-               <artifactId>demo-jaxrs</artifactId>
-               <version>1.0.0-m2-SNAPSHOT</version>
-       </parent>
-       <artifactId>jaxrs-server</artifactId>
-       <name>Java Chassis::Demo::JAXRS::Server</name>
-
-       <dependencies>
-               <dependency>
-                       <groupId>org.apache.servicecomb.demo</groupId>
-                       <artifactId>demo-schema</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.apache.servicecomb</groupId>
-                       <artifactId>provider-jaxrs</artifactId>
-               </dependency>
-       </dependencies>
-
-       <properties>
-               
<demo.main>org.apache.servicecomb.demo.jaxrs.server.JaxrsServer</demo.main>
-       </properties>
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.maven.plugins</groupId>
-                               <artifactId>maven-dependency-plugin</artifactId>
-                       </plugin>
-                       <plugin>
-                               
<groupId>com.github.odavid.maven.plugins</groupId>
-                               <artifactId>mixin-maven-plugin</artifactId>
-                               <configuration>
-                                       <mixins>
-                                               <mixin>
-                                                       
<groupId>org.apache.servicecomb.demo</groupId>
-                                                       
<artifactId>docker-build-config</artifactId>
-                                                       
<version>1.0.0-m2-SNAPSHOT</version>
-                                               </mixin>
-                                       </mixins>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
-
-       <profiles>
-               <profile>
-                       <id>docker</id>
-                       <build>
-                               <plugins>
-                                       <plugin>
-                                               <groupId>io.fabric8</groupId>
-                                               
<artifactId>docker-maven-plugin</artifactId>
-                                       </plugin>
-                                       <plugin>
-                                               
<groupId>org.commonjava.maven.plugins</groupId>
-                                               
<artifactId>directory-maven-plugin</artifactId>
-                                       </plugin>
-                               </plugins>
-                       </build>
-               </profile>
-       </profiles>
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";
+  xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.servicecomb.demo</groupId>
+    <artifactId>demo-jaxrs</artifactId>
+    <version>1.0.0-m2-SNAPSHOT</version>
+  </parent>
+  <artifactId>jaxrs-server</artifactId>
+  <name>Java Chassis::Demo::JAXRS::Server</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb.demo</groupId>
+      <artifactId>demo-schema</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>provider-jaxrs</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>swagger-invocation-validator</artifactId>
+    </dependency>
+  </dependencies>
+  <properties>
+    <demo.main>org.apache.servicecomb.demo.jaxrs.server.JaxrsServer</demo.main>
+  </properties>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>com.github.odavid.maven.plugins</groupId>
+        <artifactId>mixin-maven-plugin</artifactId>
+        <configuration>
+          <mixins>
+            <mixin>
+              <groupId>org.apache.servicecomb.demo</groupId>
+              <artifactId>docker-build-config</artifactId>
+              <version>1.0.0-m2-SNAPSHOT</version>
+            </mixin>
+          </mixins>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>docker</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>io.fabric8</groupId>
+            <artifactId>docker-maven-plugin</artifactId>
+          </plugin>
+          <plugin>
+            <groupId>org.commonjava.maven.plugins</groupId>
+            <artifactId>directory-maven-plugin</artifactId>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 </project>
diff --git 
a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java
 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java
new file mode 100644
index 000000000..986f6a348
--- /dev/null
+++ 
b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java
@@ -0,0 +1,61 @@
+/*
+ * 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.jaxrs.server;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Min;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.servicecomb.demo.validator.Student;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
+import org.hibernate.validator.constraints.Length;
+
+@RestSchema(schemaId = "validator")
+@Path("/validator")
+@Produces(MediaType.APPLICATION_JSON)
+public class Validator {
+
+  @Path("/add")
+  @POST
+  public int add(@FormParam("a") int a, @Min(20) @FormParam("b") int b) {
+    return a + b;
+  }
+
+  @Path("/sayhi/{name}")
+  @PUT
+  public String sayHi(@Length(min = 3) @PathParam("name") String name) {
+    ContextUtils.getInvocationContext().setStatus(202);
+    return name + " sayhi";
+  }
+
+  @Path("/sayhello")
+  @POST
+  public Student sayHello(@Valid Student student) {
+    student.setName("hello " + student.getName());
+    student.setAge(student.getAge());
+    return student;
+  }
+
+}
diff --git 
a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java
 
b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java
new file mode 100644
index 000000000..65feea2ec
--- /dev/null
+++ 
b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java
@@ -0,0 +1,58 @@
+/*
+ * 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.validator;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.NotNull;
+
+public class Student {
+  @NotNull
+  private String name;
+
+  @Max(20)
+  private int age;
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public Student() {
+  }
+
+  public int getAge() {
+    return age;
+  }
+
+  public void setAge(int age) {
+    this.age = age;
+  }
+
+  public Student(String name, int age) {
+    this.name = name;
+    this.age = age;
+  }
+
+  @Override
+  public String toString() {
+    return name + " " + age;
+  }
+}
diff --git a/demo/pom.xml b/demo/pom.xml
index 2cf4603c2..55505d2ad 100644
--- a/demo/pom.xml
+++ b/demo/pom.xml
@@ -47,7 +47,6 @@
     <module>demo-multiple</module>
     <module>demo-signature</module>
     <module>demo-edge</module>
-    
     <module>perf</module>
   </modules>
 
diff --git a/java-chassis-dependencies/pom.xml 
b/java-chassis-dependencies/pom.xml
index b7b622785..c0adb91c3 100644
--- a/java-chassis-dependencies/pom.xml
+++ b/java-chassis-dependencies/pom.xml
@@ -899,6 +899,11 @@
         <artifactId>swagger-invocation-springmvc</artifactId>
         <version>1.0.0-m2-SNAPSHOT</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.servicecomb</groupId>
+        <artifactId>swagger-invocation-validator</artifactId>
+        <version>1.0.0-m2-SNAPSHOT</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.servicecomb</groupId>
         <artifactId>service-registry</artifactId>
diff --git a/java-chassis-distribution/pom.xml 
b/java-chassis-distribution/pom.xml
index 95b30e1a0..ebaa6677a 100644
--- a/java-chassis-distribution/pom.xml
+++ b/java-chassis-distribution/pom.xml
@@ -88,6 +88,10 @@
             <groupId>org.apache.servicecomb</groupId>
             <artifactId>swagger-invocation-springmvc</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.servicecomb</groupId>
+            <artifactId>swagger-invocation-validator</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.apache.servicecomb</groupId>
             <artifactId>foundation-common</artifactId>
diff --git a/swagger/swagger-invocation/invocation-core/pom.xml 
b/swagger/swagger-invocation/invocation-core/pom.xml
index d60e95489..b7a367e99 100644
--- a/swagger/swagger-invocation/invocation-core/pom.xml
+++ b/swagger/swagger-invocation/invocation-core/pom.xml
@@ -48,4 +48,4 @@
                        <scope>test</scope>
                </dependency>
        </dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
index 4827a7641..5c3caf091 100644
--- 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
+++ 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
@@ -18,14 +18,17 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
 import 
org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapper;
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
 import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
+import 
org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension;
 import 
org.apache.servicecomb.swagger.invocation.response.producer.ProducerResponseMapper;
 
 public class SwaggerProducerOperation {
@@ -44,6 +47,9 @@
 
   private ProducerResponseMapper responseMapper;
 
+  private List<ProducerInvokeExtension> producerInvokeExtenstionList =
+      SPIServiceUtils.getSortedService(ProducerInvokeExtension.class);
+
   public String getName() {
     return name;
   }
@@ -119,6 +125,9 @@ public void completableFutureInvoke(SwaggerInvocation 
invocation, AsyncResponse
   public void doCompletableFutureInvoke(SwaggerInvocation invocation, 
AsyncResponse asyncResp) {
     try {
       Object[] args = argumentsMapper.toProducerArgs(invocation);
+      for (ProducerInvokeExtension producerInvokeExtension : 
producerInvokeExtenstionList) {
+        producerInvokeExtension.beforeMethodInvoke(invocation, this, args);
+      }
       Object result = producerMethod.invoke(producerInstance, args);
 
       ((CompletableFuture<Object>) result).whenComplete((realResult, ex) -> {
@@ -145,6 +154,9 @@ public Response doInvoke(SwaggerInvocation invocation) {
     Response response = null;
     try {
       Object[] args = argumentsMapper.toProducerArgs(invocation);
+      for (ProducerInvokeExtension producerInvokeExtension : 
producerInvokeExtenstionList) {
+        producerInvokeExtension.beforeMethodInvoke(invocation, this, args);
+      }
       Object result = producerMethod.invoke(producerInstance, args);
       response = responseMapper.mapResponse(invocation.getStatus(), result);
     } catch (Throwable e) {
diff --git 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverter.java
 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverter.java
index 3b36f5ab1..4c14ad87f 100644
--- 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverter.java
+++ 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverter.java
@@ -22,5 +22,9 @@
 public interface ExceptionToResponseConverter<T extends Throwable> {
   Class<T> getExceptionClass();
 
+  default int getOrder() {
+    return 0;
+  }
+
   Response convert(SwaggerInvocation swaggerInvocation, T e);
 }
diff --git 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverters.java
 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverters.java
index bc2ea3121..60706a900 100644
--- 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverters.java
+++ 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/exception/ExceptionToResponseConverters.java
@@ -31,7 +31,7 @@
 
   @SuppressWarnings("unchecked")
   public ExceptionToResponseConverters() {
-    
SPIServiceUtils.getAllService(ExceptionToResponseConverter.class).forEach(converter
 -> {
+    
SPIServiceUtils.getSortedService(ExceptionToResponseConverter.class).forEach(converter
 -> {
       if (converter.getExceptionClass() == null) {
         defaultConverter = converter;
         return;
diff --git 
a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/extension/ProducerInvokeExtension.java
 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/extension/ProducerInvokeExtension.java
new file mode 100644
index 000000000..370b3d192
--- /dev/null
+++ 
b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/invocation/extension/ProducerInvokeExtension.java
@@ -0,0 +1,32 @@
+/*
+ * 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.extension;
+
+import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
+import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+
+/**
+ * Producer method invocation extension to handle the required 
validations/checks before invoking the actual method.
+ */
+public interface ProducerInvokeExtension {
+
+  public int getOrder();
+
+  ///Invoked before the method execution to handle the required checks before 
method invocation.
+  <T> void beforeMethodInvoke(SwaggerInvocation invocation, 
SwaggerProducerOperation producerOperation,
+      Object[] args) throws Exception;
+}
diff --git 
a/swagger/swagger-invocation/invocation-core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
 
b/swagger/swagger-invocation/invocation-core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
index 2fc781e17..b717491e6 100644
--- 
a/swagger/swagger-invocation/invocation-core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
+++ 
b/swagger/swagger-invocation/invocation-core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
@@ -16,4 +16,4 @@
 #
 
 
org.apache.servicecomb.swagger.invocation.exception.InvocationExceptionToResponseConverter
-org.apache.servicecomb.swagger.invocation.exception.DefaultExceptionToResponseConverter
\ No newline at end of file
+org.apache.servicecomb.swagger.invocation.exception.DefaultExceptionToResponseConverter
diff --git 
a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/exception/TestExceptionToResponseConverters.java
 
b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/exception/TestExceptionToResponseConverters.java
index 221ae9eb7..022ff8ced 100644
--- 
a/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/exception/TestExceptionToResponseConverters.java
+++ 
b/swagger/swagger-invocation/invocation-core/src/test/java/org/apache/servicecomb/swagger/invocation/exception/TestExceptionToResponseConverters.java
@@ -38,7 +38,7 @@ public void convertExceptionToResponse(@Mocked 
ExceptionToResponseConverter c1,
       @Mocked Response rDef) {
     new Expectations(SPIServiceUtils.class) {
       {
-        SPIServiceUtils.getAllService(ExceptionToResponseConverter.class);
+        SPIServiceUtils.getSortedService(ExceptionToResponseConverter.class);
         result = Arrays.asList(c1, c2, cDef);
 
         c1.getExceptionClass();
diff --git a/swagger/swagger-invocation/invocation-validator/pom.xml 
b/swagger/swagger-invocation/invocation-validator/pom.xml
new file mode 100644
index 000000000..08b2c0c83
--- /dev/null
+++ b/swagger/swagger-invocation/invocation-validator/pom.xml
@@ -0,0 +1,52 @@
+<!--
+  ~ 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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.servicecomb</groupId>
+    <artifactId>swagger-invocation</artifactId>
+    <version>1.0.0-m2-SNAPSHOT</version>
+  </parent>
+  <artifactId>swagger-invocation-validator</artifactId>
+  <name>Java Chassis::Swagger::Invocation::Validator</name>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>swagger-invocation-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-validator</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.glassfish</groupId>
+      <artifactId>javax.el</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git 
a/swagger/swagger-invocation/invocation-validator/src/main/java/org/apache/servicecomb/swagger/invocation/validator/ConstraintViolationExceptionToResponseConverter.java
 
b/swagger/swagger-invocation/invocation-validator/src/main/java/org/apache/servicecomb/swagger/invocation/validator/ConstraintViolationExceptionToResponseConverter.java
new file mode 100644
index 000000000..5ade95199
--- /dev/null
+++ 
b/swagger/swagger-invocation/invocation-validator/src/main/java/org/apache/servicecomb/swagger/invocation/validator/ConstraintViolationExceptionToResponseConverter.java
@@ -0,0 +1,43 @@
+/*
+ * 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.validator;
+
+import javax.validation.ConstraintViolationException;
+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 ConstraintViolationExceptionToResponseConverter
+    implements ExceptionToResponseConverter<ConstraintViolationException> {
+  @Override
+  public Class<ConstraintViolationException> getExceptionClass() {
+    return ConstraintViolationException.class;
+  }
+
+  @Override
+  public Response convert(SwaggerInvocation swaggerInvocation, 
ConstraintViolationException e) {
+    return Response.createFail(new InvocationException(Status.BAD_REQUEST, 
e.getConstraintViolations().toString()));
+  }
+
+  @Override
+  public int getOrder() {
+    return -100;
+  }
+}
diff --git 
a/swagger/swagger-invocation/invocation-validator/src/main/java/org/apache/servicecomb/swagger/invocation/validator/ParameterValidator.java
 
b/swagger/swagger-invocation/invocation-validator/src/main/java/org/apache/servicecomb/swagger/invocation/validator/ParameterValidator.java
new file mode 100644
index 000000000..0cb42ed58
--- /dev/null
+++ 
b/swagger/swagger-invocation/invocation-validator/src/main/java/org/apache/servicecomb/swagger/invocation/validator/ParameterValidator.java
@@ -0,0 +1,65 @@
+/*
+ * 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.validator;
+
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.Validation;
+import javax.validation.ValidatorFactory;
+import javax.validation.executable.ExecutableValidator;
+import javax.validation.groups.Default;
+
+import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
+import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+import 
org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ParameterValidator implements ProducerInvokeExtension {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(ParameterValidator.class);
+
+  private static ExecutableValidator executableValidator;
+
+  @Override
+  public <T> void beforeMethodInvoke(SwaggerInvocation invocation, 
SwaggerProducerOperation producerOperation,
+      Object[] args)
+      throws ConstraintViolationException {
+
+    if (null == executableValidator) {
+      ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+      executableValidator = factory.getValidator().forExecutables();
+    }
+    Set<ConstraintViolation<Object>> violations =
+        
executableValidator.validateParameters(producerOperation.getProducerInstance(),
+            producerOperation.getProducerMethod(),
+            args,
+            Default.class);
+    if (violations.size() > 0) {
+      LOGGER.warn("Parameter validation failed : " + violations.toString());
+      throw new ConstraintViolationException(violations);
+    }
+  }
+
+  @Override
+  public int getOrder() {
+    return 100;
+  }
+
+}
diff --git 
a/swagger/swagger-invocation/invocation-validator/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
 
b/swagger/swagger-invocation/invocation-validator/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToResponseConverter
new file mode 100644
index 000000000..9667b7a6b
--- /dev/null
+++ 
b/swagger/swagger-invocation/invocation-validator/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.swagger.invocation.validator.ConstraintViolationExceptionToResponseConverter
\ No newline at end of file
diff --git 
a/swagger/swagger-invocation/invocation-validator/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension
 
b/swagger/swagger-invocation/invocation-validator/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension
new file mode 100644
index 000000000..215fc5692
--- /dev/null
+++ 
b/swagger/swagger-invocation/invocation-validator/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension
@@ -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.swagger.invocation.validator.ParameterValidator
diff --git a/swagger/swagger-invocation/pom.xml 
b/swagger/swagger-invocation/pom.xml
index b22339c29..515db2c5a 100644
--- a/swagger/swagger-invocation/pom.xml
+++ b/swagger/swagger-invocation/pom.xml
@@ -30,5 +30,6 @@
        <module>invocation-core</module>
        <module>invocation-jaxrs</module>
        <module>invocation-springmvc</module>
+       <module>invocation-validator</module>
   </modules>
 </project>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to