You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2022/01/23 09:04:10 UTC

[dubbo] branch 3.0 updated: feature: support jsr-303 jakarta namespace (#9552)

This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new c589064  feature: support jsr-303 jakarta namespace (#9552)
c589064 is described below

commit c589064e2056ce257f51f9905d236ef8e2159d4d
Author: 桔子 <ju...@qq.com>
AuthorDate: Sun Jan 23 17:03:57 2022 +0800

    feature: support jsr-303 jakarta namespace (#9552)
    
    Java EE has been renamed from javax to jakarta, including the jsr-303 api.
    To support Hibernate Validator 7.x, a new JValidatorNew file has been added for compatibility with version 7.x
    
    close #9544
---
 dubbo-dependencies-bom/pom.xml                     | 11 +++
 dubbo-filter/dubbo-filter-validation/pom.xml       |  4 +
 .../dubbo/validation/filter/ValidationFilter.java  |  9 +--
 .../support/jvalidation/JValidationNew.java        | 40 ++++++++++
 .../validation/support/jvalidation/JValidator.java | 61 ++++++++-------
 .../{JValidator.java => JValidatorNew.java}        | 87 ++++++++++++----------
 .../org.apache.dubbo.validation.Validation         |  3 +-
 .../support/jvalidation/JValidatorTest.java        |  6 +-
 .../java/org/apache/dubbo/rpc/RpcException.java    |  9 ++-
 9 files changed, 152 insertions(+), 78 deletions(-)

diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index b0236bd..f89b1b8 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -114,6 +114,7 @@
         <javax_annotation-api_version>1.3.2</javax_annotation-api_version>
         <servlet_version>3.1.0</servlet_version>
         <jetty_version>9.4.43.v20210629</jetty_version>
+        <validation_new_version>3.0.1</validation_new_version>
         <validation_version>1.1.0.Final</validation_version>
         <hibernate_validator_version>5.4.1.Final</hibernate_validator_version>
         <jel_version>3.0.1-b08</jel_version>
@@ -395,6 +396,16 @@
                 <version>${jel_version}</version>
             </dependency>
             <dependency>
+                <groupId>jakarta.validation</groupId>
+                <artifactId>jakarta.validation-api</artifactId>
+                <version>${validation_new_version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.hibernate.validator</groupId>
+                <artifactId>hibernate-validator</artifactId>
+                <version>${hibernate_validator_new_version}</version>
+            </dependency>
+            <dependency>
                 <groupId>javax.cache</groupId>
                 <artifactId>cache-api</artifactId>
                 <version>${jcache_version}</version>
diff --git a/dubbo-filter/dubbo-filter-validation/pom.xml b/dubbo-filter/dubbo-filter-validation/pom.xml
index 51d70ae..e302706 100644
--- a/dubbo-filter/dubbo-filter-validation/pom.xml
+++ b/dubbo-filter/dubbo-filter-validation/pom.xml
@@ -35,6 +35,10 @@
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
+            <groupId>jakarta.validation</groupId>
+            <artifactId>jakarta.validation-api</artifactId>
+        </dependency>
+        <dependency>
             <groupId>javax.validation</groupId>
             <artifactId>validation-api</artifactId>
         </dependency>
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java
index 0df2752..50699b5 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/filter/ValidationFilter.java
@@ -27,8 +27,6 @@ import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.validation.Validation;
 import org.apache.dubbo.validation.Validator;
 
-import javax.validation.ValidationException;
-
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
 import static org.apache.dubbo.common.constants.FilterConstants.VALIDATION_KEY;
@@ -90,10 +88,11 @@ public class ValidationFilter implements Filter {
                     validator.validate(invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
                 }
             } catch (RpcException e) {
+                if(e.isValidation()){
+
+                    return AsyncRpcResult.newDefaultAsyncResult(e, invocation);
+                }
                 throw e;
-            } catch (ValidationException e) {
-                // only use exception's message to avoid potential serialization issue
-                return AsyncRpcResult.newDefaultAsyncResult(new ValidationException(e.getMessage()), invocation);
             } catch (Throwable t) {
                 return AsyncRpcResult.newDefaultAsyncResult(t, invocation);
             }
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidationNew.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidationNew.java
new file mode 100644
index 0000000..32cec16
--- /dev/null
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidationNew.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.dubbo.validation.support.jvalidation;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.validation.Validator;
+import org.apache.dubbo.validation.support.AbstractValidation;
+
+/**
+ * Creates a new instance of {@link Validator} using input argument url.
+ * @see AbstractValidation
+ * @see Validator
+ */
+public class JValidationNew extends AbstractValidation {
+
+    /**
+     * Return new instance of {@link JValidator}
+     * @param url Valid URL instance
+     * @return Instance of JValidator
+     */
+    @Override
+    protected Validator createValidator(URL url) {
+        return new JValidatorNew(url);
+    }
+
+}
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
index cc4da05..b6797f6 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.bytecode.ClassGenerator;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.validation.MethodValidated;
 import org.apache.dubbo.validation.Validator;
 
@@ -51,6 +52,7 @@ import javax.validation.Constraint;
 import javax.validation.ConstraintViolation;
 import javax.validation.ConstraintViolationException;
 import javax.validation.Validation;
+import javax.validation.ValidationException;
 import javax.validation.ValidatorFactory;
 import javax.validation.groups.Default;
 import java.lang.annotation.Annotation;
@@ -256,37 +258,42 @@ public class JValidator implements Validator {
 
     @Override
     public void validate(String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Exception {
-        List<Class<?>> groups = new ArrayList<>();
-        Class<?> methodClass = methodClass(methodName);
-        if (methodClass != null) {
-            groups.add(methodClass);
-        }
-        Set<ConstraintViolation<?>> violations = new HashSet<>();
-        Method method = clazz.getMethod(methodName, parameterTypes);
-        Class<?>[] methodClasses;
-        if (method.isAnnotationPresent(MethodValidated.class)){
-            methodClasses = method.getAnnotation(MethodValidated.class).value();
-            groups.addAll(Arrays.asList(methodClasses));
-        }
-        // add into default group
-        groups.add(0, Default.class);
-        groups.add(1, clazz);
+        try {
+            List<Class<?>> groups = new ArrayList<>();
+            Class<?> methodClass = methodClass(methodName);
+            if (methodClass != null) {
+                groups.add(methodClass);
+            }
+            Set<ConstraintViolation<?>> violations = new HashSet<>();
+            Method method = clazz.getMethod(methodName, parameterTypes);
+            Class<?>[] methodClasses;
+            if (method.isAnnotationPresent(MethodValidated.class)){
+                methodClasses = method.getAnnotation(MethodValidated.class).value();
+                groups.addAll(Arrays.asList(methodClasses));
+            }
+            // add into default group
+            groups.add(0, Default.class);
+            groups.add(1, clazz);
 
-        // convert list to array
-        Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
+            // convert list to array
+            Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
 
-        Object parameterBean = getMethodParameterBean(clazz, method, arguments);
-        if (parameterBean != null) {
-            violations.addAll(validator.validate(parameterBean, classgroups ));
-        }
+            Object parameterBean = getMethodParameterBean(clazz, method, arguments);
+            if (parameterBean != null) {
+                violations.addAll(validator.validate(parameterBean, classgroups ));
+            }
 
-        for (Object arg : arguments) {
-            validate(violations, arg, classgroups);
-        }
+            for (Object arg : arguments) {
+                validate(violations, arg, classgroups);
+            }
 
-        if (!violations.isEmpty()) {
-            logger.error("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations);
-            throw new ConstraintViolationException("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations, violations);
+            if (!violations.isEmpty()) {
+                logger.error("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations);
+                throw new ConstraintViolationException("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations, violations);
+            }
+        } catch (ValidationException e) {
+            // only use exception's message to avoid potential serialization issue
+            throw new RpcException(RpcException.VALIDATION_EXCEPTION, e.getMessage(), e);
         }
     }
 
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java
similarity index 84%
copy from dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
copy to dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java
index cc4da05..a23b32f 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidatorNew.java
@@ -21,9 +21,17 @@ import org.apache.dubbo.common.bytecode.ClassGenerator;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.validation.MethodValidated;
 import org.apache.dubbo.validation.Validator;
 
+import jakarta.validation.Constraint;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import jakarta.validation.Validation;
+import jakarta.validation.ValidationException;
+import jakarta.validation.ValidatorFactory;
+import jakarta.validation.groups.Default;
 import javassist.ClassPool;
 import javassist.CtClass;
 import javassist.CtField;
@@ -47,12 +55,6 @@ import javassist.bytecode.annotation.MemberValue;
 import javassist.bytecode.annotation.ShortMemberValue;
 import javassist.bytecode.annotation.StringMemberValue;
 
-import javax.validation.Constraint;
-import javax.validation.ConstraintViolation;
-import javax.validation.ConstraintViolationException;
-import javax.validation.Validation;
-import javax.validation.ValidatorFactory;
-import javax.validation.groups.Default;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
@@ -67,25 +69,25 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * Implementation of JValidation. JValidation is invoked if configuration validation attribute value is 'jvalidation'.
+ * Implementation of JValidationNew. JValidationNew is invoked if configuration validation attribute value is 'jvalidationNew'.
  * <pre>
- *     e.g. &lt;dubbo:method name="save" validation="jvalidation" /&gt;
+ *     e.g. &lt;dubbo:method name="save" validation="jvalidationNew" /&gt;
  * </pre>
  */
-public class JValidator implements Validator {
+public class JValidatorNew implements Validator {
 
-    private static final Logger logger = LoggerFactory.getLogger(JValidator.class);
+    private static final Logger logger = LoggerFactory.getLogger(JValidatorNew.class);
 
     private final Class<?> clazz;
 
     private final Map<String, Class> methodClassMap;
 
-    private final javax.validation.Validator validator;
+    private final jakarta.validation.Validator validator;
 
     @SuppressWarnings({"unchecked", "rawtypes"})
-    public JValidator(URL url) {
+    public JValidatorNew(URL url) {
         this.clazz = ReflectUtils.forName(url.getServiceInterface());
-        String jvalidation = url.getParameter("jvalidation");
+        String jvalidation = url.getParameter("jvalidationNew");
         ValidatorFactory factory;
         if (jvalidation != null && jvalidation.length() > 0) {
             factory = Validation.byProvider((Class) ReflectUtils.forName(jvalidation)).configure().buildValidatorFactory();
@@ -256,37 +258,42 @@ public class JValidator implements Validator {
 
     @Override
     public void validate(String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Exception {
-        List<Class<?>> groups = new ArrayList<>();
-        Class<?> methodClass = methodClass(methodName);
-        if (methodClass != null) {
-            groups.add(methodClass);
-        }
-        Set<ConstraintViolation<?>> violations = new HashSet<>();
-        Method method = clazz.getMethod(methodName, parameterTypes);
-        Class<?>[] methodClasses;
-        if (method.isAnnotationPresent(MethodValidated.class)){
-            methodClasses = method.getAnnotation(MethodValidated.class).value();
-            groups.addAll(Arrays.asList(methodClasses));
-        }
-        // add into default group
-        groups.add(0, Default.class);
-        groups.add(1, clazz);
+        try {
+            List<Class<?>> groups = new ArrayList<>();
+            Class<?> methodClass = methodClass(methodName);
+            if (methodClass != null) {
+                groups.add(methodClass);
+            }
+            Set<ConstraintViolation<?>> violations = new HashSet<>();
+            Method method = clazz.getMethod(methodName, parameterTypes);
+            Class<?>[] methodClasses;
+            if (method.isAnnotationPresent(MethodValidated.class)){
+                methodClasses = method.getAnnotation(MethodValidated.class).value();
+                groups.addAll(Arrays.asList(methodClasses));
+            }
+            // add into default group
+            groups.add(0, Default.class);
+            groups.add(1, clazz);
 
-        // convert list to array
-        Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
+            // convert list to array
+            Class<?>[] classgroups = groups.toArray(new Class[groups.size()]);
 
-        Object parameterBean = getMethodParameterBean(clazz, method, arguments);
-        if (parameterBean != null) {
-            violations.addAll(validator.validate(parameterBean, classgroups ));
-        }
+            Object parameterBean = getMethodParameterBean(clazz, method, arguments);
+            if (parameterBean != null) {
+                violations.addAll(validator.validate(parameterBean, classgroups ));
+            }
 
-        for (Object arg : arguments) {
-            validate(violations, arg, classgroups);
-        }
+            for (Object arg : arguments) {
+                validate(violations, arg, classgroups);
+            }
 
-        if (!violations.isEmpty()) {
-            logger.error("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations);
-            throw new ConstraintViolationException("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations, violations);
+            if (!violations.isEmpty()) {
+                logger.error("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations);
+                throw new ConstraintViolationException("Failed to validate service: " + clazz.getName() + ", method: " + methodName + ", cause: " + violations, violations);
+            }
+        } catch (ValidationException e) {
+            // only use exception's message to avoid potential serialization issue
+            throw new RpcException(RpcException.VALIDATION_EXCEPTION, e.getMessage(), e);
         }
     }
 
diff --git a/dubbo-filter/dubbo-filter-validation/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.validation.Validation b/dubbo-filter/dubbo-filter-validation/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.validation.Validation
index ae3dc96..98ee4f5 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.validation.Validation
+++ b/dubbo-filter/dubbo-filter-validation/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.validation.Validation
@@ -1 +1,2 @@
-jvalidation=org.apache.dubbo.validation.support.jvalidation.JValidation
\ No newline at end of file
+jvalidation=org.apache.dubbo.validation.support.jvalidation.JValidation
+jvalidationNew=org.apache.dubbo.validation.support.jvalidation.JValidationNew
\ No newline at end of file
diff --git a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java
index 01db4b9..acfb7c7 100644
--- a/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java
+++ b/dubbo-filter/dubbo-filter-validation/src/test/java/org/apache/dubbo/validation/support/jvalidation/JValidatorTest.java
@@ -17,12 +17,12 @@
 package org.apache.dubbo.validation.support.jvalidation;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.validation.support.jvalidation.mock.ValidationParameter;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import javax.validation.ConstraintViolationException;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -47,11 +47,13 @@ public class JValidatorTest {
 
     @Test
     public void testItWhenItViolatedConstraint() throws Exception {
-        Assertions.assertThrows(ConstraintViolationException.class, () -> {
+        RpcException rpcException = Assertions.assertThrows(RpcException.class, () -> {
             URL url = URL.valueOf("test://test:11/org.apache.dubbo.validation.support.jvalidation.mock.JValidatorTestTarget");
             JValidator jValidator = new JValidator(url);
             jValidator.validate("someMethod2", new Class<?>[]{ValidationParameter.class}, new Object[]{new ValidationParameter()});
         });
+
+        Assertions.assertTrue(rpcException.isValidation());
     }
 
     @Test
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java
index 11bfe82..9ab6afa 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcException.java
@@ -22,12 +22,10 @@ import javax.naming.LimitExceededException;
  * RPC Exception. (API, Prototype, ThreadSafe)
  *
  * @serial Don't change the class name and properties.
- * @export
  * @see org.apache.dubbo.rpc.Invoker#invoke(Invocation)
  * @since 1.0
  */
-public /**final**/
-class RpcException extends RuntimeException {
+public class RpcException extends RuntimeException {
 
     public static final int UNKNOWN_EXCEPTION = 0;
     public static final int NETWORK_EXCEPTION = 1;
@@ -41,6 +39,7 @@ class RpcException extends RuntimeException {
     public static final int REGISTRY_EXCEPTION = 9;
     public static final int ROUTER_CACHE_NOT_BUILD = 10;
     public static final int METHOD_NOT_FOUND = 11;
+    public static final int VALIDATION_EXCEPTION = 12;
     private static final long serialVersionUID = 7815426752583648734L;
     /**
      * RpcException cannot be extended, use error code for exception type to keep compatibility
@@ -118,4 +117,8 @@ class RpcException extends RuntimeException {
     public boolean isLimitExceed() {
         return code == LIMIT_EXCEEDED_EXCEPTION || getCause() instanceof LimitExceededException;
     }
+
+    public boolean isValidation() {
+        return code == VALIDATION_EXCEPTION;
+    }
 }