Repository: camel
Updated Branches:
  refs/heads/camel-2.18.x 6cb200c09 -> 495cddd83


CAMEL-10548: Converter from List to String is not found when 
@EnableAutoConfiguration is used


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/65a67bc4
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/65a67bc4
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/65a67bc4

Branch: refs/heads/camel-2.18.x
Commit: 65a67bc4a4a975017200e1ce46a1d27d4d552a76
Parents: 6cb200c
Author: lburgazzoli <lburgazz...@gmail.com>
Authored: Thu Dec 1 15:06:44 2016 +0100
Committer: lburgazzoli <lburgazz...@gmail.com>
Committed: Thu Dec 1 16:32:03 2016 +0100

----------------------------------------------------------------------
 .../camel/spring/boot/SpringTypeConverter.java  |  31 ++++-
 .../spring/boot/SpringTypeConverterTest.java    | 129 +++++++++++++++++++
 2 files changed, 158 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/65a67bc4/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
index 5f4021a..204f13b 100644
--- 
a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
+++ 
b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
@@ -19,20 +19,26 @@ package org.apache.camel.spring.boot;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.TypeConversionException;
 import org.apache.camel.support.TypeConverterSupport;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.convert.ConversionFailedException;
 import org.springframework.core.convert.ConversionService;
+import org.springframework.core.convert.ConverterNotFoundException;
+import org.springframework.core.convert.TypeDescriptor;
 
 public class SpringTypeConverter extends TypeConverterSupport {
 
     private final List<ConversionService> conversionServices;
+    private final ConcurrentHashMap<Class<?>, TypeDescriptor> types;
 
     @Autowired
     public SpringTypeConverter(List<ConversionService> conversionServices) {
         this.conversionServices = conversionServices;
+        this.types = new ConcurrentHashMap<>();
     }
 
     @Override
@@ -47,12 +53,33 @@ public class SpringTypeConverter extends 
TypeConverterSupport {
             return null;
         }
 
+        TypeDescriptor sourceType = types.computeIfAbsent(value.getClass(), 
TypeDescriptor::valueOf);
+        TypeDescriptor targetType = types.computeIfAbsent(type, 
TypeDescriptor::valueOf);
+
         for (ConversionService conversionService : conversionServices) {
-            if (conversionService.canConvert(value.getClass(), type)) {
-                return conversionService.convert(value, type);
+            if (conversionService.canConvert(sourceType, targetType)) {
+                try {
+                    return (T)conversionService.convert(value, sourceType, 
targetType);
+                } catch (ConversionFailedException e) {
+                    // if value is a collection or an array the check 
ConversionService::canConvert
+                    // may return true but then the conversion of specific 
objects may fail
+                    //
+                    // https://issues.apache.org/jira/browse/CAMEL-10548
+                    // https://jira.spring.io/browse/SPR-14971
+                    //
+                    if (e.getCause() instanceof ConverterNotFoundException && 
isArrayOrCollection(value)) {
+                        return null;
+                    } else {
+                        throw new TypeConversionException(value, type, e);
+                    }
+                }
             }
         }
+
         return null;
     }
 
+    private boolean isArrayOrCollection(Object value) {
+        return value instanceof Collection || value.getClass().isArray();
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/65a67bc4/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
 
b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
new file mode 100644
index 0000000..3ccc367
--- /dev/null
+++ 
b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
@@ -0,0 +1,129 @@
+/**
+ * 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.camel.spring.boot;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.ConversionFailedException;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.core.convert.ConverterNotFoundException;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.core.convert.support.DefaultConversionService;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = 
SpringTypeConverterTest.SpringTypeConversionConfiguration.class)
+public class SpringTypeConverterTest {
+    @Autowired
+    @Qualifier("camelSpringConversionService")
+    ConversionService conversionService;
+
+    @Autowired
+    @Qualifier("camelSpringTypeConverter")
+    SpringTypeConverter converter;
+
+    @Test
+    public void testConversionService() {
+        Collection<?> source = Arrays.asList(new Person("Name", 30));
+
+        Assert.assertFalse(conversionService.canConvert(Person.class, 
String.class));
+        Assert.assertTrue(conversionService.canConvert(source.getClass(), 
String.class));
+
+        try {
+            conversionService.convert(source, String.class);
+        } catch (ConversionFailedException e) {
+            // Expected as Person can't be converted to a string according to
+            // Spring's FallbackObjectToStringConverter, see javadoc for:
+            //
+            //   
org.springframework.core.convert.support.FallbackObjectToStringConverter
+            //
+            Assert.assertTrue(e.getCause() instanceof 
ConverterNotFoundException);
+        }
+
+
+        Assert.assertNull(converter.convertTo(String.class, source));
+    }
+
+    public static class Person {
+        private String name;
+        private int age;
+
+        public Person(String name, int age) {
+            this.name = name;
+            this.age = age;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public int getAge() {
+            return age;
+        }
+
+        public void setAge(int age) {
+            this.age = age;
+        }
+
+        @Override
+        public String toString() {
+            return "Person{" +
+                "name='" + name + '\'' +
+                ", age=" + age +
+                '}';
+        }
+    }
+
+    @Configuration
+    @EnableAutoConfiguration(
+        exclude = {
+            CamelAutoConfiguration.class, TypeConversionConfiguration.class, 
WebMvcAutoConfiguration.class
+        }
+    )
+    public static class SpringTypeConversionConfiguration {
+        @Bean
+        ConversionService camelSpringConversionService(ApplicationContext 
applicationContext) {
+            DefaultConversionService service = new DefaultConversionService();
+            for (Converter converter : 
applicationContext.getBeansOfType(Converter.class).values()) {
+                service.addConverter(converter);
+            }
+
+            return service;
+        }
+        @Bean
+        SpringTypeConverter camelSpringTypeConverter(List<ConversionService> 
conversionServices) {
+            return new SpringTypeConverter(conversionServices);
+        }
+    }
+}
\ No newline at end of file

Reply via email to