Search code examples
javaspringapache-camelactivemq-classicspring-dsl

Separate route instances within single Camel context


I use Apache Camel module deployed inside ActiveMQ service.

Given I use Spring DSL and I have route definition ( implemented as routeContext) in the FilteringRouteContext.xml file (simplified):

<routeContext id="filteringRouteContext" xmlns="http://camel.apache.org/schema/spring">
    <route id="myFilteringRoute">
        <from uri="direct:filteringRoute"/>
        <idempotentConsumer messageIdRepositoryRef="idempotentRepository" skipDuplicate="false">
            <simple>${header.JMSType}</simple>
            <filter>
                <property>CamelDuplicateMessage</property>
                <stop/>
            </filter>
        </idempotentConsumer>
    </route>
</routeContext>

Next, I have configured Camel Context in other XML file (simplified):

<import resource="classpath:FilteringRouteContext.xml"/>

    <camelContext xmlns="http://camel.apache.org/schema/spring">

        <routeContextRef ref="filteringRouteContext"/>

        <route id="myRoute1">
            <from uri="activemq:topic:source1" />
            <to uri="direct:filteringRoute" />
            <to uri="activemq:topic:target1" />
        </route>

        <route id="myRoute2">
            <from uri="activemq:topic:source2" />
            <to uri="direct:filteringRoute" />
            <to uri="activemq:topic:target2" />
        </route>

        <route id="myRoute3">
            <from uri="activemq:topic:source3" />
            <to uri="direct:filteringRoute" />
            <to uri="activemq:topic:target3" />
        </route>

    </camelContext>

    <bean id="idempotentRepository"
          class="org.apache.camel.processor.idempotent.MemoryIdempotentRepository">
        <property name="cacheSize" value="10"/>
    </bean>

I would like to have shared route (with id=myFilteringRoute) from filteringRouteContext declared as, using IoC terminology, instance per dependency, so each route from single Camel Context (with id=myRoute1, myRoute2, myRoute3) should use it's own instance of that shared route (with id=myFilteringRoute), with separate internal state, bean instances, etc.

In other words, each route from Camel Context (with id=myRoute1, myRoute2, myRoute3) should not use the same instance of shared route (with id=myFilteringRoute), but should has its own completely separate instances (with completely separated internal states and bean instances )

Please consider that my shared route (with id=myFilteringRoute) may use more beans, which may have various scopes (singleton, prototype, request etc.).

My questions are: Can I achieve this goal using single Camel Context, or do I need to place my routes (with id=myRoute1, myRoute2, myRoute3) in separate Camel Contexts? What is the best solution of my problem?

Is there important performance impact If I use more than one Camel Contexts, and each context uses beans to communicate with ActiveMQ (org.apache.activemq.camel.component.ActiveMQComponent), or other beans that consume internal or system resources?

Or maybe it's better to resolve my problem by using Java DSL instead of Spring DSL?

Thank You.


Solution

  • Current Camel Spring DSL definitions are created by JAXB when it unmarshals the xml. This definitions help camel runtime to to build up processors and assemble them to route the message. In this way routeContextRef has nothing do with the scopes you mentioned.

    But for the beans which you created by Spring with bean element, you can define the scopes if you like, and camel just grab it from Spring Application Context if there is bean reference in the Camel Spring DSL.

    To answer you question, routeContextRef just give a way to share the route definition instance across the camel context, if you don't want share their instance you need to create the camel context in different spring application context which could hold the different instance of routeContext.