I've tried searching for this information but haven't been able to find it. I am relatively new to Camel (and Java) so forgive me if I have overlooked something simple. Please keep in mind this is just sample code so it may be a bit brittle.
The real issue can be found in the Java output (all the way at the bottom) at the following line:
org.quartz.JobExecutionException: java.lang.ClassNotFoundException: #{${header.ProtobufType}} [See nested exception: java.lang.ClassNotFoundException: #{${header.ProtobufType}}]
I want to (at runtime) decide what instanceClass to use when marshaling or unmarshaling a message. I think using Spring Expression Language is the way to go but haven't been able to figure out the proper Google queries for what I am looking for. My Spring application context looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="toBean" class="To.ToBean" />
<bean id="fromBean" class="From.FromBean" />
<bean id="addTypeProcessor" class="Processor.AddTypeProcessor" />
<camel:errorHandler id="camelErrorHandler" type="NoErrorHandler" />
<camelContext id="camelContext" errorHandlerRef="camelErrorHandler" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="quartz://myTimer?trigger.repeatCount=-1&trigger.repeatInterval=5000" />
<to uri="bean:fromBean" />
<process ref="addTypeProcessor" />
<marshal>
<protobuf instanceClass="#{${header.ProtobufType}}" />
</marshal>
<unmarshal>
<protobuf instanceClass="#{${header.ProtobufType}}" />
</unmarshal>
<to uri="bean:toBean" />
<process ref="addTypeProcessor" />
</route>
</camelContext>
</beans>
My AddTypeProcessor looks like this:
package Processor;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class AddTypeProcessor implements Processor {
@Override
public void process(Exchange exchange) throws Exception {
String headerName = "ProtobufType";
String headerValue = (String) exchange.getIn().getHeader(headerName);
System.out.println(headerName + " was " + headerValue);
exchange.getIn().setHeader(headerName, exchange.getIn().getBody().getClass().getCanonicalName());
headerValue = (String) exchange.getIn().getHeader(headerName);
System.out.println(headerName + " is " + headerValue);
}
}
My output is the following:
0 [main] INFO org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@63c5ab93: startup date [Fri Jun 28 16:33:17 EDT 2013]; root of context hierarchy
46 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
1081 [main] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7cb01f72: defining beans [toBean,fromBean,addTypeProcessor,camelErrorHandler,template,consumerTemplate,camelContext:beanPostProcessor,camelContext]; root of factory hierarchy
1285 [main] INFO org.apache.camel.spring.SpringCamelContext - Apache Camel 2.10.1 (CamelContext: camelContext) is starting
1356 [main] INFO org.apache.camel.management.ManagementStrategyFactory - JMX enabled.
1521 [main] INFO org.apache.camel.impl.converter.DefaultTypeConverter - Loaded 175 type converters
1633 [main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
1645 [main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
1645 [main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.1.8.5 created.
1646 [main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
1647 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v1.8.5) 'DefaultQuartzScheduler-camelContext' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
1647 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler-camelContext' initialized from an externally provided properties instance.
1647 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 1.8.5
1812 [main] INFO org.apache.camel.spring.SpringCamelContext - Route: route1 started and consuming from: Endpoint[quartz://myTimer?trigger.repeatCount=-1&trigger.repeatInterval=5000]
1812 [main] INFO org.apache.camel.management.DefaultManagementLifecycleStrategy - StatisticsLevel at All so enabling load performance statistics
1817 [main] INFO org.apache.camel.component.quartz.QuartzComponent - Starting Quartz scheduler: DefaultQuartzScheduler-camelContext
1817 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler-camelContext_$_NON_CLUSTERED started.
1819 [main] INFO org.apache.camel.spring.SpringCamelContext - Total 1 routes, of which 1 is started.
1822 [main] INFO org.apache.camel.spring.SpringCamelContext - Apache Camel 2.10.1 (CamelContext: camelContext) started in 0.535 seconds
ProtobufType was null
ProtobufType is WireFormatProtos.WireFormat.A
1848 [DefaultQuartzScheduler-camelContext_Worker-1] WARN org.apache.camel.util.ObjectHelper - Cannot find class: $header.ProtobufType
1849 [DefaultQuartzScheduler-camelContext_Worker-1] ERROR org.apache.camel.component.quartz.QuartzEndpoint - Error processing exchange. Exchange[Message: ]. Caused by: [org.quartz.JobExecutionException - java.lang.ClassNotFoundException: #{${header.ProtobufType}}]
1850 [DefaultQuartzScheduler-camelContext_Worker-1] INFO org.quartz.core.JobRunShell - Job DEFAULT.quartz-endpoint1 threw a JobExecutionException:
org.quartz.JobExecutionException: java.lang.ClassNotFoundException: #{${header.ProtobufType}} [See nested exception: java.lang.ClassNotFoundException: #{${header.ProtobufType}}]
at org.apache.camel.component.quartz.QuartzEndpoint.onJobExecute(QuartzEndpoint.java:117)
at org.apache.camel.component.quartz.CamelJob.execute(CamelJob.java:54)
at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: java.lang.ClassNotFoundException: #{${header.ProtobufType}}
at org.apache.camel.impl.DefaultClassResolver.resolveMandatoryClass(DefaultClassResolver.java:52)
at org.apache.camel.dataformat.protobuf.ProtobufDataFormat.loadDefaultInstance(ProtobufDataFormat.java:79)
at org.apache.camel.dataformat.protobuf.ProtobufDataFormat.getInstance(ProtobufDataFormat.java:67)
at org.apache.camel.dataformat.protobuf.ProtobufDataFormat.unmarshal(ProtobufDataFormat.java:109)
at org.apache.camel.processor.UnmarshalProcessor.process(UnmarshalProcessor.java:57)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:73)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90)
at org.apache.camel.processor.interceptor.TraceInterceptor.process(TraceInterceptor.java:91)
at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:45)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90)
at org.apache.camel.processor.interceptor.DefaultChannel.process(DefaultChannel.java:303)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:117)
at org.apache.camel.processor.Pipeline.process(Pipeline.java:80)
at org.apache.camel.processor.RouteContextProcessor.processNext(RouteContextProcessor.java:45)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90)
at org.apache.camel.processor.UnitOfWorkProcessor.processAsync(UnitOfWorkProcessor.java:150)
at org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:117)
at org.apache.camel.processor.RouteInflightRepositoryProcessor.processNext(RouteInflightRepositoryProcessor.java:48)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
at org.apache.camel.processor.DelegateAsyncProcessor.processNext(DelegateAsyncProcessor.java:99)
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:90)
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:73)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
at org.apache.camel.processor.loadbalancer.QueueLoadBalancer.process(QueueLoadBalancer.java:44)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:99)
at org.apache.camel.processor.loadbalancer.QueueLoadBalancer.process(QueueLoadBalancer.java:71)
at org.apache.camel.component.quartz.QuartzEndpoint.onJobExecute(QuartzEndpoint.java:113)
... 3 more
This is not possible.
Instead you can use a processor / bean, and then create the marshaller and unmarshaller in the java code, and invoke the marshal/unmarshal method. As this is java code, you can then have the dynamic behavior of defining the instance class from a camel message header.