I created a Java class for EIP Event Messages. I expected to receive a Message at Observer.accept(Object o)
when using Camel's Bean component but I get an Event
instead. While this is convenient since I don't have to extract the Event
from the Message
's body myself I don't have access to the message's possible headers and attachments with this.
EventMessageTest.java
package name.igb.eip.integration.styles.test;import java.time.Instant;import java.util.List;import java.util.Vector;import java.util.function.Consumer;import java.util.function.Supplier;import org.apache.camel.CamelContext;import org.apache.camel.builder.RouteBuilder;import org.apache.camel.impl.DefaultCamelContext;import org.apache.camel.impl.engine.DefaultCamelContextNameStrategy;import org.apache.camel.model.RouteDefinition;import org.slf4j.Logger;import org.slf4j.LoggerFactory;class EventMessageTest { static final Logger log = LoggerFactory.getLogger( EventMessageTest.class ); public static void main( final String... args ) throws Exception { try ( CamelContext cc = new DefaultCamelContext(); ) { cc.setNameStrategy( new DefaultCamelContextNameStrategy( "Messaging Sample" ) ); cc.getRegistry().bind( "Subject", new Subject( "Subject" ) ); cc.getRegistry().bind( "Observer", new Observer( "Observer" ) ); final List<Observer> observers = new Vector<>(); observers.add( new Observer( "Observer 1" ) ); observers.add( new Observer( "Observer 2" ) ); observers.add( new Observer( "Observer 3" ) ); cc.addRoutes( new RouteBuilder() { @Override public void configure() { final RouteDefinition route = from( "timer:Event?repeatCount=1" ) .log( "creating endpoint " + Subject.class.getSimpleName() +"..." ) .bean( Subject.class ) // Subject.get() returns an Event .log( "creating..." ) .process().message( m -> { log.info( "...{}<{}>", m, m.getBody( Event.class ).getClass().getSimpleName() ); } ) .routeId( "Event route" ); for ( final Observer observer : observers ) { log.info( "creating endpoint {}...", observer.id ); route .to( "bean:Observer" ) // this sends Event to Observer // this alternative sends Message to Observer N .process().message( m -> { observer.accept( m ); } ); } } } ); // addRoutes( RouteBuilder() ) cc.start(); Thread.sleep( 2000 ); cc.stop(); cc.close(); } catch ( final Exception e ) { e.printStackTrace(); } } // main()} // EventMessageTestclass Subject implements Supplier<Event> { String id; Subject( final String id ) { this.id = id; } @Override @Handler public Event get() { return new Event(); }} // Subjectclass Event { String id = Instant.now().toString();} // Eventclass Observer implements Consumer<Object> { String id; Observer( final String id ) throws Exception { this.id = id; } Observer setId( final String id ) { this.id = id; return this; } @Override @Handler public void accept( final Object o ) { // Why is o an Event and not a Message here if Observer is created // by RouteDefinition.to( "bean:Observer" )? EventMessageTest.log.info( "\n{} receiving {}...", id, o.getClass().getSimpleName() ); }} // Observer
Output
19:24:13.404 [main] INFO n.i.e.i.s.test.EventMessageTest$1 - creating endpoint Observer 1...19:24:13.408 [main] INFO n.i.e.i.s.test.EventMessageTest$1 - creating endpoint Observer 2...19:24:13.408 [main] INFO n.i.e.i.s.test.EventMessageTest$1 - creating endpoint Observer 3...19:24:14.553 [Camel (camel-1) thread #1 - timer://Event] INFO Event route - creating endpoint Subject...19:24:14.559 [Camel (camel-1) thread #1 - timer://Event] INFO Event route - creating...19:24:14.559 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.s.test.EventMessageTest$1 - ...Message<Event>19:24:14.560 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.styles.test.EventMessageTest - Observer receiving Event...19:24:14.560 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.styles.test.EventMessageTest - Observer 1 receiving DefaultMessage...19:24:14.560 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.styles.test.EventMessageTest - Observer receiving Event...19:24:14.560 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.styles.test.EventMessageTest - Observer 2 receiving DefaultMessage...19:24:14.560 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.styles.test.EventMessageTest - Observer receiving Event...19:24:14.560 [Camel (camel-1) thread #1 - timer://Event] INFO n.i.e.i.styles.test.EventMessageTest - Observer 3 receiving DefaultMessage...
Is this a bug or a feature (and why if it's the latter)?
If I change the following two lines to:
...class Observer implements Consumer<Message> {... public void accept( final Message o ) {...
I get:
java.lang.ClassCastException: class name.igb.eip.integration.styles.test.Event cannot be cast to class org.apache.camel.Message (name.igb.eip.integration.styles.test.Event and org.apache.camel.Message are in unnamed module of loader 'app') at name.igb.eip.integration.styles.test.Observer.accept(EventMessageTest.java:1) ...
so apparently Camel doesn't look at the Consumer
's type parameter.
POM (for MRE testing)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>name.igb</groupId><artifactId>eip</artifactId><version>0.0.1-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven.compiler.release>23</maven.compiler.release><javaee.version>8.0.1</javaee.version><jakarta.enterprise.cdi-api.version>4.1.0</jakarta.enterprise.cdi-api.version><weld-se.version>6.0.0.Final</weld-se.version><camel.version>4.8.2</camel.version><slf4j.version>2.0.16</slf4j.version><logback.version>1.5.15</logback.version><mockito.version>5.14.2</mockito.version><hierarchy-maven-plugin.version>1.4</hierarchy-maven-plugin.version></properties><dependencies><dependency><groupId>javax</groupId><artifactId>javaee-api</artifactId><version>${javaee.version}</version></dependency><dependency><groupId>jakarta.enterprise</groupId><artifactId>jakarta.enterprise.cdi-api</artifactId><version>${jakarta.enterprise.cdi-api.version}</version><scope>provided</scope></dependency><dependency><groupId>org.jboss.weld.se</groupId><artifactId>weld-se-shaded</artifactId><version>${weld-se.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-core</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-test-junit5</artifactId><version>${camel.version}</version><scope>test</scope></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-componentdsl</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-direct</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-groovy</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-mail</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-jms</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-sjms</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.apache.camel</groupId><artifactId>camel-sjms2</artifactId><version>${camel.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>${logback.version}</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>${logback.version}</version></dependency><dependency><groupId>org.mockito</groupId><!-- artifactId>mockito-core</artifactId --><artifactId>mockito-core</artifactId><version>${mockito.version}</version><scope>test</scope></dependency></dependencies><build><defaultGoal>install</defaultGoal><plugins><!-- allows the route to be run via 'mvn camel:run' --><plugin><groupId>org.apache.camel</groupId><artifactId>camel-maven-plugin</artifactId><version>${camel.version}</version></plugin><plugin><groupId>com.github.exampledriven</groupId><artifactId>hierarchy-maven-plugin</artifactId><version>${hierarchy-maven-plugin.version}</version></plugin></plugins></build></project>