Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
2.16.2
-
None
-
Unknown
-
Important
Description
As documented in the camel-spring-boot documentation, camel-spring-boot will delegate type conversion to Spring by default (see org.apache.camel.spring.boot.TypeConversionConfiguration). Whenever the body of a route changes to a List, Spring believes it can convert it and fails. See the supplied test.
The runs correctly if the SpringTypeConverter is removed.
StreamCachingTest.java
package com.example.bugs; import org.apache.camel.CamelContext; import org.apache.camel.EndpointInject; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.spring.boot.SpringTypeConverter; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.Test; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.DefaultConversionService; import java.io.File; import java.io.FileInputStream; import java.util.List; import static java.util.Arrays.asList; public class StreamCachingTest extends CamelTestSupport { public static final String URI_END_OF_ROUTE = "mock:end_of_route"; @EndpointInject(uri = URI_END_OF_ROUTE) private MockEndpoint endOfRoute; @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { context.getTypeConverterRegistry().addFallbackTypeConverter(springTypeConverter(context, new ConversionService[]{new DefaultConversionService()}), true); from("direct:foo") .streamCaching() .bean(MyBean.class) .to(URI_END_OF_ROUTE); } }; } @Test public void stream_caching_with_spring() throws Exception { endOfRoute.expectedMessageCount(1); template.sendBody("direct:foo", new FileInputStream(new File("src/main/resources/banner.txt"))); endOfRoute.assertIsSatisfied(); } public static class MyBean { public List<Integer> someNumbers() { return asList(1, 2, 3); } } /** * Copied from org.apache.camel.spring.boot.TypeConversionConfiguration (they are package protected) **/ @Bean SpringTypeConverter springTypeConverter(CamelContext camelContext, ConversionService[] conversionServices) { SpringTypeConverter springTypeConverter = new SpringTypeConverter(asList(conversionServices)); camelContext.getTypeConverterRegistry().addFallbackTypeConverter(springTypeConverter, true); return springTypeConverter; } @ConditionalOnMissingBean @Bean ConversionService defaultCamelConversionService(ApplicationContext applicationContext) { DefaultConversionService service = new DefaultConversionService(); for (Converter converter : applicationContext.getBeansOfType(Converter.class).values()) { service.addConverter(converter); } return service; } }
Result:
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-CAW811-53239-1457446127171-0-2][Message: 1,2,3] at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1658) at org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:646) at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:471) at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:467) at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:139) at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:144) at no.avinor.agressointegration.StreamCachingTest.stream_caching_with_spring(StreamCachingTest.java:50) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55) at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55) at org.junit.rules.RunRules.evaluate(RunRules.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) Caused by: org.apache.camel.TypeConversionException: Error during type conversion from type: java.lang.String to the required type: org.apache.camel.StreamCache with value 1,2,3 due Failed to convert from type [java.util.Arrays$ArrayList<?>] to type [org.apache.camel.StreamCache] for value '[1, 2, 3]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.Arrays$ArrayList<?>] to type [org.apache.camel.StreamCache] at org.apache.camel.impl.converter.BaseTypeConverterRegistry.createTypeConversionException(BaseTypeConverterRegistry.java:610) at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:137) at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:72) at org.apache.camel.impl.MessageSupport.getBody(MessageSupport.java:47) at org.apache.camel.impl.DefaultStreamCachingStrategy.cache(DefaultStreamCachingStrategy.java:189) at org.apache.camel.processor.CamelInternalProcessor$StreamCachingAdvice.before(CamelInternalProcessor.java:765) at org.apache.camel.processor.CamelInternalProcessor$StreamCachingAdvice.before(CamelInternalProcessor.java:744) at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:138) at org.apache.camel.processor.Pipeline.process(Pipeline.java:121) at org.apache.camel.processor.Pipeline.process(Pipeline.java:83) at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190) at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:62) at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190) at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:109) at org.apache.camel.processor.UnitOfWorkProducer.process(UnitOfWorkProducer.java:68) at org.apache.camel.impl.ProducerCache$2.doInProducer(ProducerCache.java:412) at org.apache.camel.impl.ProducerCache$2.doInProducer(ProducerCache.java:380) at org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:270) at org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:380) at org.apache.camel.impl.ProducerCache.send(ProducerCache.java:221) at org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:124) at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:137) ... 34 more Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.Arrays$ArrayList<?>] to type [org.apache.camel.StreamCache] for value '[1, 2, 3]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.Arrays$ArrayList<?>] to type [org.apache.camel.StreamCache] at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:176) at org.apache.camel.spring.boot.SpringTypeConverter.convertTo(SpringTypeConverter.java:40) at org.apache.camel.impl.converter.BaseTypeConverterRegistry.doConvertTo(BaseTypeConverterRegistry.java:333) at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:120) ... 54 more Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.Arrays$ArrayList<?>] to type [org.apache.camel.StreamCache] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:313) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) at org.springframework.core.convert.support.CollectionToObjectConverter.convert(CollectionToObjectConverter.java:64) at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35) ... 59 more