You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2020/06/09 20:44:56 UTC

[cxf] branch master updated: CXF-8296: Custom Boolean ParamConverter wrong behaviour (#677)

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

reta pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new e68022f  CXF-8296: Custom Boolean ParamConverter wrong behaviour (#677)
e68022f is described below

commit e68022f3d92725f4379391559cf843bd56335673
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Tue Jun 9 16:44:40 2020 -0400

    CXF-8296: Custom Boolean ParamConverter wrong behaviour (#677)
---
 .../org/apache/cxf/jaxrs/utils/InjectionUtils.java | 37 +++++++++----
 .../test/java/org/apache/cxf/jaxrs/Customer.java   | 12 ++++-
 .../org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java | 62 ++++++++++++++++++++++
 3 files changed, 100 insertions(+), 11 deletions(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
index f2204bf..7e73cae 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
@@ -45,6 +45,7 @@ import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.SortedSet;
@@ -435,9 +436,12 @@ public final class InjectionUtils {
 
         value = decodeValue(value, decoded, pType);
 
+        final Optional<ParamConverter<T>> converter = getParamConverter(pClass, genericType, paramAnns, message);
         Object result = null;
         try {
-            result = createFromParameterHandler(value, pClass, genericType, paramAnns, message);
+            if (converter.isPresent()) {
+                result = converter.get().fromString(value);
+            }
         } catch (IllegalArgumentException nfe) {
             throw createParamConversionException(pType, nfe);
         }
@@ -449,6 +453,10 @@ public final class InjectionUtils {
                 theResult = pClass.cast(result);
             }
             return theResult;
+        } else if (converter.isPresent() && !pClass.isPrimitive()) {
+            // The converter was applied and returned null value, acceptable
+            // outcome for non-primitive type.
+            return pClass.cast(result);
         }
 
         if (Number.class.isAssignableFrom(pClass) && "".equals(value)) {
@@ -539,21 +547,30 @@ public final class InjectionUtils {
         }
         return ExceptionUtils.toBadRequestException(ex, null);
     }
+    
+    public static <T> Optional<ParamConverter<T>> getParamConverter(Class<T> pClass,
+            Type genericType, Annotation[] anns, Message message) {
+        
+        if (message != null) {
+            ServerProviderFactory pf = ServerProviderFactory.getInstance(message);
+            ParamConverter<T> pm = pf.createParameterHandler(pClass, genericType, anns, message);
+            return Optional.ofNullable(pm);
+        }
+        
+        return Optional.empty();
+    }
+
     public static <T> T createFromParameterHandler(String value,
                                                     Class<T> pClass,
                                                     Type genericType,
                                                     Annotation[] anns,
                                                     Message message) {
-        T result = null;
-        if (message != null) {
-            ServerProviderFactory pf = ServerProviderFactory.getInstance(message);
-            ParamConverter<T> pm = pf.createParameterHandler(pClass, genericType, anns, message);
-            if (pm != null) {
-                result = pm.fromString(value);
-            }
-        }
-        return result;
+        return getParamConverter(pClass, genericType, anns, message)
+            .map(pm -> pm.fromString(value))
+            .orElse(null);
     }
+    
+    
 
     public static void reportServerError(String messageName, String parameter) {
         reportServerError(messageName, parameter, true);
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java
index 998fe31..10f7e50 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/Customer.java
@@ -33,6 +33,7 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.CookieParam;
 import javax.ws.rs.DefaultValue;
@@ -85,6 +86,8 @@ public class Customer extends AbstractCustomer implements CustomerInfo {
         //CHECKSTYLE:OFF
         public List<CustomerBean> e;
         //CHECKSTYLE:ON
+        @FormParam("value")
+        private Boolean bool;
 
         public void setA(String aString) {
             this.a = aString;
@@ -122,7 +125,12 @@ public class Customer extends AbstractCustomer implements CustomerInfo {
         public void setCb(boolean cb) {
             this.cb = cb;
         }
-
+        public void setBool(Boolean bool) {
+            this.bool = bool;
+        }
+        public Boolean getBool() {
+            return bool;
+        }
     }
 
     @Context private ContextResolver<JAXBContext> cr;
@@ -251,7 +259,9 @@ public class Customer extends AbstractCustomer implements CustomerInfo {
     public void testMatrixBean(@MatrixParam("") CustomerBean cb) {
 
     }
+    public void testBeanParam(@BeanParam CustomerBean cb) {
 
+    }
     public Application getApplication1() {
         return application1;
     }
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
index 969bda4..9638f37 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
@@ -2061,6 +2061,42 @@ public class JAXRSUtilsTest {
         SimpleFactory sf = (SimpleFactory)params.get(1);
         assertEquals(2, sf.getId());
     }
+    
+    @Test
+    public void testBeanParamsWithBooleanConverter() throws Exception {
+        Class<?>[] argType = {Customer.CustomerBean.class};
+        Method m = Customer.class.getMethod("testBeanParam", argType);
+        Message messageImpl = createMessage();
+        messageImpl.put(Message.REQUEST_URI, "/bar");
+        
+        // The converter converts any Boolean to null
+        ProviderFactory.getInstance(messageImpl)
+            .registerUserProvider(new MyBoolParamConverterProvider());
+        
+        MultivaluedMap<String, String> headers = new MetadataMap<>();
+        headers.putSingle("Content-Type", MediaType.APPLICATION_FORM_URLENCODED);
+        messageImpl.put(Message.PROTOCOL_HEADERS, headers);
+        String body = "value=true";
+        messageImpl.setContent(InputStream.class, new ByteArrayInputStream(body.getBytes()));
+
+        final ClassResourceInfo cri = new ClassResourceInfo(Customer.class);
+        final MethodDispatcher md = new MethodDispatcher();
+        
+        final OperationResourceInfo ori = new OperationResourceInfo(m, cri);
+        md.bind(ori, m);
+        
+        cri.setMethodDispatcher(md);
+        cri.initBeanParamInfo(ServerProviderFactory.getInstance(messageImpl));
+
+        List<Object> params = JAXRSUtils.processParameters(ori,
+                                                           null,
+                                                           messageImpl);
+        assertEquals("Bean should be created", 1, params.size());
+        Customer.CustomerBean cb = (Customer.CustomerBean)params.get(0);
+        assertNotNull(cb);
+
+        assertNull(cb.getBool());
+    }
 
     private static OperationResourceInfo findTargetResourceClass(List<ClassResourceInfo> resources,
                                                                 Message message,
@@ -2108,6 +2144,32 @@ public class JAXRSUtilsTest {
         return endpoint;
     }
 
+    @SuppressWarnings("unchecked")
+    static class MyBoolParamConverterProvider implements ParamConverterProvider {
+        @Override
+        public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
+            if (rawType.isAssignableFrom(Boolean.TYPE) || rawType.isAssignableFrom(Boolean.class)) {
+                return (ParamConverter<T>) new ParamConverter<Boolean>() {
+                    @Override
+                    public Boolean fromString(String value) {
+                        if (rawType.isAssignableFrom(Boolean.TYPE)) {
+                            return true;
+                        }
+                        return null;
+                    }
+        
+                    @Override
+                    public String toString(Boolean value) {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+            
+            return null;
+        }
+    }
+    
+    
     static class MyTypeParamConverterProvider
         implements ParamConverterProvider, ParamConverter<MyType<Integer>> {