【问题标题】:Alternative to long URI to configure a Camel Endpoint with Spring beans?使用 Spring bean 配置 Camel Endpoint 的长 URI 替代方案?
【发布时间】:2023-10-30 06:01:01
【问题描述】:

我试图找到一种方法来使用 spring bean 来配置 Camel 端点,该 spring bean 是从骆驼上下文中路由中的端点声明中引用的,但它不起作用。

例如,有时使用许多参数定义端点 URI 是非常可怕的(!!),使用 bean 及其属性配置端点会容易得多。 (或者更好的是,当在 XML 中配置端点时,或元素应该有子元素,比如我们可以配置端点参数的常规 bean。

下面的第一种方法效果很好,非常标准且非常简单。第二种方法是我想改用的方法,但它不起作用。我尝试了很多变化,但没有成功!下面的第三种选择实际上对 Camel 开发人员来说只是一个有趣的建议,但它也说明了我的观点。

在下面的示例中,我只为文件端点配置了 3 个参数,但想象一下 URI 有 10 个参数!我的问题是如何使我的第二种方法正常工作,我确定有一个简单的解决方案!?我也尝试过使用工厂 bean 和工厂方法,但也没有用。

1) 在 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) 我希望有效但不起作用的替代方案(对我来说!):

<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) 未来有趣的替代方案(混合在上述两个替代方案之间):

...

    <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>

【问题讨论】:

    标签: spring uri apache-camel javabeans endpoint


    【解决方案1】:

    究竟是什么不适合你?

    以下设置按预期完成了工作:

    <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> 
    

    注意:

    • file 属性为必填项
    • 属性movemoveFailedpreMove 不是java.lang.String 类型,而是org.apache.camel.Expression 类型,必须进行相应的初始化。
    • moveExpression 属性需要完整的文件表达式。如果只使用.done 而不是${file:parent}/.done/${file:onlyname},则文件将重命名为.done,而不是移动到名为.done 的目录中。

    【讨论】:

    • 是的,这是可行的,但是当您添加一些属性来设置参数时,它们并不总是正常工作,或者就像它们被指定为 URI 参数一样。例如,如果我使用“move”属性和 SimpleExpression 类型的 bean 作为值(而不是字符串)指定“move”参数,那么一切都在启动,但是输入文件夹中的文件无法移动到'move' 文件夹,因为它需要一个文件而不是文件夹(显然,根据异常消息)。
    • @The4Summers 你是对的,它的工作方式不同。我添加了一个moveExpression 示例来展示如何正确处理此问题。
    • 是的,我也可以让它工作,但是这种方法最终比简单地使用 URI 更复杂和繁重!像我在上面的第三个替代方案中提出的那样配置端点会更有趣。也许如果我有时间,我会尝试创建自己的“from”和“to”标签,通过从 params 元素构建完整的 URI 来包装现有标签......!我也可以向 Camel 开发人员提出这个建议。谢谢。
    • @The4Summers 好主意。但是,您仍然可以将问题标记为已回答...
    【解决方案2】:

    正如我在上一条评论中所说,我能够使端点的 bean 配置工作(参见上面的 cmets),但这种方法最终比简单地使用 URI 更复杂和繁重!

    如果有一种方法来配置端点,就像我在上面的第三个替代方案中提出的那样,那会更有趣。也许如果我有时间,我会尝试创建自己的标签,通过从 params 元素构建完整的 URI 来包装现有的标签......!我也可以向 Camel 开发人员提出这个建议。

    请参阅下面的示例,了解将来配置端点(或使用我想编写的 XML 包装器)如何有趣:

    <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>
    

    不幸的是,目前无法进行如上所示的端点配置,但我想如果能拥有它会很不错!目前,唯一的方法是将所有参数指定为非常长的 URI 中的参数,或者将端点配置为常规 bean,这意味着它所暗示的所有复杂性(有关详细信息,请参阅上面的 cmets)。

    【讨论】:

    • 从 Camel 2.15 开始应该有一个&lt;endpoint&gt; 标签,camel endpoint feature。我只是无法启动它,它说“已经定义了具有该名称的 bean,并且禁用了覆盖。”,无论我给端点提供什么 id...