You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@dubbo.apache.org by GitBox <gi...@apache.org> on 2018/04/20 08:43:52 UTC

[GitHub] stefli closed pull request #1644: Issue about the provider side parameter validation

stefli closed pull request #1644: Issue about the provider side parameter validation
URL: https://github.com/apache/incubator-dubbo/pull/1644
 
 
   

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/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java
index 6369c9785a..44789fa00a 100644
--- a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/DemoService.java
@@ -20,4 +20,6 @@
 
     String sayHello(String name);
 
+    String sayHelloWithParameterValidation(RequestParam param);
+
 }
\ No newline at end of file
diff --git a/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/RequestParam.java b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/RequestParam.java
new file mode 100644
index 0000000000..fcc8d7da8e
--- /dev/null
+++ b/dubbo-demo/dubbo-demo-api/src/main/java/com/alibaba/dubbo/demo/RequestParam.java
@@ -0,0 +1,34 @@
+package com.alibaba.dubbo.demo;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+
+/**
+ * Demo for parameter validation
+ */
+public class RequestParam implements Serializable {
+
+    private static final long serialVersionUID = -2985070735827125058L;
+
+    public RequestParam() {
+    }
+
+    public RequestParam(String name) {
+        this.name = name;
+    }
+
+    @NotEmpty(message = "Name required!")
+    @Size(min = 6, max = 20, message = "Between 6 and 20!")
+    private String name;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+}
diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java
index 9caacbc7ad..cd48d6e7b8 100644
--- a/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/java/com/alibaba/dubbo/demo/consumer/Consumer.java
@@ -17,8 +17,16 @@
 package com.alibaba.dubbo.demo.consumer;
 
 import com.alibaba.dubbo.demo.DemoService;
+import com.alibaba.dubbo.demo.RequestParam;
+import com.alibaba.dubbo.rpc.RpcException;
+import org.hibernate.validator.internal.engine.path.PathImpl;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.Iterator;
+import java.util.Set;
+
 public class Consumer {
 
     public static void main(String[] args) {
@@ -34,7 +42,22 @@ public static void main(String[] args) {
                 Thread.sleep(1000);
                 String hello = demoService.sayHello("world"); // call remote method
                 System.out.println(hello); // get result
-
+                String helloWithParameterValidation = demoService.sayHelloWithParameterValidation(new RequestParam("hello")); // call remote method
+                System.out.println(helloWithParameterValidation); // get result
+            } catch (RpcException e) {
+                if (e.getCause() instanceof ConstraintViolationException) {
+                    ConstraintViolationException ve = (ConstraintViolationException) e.getCause();
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Iterator it = violations.iterator();
+                    while (it.hasNext()) {
+                        ConstraintViolation cv = (ConstraintViolation) it.next();
+                        String name = ((PathImpl) cv.getPropertyPath()).getLeafNode().getName();
+                        String message = cv.getMessage();
+                        System.out.printf("The value [hello] of the field [%s] check failed with message [%s]", name, message);
+                    }
+                } else {
+                    throw e;
+                }
             } catch (Throwable throwable) {
                 throwable.printStackTrace();
             }
@@ -43,4 +66,5 @@ public static void main(String[] args) {
         }
 
     }
+
 }
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
index 59281a8277..71867d9359 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
+++ b/dubbo-demo/dubbo-demo-provider/src/main/java/com/alibaba/dubbo/demo/provider/DemoServiceImpl.java
@@ -17,6 +17,7 @@
 package com.alibaba.dubbo.demo.provider;
 
 import com.alibaba.dubbo.demo.DemoService;
+import com.alibaba.dubbo.demo.RequestParam;
 import com.alibaba.dubbo.rpc.RpcContext;
 
 import java.text.SimpleDateFormat;
@@ -29,4 +30,9 @@ public String sayHello(String name) {
         return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
     }
 
+    public String sayHelloWithParameterValidation(RequestParam param) {
+        System.out.println("Hello " + param.getName() + " with parameter validation, request from consumer: " + RpcContext.getContext().getRemoteAddress());
+        return "Hello " + param.getName() + " with parameter validation, response from provider: " + RpcContext.getContext().getLocalAddress();
+    }
+
 }
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
index 46c87e37da..5f863e339b 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -34,6 +34,6 @@
     <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
 
     <!-- declare the service interface to be exported -->
-    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
+    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" validation="true"/>
 
 </beans>
\ No newline at end of file
diff --git a/dubbo-demo/pom.xml b/dubbo-demo/pom.xml
index 051fd7d930..d868b019bc 100644
--- a/dubbo-demo/pom.xml
+++ b/dubbo-demo/pom.xml
@@ -47,4 +47,21 @@
         </dependencies>
     </dependencyManagement>
 
+    <dependencies>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.el</groupId>
+            <artifactId>javax.el-api</artifactId>
+            <version>2.2.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.web</groupId>
+            <artifactId>javax.el</artifactId>
+            <version>2.2.4</version>
+        </dependency>
+    </dependencies>
+
 </project>
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/CustomConstraintViolation.java b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/CustomConstraintViolation.java
new file mode 100644
index 0000000000..1594296c9d
--- /dev/null
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/CustomConstraintViolation.java
@@ -0,0 +1,97 @@
+package com.alibaba.dubbo.validation;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Path;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.io.Serializable;
+
+/**
+ * Custom constraint violation to store the validation errors
+ * In order to instead of the implementation of hibernate validator
+ * @author stefli
+ * @param <T>
+ */
+public class CustomConstraintViolation<T> implements ConstraintViolation<T>, Serializable {
+
+    private static final long serialVersionUID = -3042079204640314031L;
+
+    private String message;
+    private Path path;
+
+    public CustomConstraintViolation() {
+
+    }
+
+    public CustomConstraintViolation(String message, Path path) {
+        this.message = message;
+        this.path = path;
+    }
+
+    public Path getPath() {
+        return path;
+    }
+
+    public void setPath(Path path) {
+        this.path = path;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public String getMessageTemplate() {
+        return null;
+    }
+
+    @Override
+    public T getRootBean() {
+        return null;
+    }
+
+    @Override
+    public Class<T> getRootBeanClass() {
+        return null;
+    }
+
+    @Override
+    public Object getLeafBean() {
+        return null;
+    }
+
+    @Override
+    public Object[] getExecutableParameters() {
+        return null;
+    }
+
+    @Override
+    public Object getExecutableReturnValue() {
+        return null;
+    }
+
+    @Override
+    public Path getPropertyPath() {
+        return this.path;
+    }
+
+    @Override
+    public Object getInvalidValue() {
+        return null;
+    }
+
+    @Override
+    public ConstraintDescriptor<?> getConstraintDescriptor() {
+        return null;
+    }
+
+    @Override
+    public <U> U unwrap(Class<U> type) {
+        return null;
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/CustomConstraintViolationException.java b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/CustomConstraintViolationException.java
new file mode 100644
index 0000000000..7f2aff2e22
--- /dev/null
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/CustomConstraintViolationException.java
@@ -0,0 +1,51 @@
+package com.alibaba.dubbo.validation;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.Set;
+
+/**
+ * Custom constraint violation exception to wrap the errors
+ * @author stefli
+ *
+ */
+public class CustomConstraintViolationException extends ConstraintViolationException {
+
+    private static final long serialVersionUID = 1915414386865706919L;
+
+    private String message;
+    private Set<ConstraintViolation<?>> constraintViolations;
+
+    public CustomConstraintViolationException() {
+        super(null);
+    }
+
+    public CustomConstraintViolationException(String message, Set<ConstraintViolation<?>> constraintViolations) {
+        super(message, constraintViolations);
+        this.message = message;
+        this.constraintViolations = constraintViolations;
+    }
+
+    public CustomConstraintViolationException(Set<ConstraintViolation<?>> constraintViolations) {
+        this(null, constraintViolations);
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    @Override
+    public Set<ConstraintViolation<?>> getConstraintViolations() {
+        return constraintViolations;
+    }
+
+    public void setConstraintViolations(Set<ConstraintViolation<?>> constraintViolations) {
+        this.constraintViolations = constraintViolations;
+    }
+
+}
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/filter/ValidationFilter.java b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/filter/ValidationFilter.java
index d26d01888d..b02c9389bd 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/filter/ValidationFilter.java
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/com/alibaba/dubbo/validation/filter/ValidationFilter.java
@@ -25,11 +25,21 @@
 import com.alibaba.dubbo.rpc.Result;
 import com.alibaba.dubbo.rpc.RpcException;
 import com.alibaba.dubbo.rpc.RpcResult;
+import com.alibaba.dubbo.validation.CustomConstraintViolation;
+import com.alibaba.dubbo.validation.CustomConstraintViolationException;
 import com.alibaba.dubbo.validation.Validation;
 import com.alibaba.dubbo.validation.Validator;
 
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * ValidationFilter
+ * Use custom constraint violation exception to wrap the message and property path
+ *
+ * @author stefli
  */
 @Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.VALIDATION_KEY, order = 10000)
 public class ValidationFilter implements Filter {
@@ -46,14 +56,21 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
             try {
                 Validator validator = validation.getValidator(invoker.getUrl());
                 if (validator != null) {
-                    validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
+                    validator.validate(invocation.getMethodName(), invocation.getParameterTypes(),
+                            invocation.getArguments());
+                }
+            } catch (ConstraintViolationException e) {
+                Set<ConstraintViolation<?>> set = new HashSet<ConstraintViolation<?>>();
+                for (ConstraintViolation<?> v : e.getConstraintViolations()) {
+                    set.add(new CustomConstraintViolation<String>(v.getMessage(), v.getPropertyPath()));
                 }
-            } catch (RpcException e) {
-                throw e;
-            } catch (Throwable t) {
-                return new RpcResult(t);
+
+                return new RpcResult(new RpcException(new CustomConstraintViolationException(set)));
+            } catch (Exception e) {
+                return new RpcResult(new RpcException(e));
             }
         }
+
         return invoker.invoke(invocation);
     }
 
diff --git a/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/com/alibaba/dubbo/test/provider/DefaultDemoService.java b/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/com/alibaba/dubbo/test/provider/DefaultDemoService.java
index 004f9a70d9..7fc109b891 100644
--- a/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/com/alibaba/dubbo/test/provider/DefaultDemoService.java
+++ b/dubbo-test/dubbo-test-compatibility/dubbo-test-spring3/src/main/java/com/alibaba/dubbo/test/provider/DefaultDemoService.java
@@ -18,6 +18,7 @@
 
 import com.alibaba.dubbo.config.annotation.Service;
 import com.alibaba.dubbo.demo.DemoService;
+import com.alibaba.dubbo.demo.RequestParam;
 
 /**
  * Default {@link DemoService} implementation
@@ -37,4 +38,9 @@ public String sayHello(String name) {
         return "DefaultDemoService - sayHell() : " + name;
     }
 
+    @Override
+    public String sayHelloWithParameterValidation(RequestParam param) {
+        return "DefaultDemoService - sayHelloWithParameterValidation() : " + param.getName();
+    }
+
 }


 

----------------------------------------------------------------
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:
users@infra.apache.org


With regards,
Apache Git Services