1
votes

I tried to find a way to configure a Camel endpoint using a spring bean that is referenced from the endpoint declaration in route in a camel context, but it does not work.

For exemple, sometime defining an endpoint URI with many parameters is very horrible (!!), it would be lot more easier to configure the endpoint with a bean and its properties. (Or even better, when configuring a endpoint in XML, maybe the or elements should have sub-elements like a regular beans where we could configure the parameters of the endpoint).

The first approach below work well and is very standard and pretty simple. The second approach, is the one I would like to use instead, but it does not work. I tried with many variations, but without success! The third alternative below would just be an interesting proposal for Camel developers in fact, but it also illustrate my point.

In my example below, I only configured 3 parameters for the file endpoint, but imagine the URI with 10 parameters!! My question is how can I make my second approach working properly, I'm sure there is a simple solution!? I also tried using a factory-bean and a factory method, but it diid not work neither.

1) Standard way to configure a camel endpoint in XML (spring beans):

...
<camel:camelContext id="camelContext"  >

    <camel:route id="deviceDataLogsPoller"  >
        <camel:from uri="file://long/path/to/input?preMove=../inprogress&amp;move=../done&amp;moveFailed=../error" />

        <camel:log message="Input device data file read from file in input folder {{im.filePoller.folder.input}}." loggingLevel="INFO" />

    </camel:route>
</camel:camelContext>

2) Alternative that I expected to be valide but that does not work (for me!):

<bean id="filePoller" class="org.apache.camel.component.file.FileEndpoint" >

    <property name="camelContext" ref="camelContext" />
    <property name="localWorkDirectory" value="/long/path/to/input" />
    <property name="preMove"   value="../inprogress" />
    <property name="move"       value="../done" />
    <property name="moveFailed" value="../error" />
    ...
</bean>

...
<camel:camelContext id="camelContext"  >

    <camel:route id="deviceDataLogsPoller"  >
        <camel:from ref="filePoller" />

        <camel:log message="Input device data file read from file in input folder {{im.filePoller.folder.input}}." loggingLevel="INFO" />

    </camel:route>
</camel:camelContext>

3) Alternative that would be interesting in the future (mixed between two alternatives above):

...

    <camel:route id="deviceDataLogsPoller"  >
        <camel:from uri="file://long/path/to/input" >
             <property name="preMove"   value="../inprogress" />
             <property name="move"       value="../done" />
             <property name="moveFailed" value="../error" />
             ...
        </camel:from>

        <camel:log message="Input device data file read from file in input folder {{im.filePoller.folder.input}}." loggingLevel="INFO" />

    </camel:route>
</camel:camelContext>
2

2 Answers

1
votes

What did not work for you exactly?

Following setup did the job as expected:

<bean id="filePoller" class="org.apache.camel.component.file.FileEndpoint">
    <property name="file" value="src/data/bean-ref" />
    <property name="move" ref="moveExpression"/>
</bean>

<bean id="moveExpression" class="org.apache.camel.model.language.SimpleExpression">
    <constructor-arg value="${file:parent}/.done/${file:onlyname}" />
</bean>

<camelContext xmlns="http://camel.apache.org/schema/spring" id="camelContext">
    <route>
        <from ref="filePoller" />
        <log message="${body}" />
    </route>
</camelContext> 

Note:

  • The property file is mandatory
  • The properties move, moveFailed, and preMove are not of type java.lang.String but of type org.apache.camel.Expression and have to be initialized accordingly.
  • The property moveExpression needs a full file expression. If only .done is used instead of ${file:parent}/.done/${file:onlyname} then the file is renamed to .done and not moved to a directory named .done.
0
votes

As stated in my last comment, I was able to make the bean configuration for an endpoint work (see comments above), but this approach is finally lot more complex and heavy than simply using the URIs after all!!

It would have been more interesting to have a way to configure the endpoints like I proposed in my 3rd alternative above. Maybe if I have time, I will try to create my own and tags that will wrap the existing ones by constructing the full URI from params elements...! I can also propose this to Camel developers.

See an example below of how it could be interesting to configure endpoints in the future (or with the XML wrapper I would like to code):

<camel:route id="deviceDataLogsPoller">

    <camel:from uri="file://long/path/to/input" >

         <param name="preMove"   value="../inprogress" />
         <param name="move"       value="../done" />
         <param name="moveFailed" value="../error" />
         ...
    </camel:from>

    ...

</camel:route>

Unfortunately, the endpoint configuration as shown above is not possible for the moment, but it would be a nice to have I think! For the moment, the only way is either to specify all the parameters as params in a very long URI, or to configure the endpoint as a regular bean, with with all the complexity it implies (see comments above for details).