2

So, now I am attempting to import routes from an XML file into the Java DSL.

I've been attempting to start with this link but since it's such a simple example, it doesn't really help me and doesn't point me to a more complicated example.

My problem is that my Camel routes use beans. Beans for the PropertiesComponent and FileIdempotentRepository and others are defined within the XML file for use by the routes in the XML file.

My original Spring configuration looked something like the following:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
 http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

<bean id="bean1" class="class1" />
<bean id="bean2" class="class2" />
<bean id="bean3" class="FileIdempotentRepository"> [...] </bean>
<bean id="properties" class="PropertiesComponent"> [...] </bean>

  <camelContext xmlns="http://camel.apache.org/schema/spring">
      <route>
          <from uri="{{someplace}}&amp;filter=#bean1" />
          <setHeader headerName="FileRepoKey">
              <simple>${file:name}-${file:modified}</simple>
          </setHeader>
          <idempotentConsumer messageIdRepositoryRef="bean3">
              <header>FileRepoKey</header>
              <process ref="bean2" />
              <to uri="{{otherplace}}"/>
          </idempotentConsumer>
      </route>
  </camelContext>
</beans>

So how do I convert this mess into something usable by the Java DSL to import routes from?

I understand from looking at that link that I need to do something like convert <camelContext> to <routes>. But leaving in the beans gives me an error along the lines of:

Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.springframework.org/schema/beans", local:"beans"). Expected elements are [...]

What do I need to change? Or can I not have beans in the XML file in order for it to be imported by the Java used in the link?

Jsmith
  • 350
  • 1
  • 4
  • 19
  • The issue is that your original files are Spring XML contexts.. not just simple routes in XML per the link you reference. What is the requirement and/or problem you are trying to solve? In other words.. why are you wanting/needing to load routes from XML files? – Matt Pavlovich Dec 06 '16 at 16:59
  • Basically the boss wants the ability to quickly add a route without having to write the proper Java implementation. Leaving the new route to be implemented in the next build rather than immediately. – Jsmith Dec 06 '16 at 17:22
  • Gotcha.. so I doubt that route import feat supports reading the beans b/c that would entire essentially re-implementing Spring. If you read the note on the page.. you'll see there are limits to the complexity of the route-- no sharing of exception handlers, interceptors etc. Beans would fall into that – Matt Pavlovich Dec 06 '16 at 19:13
  • For your use case.. you might look to use the auto-deploy feature in Karaf-based containers (Karaf, ServiceMix, Fuse, Talend etc). You can drop Camel .xml files into the deploy folder and it will make a best effort to auto-bundle them. If your beans are already installed as bundles it might work for you. – Matt Pavlovich Dec 06 '16 at 19:14

2 Answers2

2

I guess I should've asked this a different way and maybe someone would have thought of this way.

It may give you all nightmares, I'm not sure. Be warned.

So since the concept is "have things potentially run from an XML file alongside Java" the following end result came about:

    public static void main(String[] args) throws Exception {

    Main main = new Main();

    //the XML file has a CamelContext in it. 
    main.setApplicationContextUri("myRoutes.xml");
    main.start();//instantiates the CamelContext so we can use it in Java
    List<CamelContext> camelContexts = main.getCamelContexts(); //should only have 1 item in the list
    CamelContext context = camelContexts.get(0);

    //in order to add a component to the registry the following is needed for set up
    //  afterwards, should just be able to add anything to the registry with registry.put("name", object)
    final SimpleRegistry registry = new SimpleRegistry();
    final CompositeRegistry compositeRegistry = new CompositeRegistry();
    compositeRegistry.addRegistry(context.getRegistry());
    compositeRegistry.addRegistry(registry);
    ((DefaultCamelContext) context).setRegistry(compositeRegistry);

    final FileIdempotentRepository myFileStore = new FileIdempotentRepository();
    File myFile = new File("idempotentRepoFiles/myFileStore.txt");

    final TimeStampFileFilter<?> myFileFilter = new TimeStampFileFilter<Object>(0L);
    registry.put("myFileFilter", myFileFilter);

    //512MB
    myFileStore.setMaxFileStoreSize(536870912L);
    myFileStore.setFileStore(myFile);
    myFileStore.setCacheSize(100000);

    //add a route to the CamelContext that was initially created in the XML file
    context.addRoutes(new RouteBuilder() {

        @Override
        public void configure() throws Exception {
            onException(myException.class)
                .handled(true);
            onException(GenericFileOperationFailedException.class)
                .onException(SocketException.class)
                .maximumRedeliveries(2)
                .redeliveryDelay(5000L)
                ;
            Processor myProcessor = new myProcessor();
            from("{{myStart}}&filter=#myFileFilter")
            .setHeader("myFileRepoKey", simple("${file:name}-${file:modified}"))
            .idempotentConsumer(header("myFileRepoKey"), myFileStore)
            .process(myProcessor)
            .to("{{myEnd}}")
            ;

        }

    });

    context.start();
    main.run();
}

Basically: create a CamelContext in the Spring XML file, initialize it, grab it, modify it to include routes built in Java.

Jsmith
  • 350
  • 1
  • 4
  • 19
1

Route definition in Camel can be XML based (Spring DSL or Blueprint DSL) or Java based (Java DSL). A route definition can be expressed equally in both languages.

In a Spring application you can define your beans in a file and your routes in other files which you import. Routes defined in external files can refer to beans defined in your main file.

spring-main.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
 http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <bean id="bean1" class="class1" />
    <bean id="bean2" class="class2" />
    <bean id="bean3" class="FileIdempotentRepository"> [...] </bean>
    <bean id="properties" class="PropertiesComponent"> [...] </bean>

    <import resource="camel-routes.xml"/>
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <routeContextRef ref="ExternalRoutes"/>
    </camelContext>
</beans>

camel-routes.xml

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
   http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <routeContext id="ExternalRoutes" xmlns="http://camel.apache.org/schema/spring">

        <route id="ARoute">
            <from uri="direct:startHere" />
            <to uri="bean:bean3" />
        </route>
    </routeContext>
</beans>

You can import more than one external file, of course. Just name each RouteContext differently.

If you modify one of the RouteContexts you must then restart your application. If you need a more dynamic application, try using an OSGi container to run your Camel routes, so you can easily modularize your application and add/remove features at runtime.

Community
  • 1
  • 1
Alessandro Da Rugna
  • 4,571
  • 20
  • 40
  • 64