Apache Camel:如何最好地重用其他路由中的Camel路由?

4
我尝试使用routeContext在同一个camelContext内复用Camel路由,但是我发现在使用onException、intercept、dataFormats等方面存在一些限制,正如如何从其他XML文件中导入路由所述。
另一个选择是使用多个camelContext和vm-direct端点进行通信,但是Spring Boot只能使用一个camelContext。在这个备选方案中,我找到了这篇文章如何在Spring Boot应用程序中配置多个Camel上下文
是否有其他选择来共享路由而没有任何限制?
Spring Boot Came单一configl xml模型中不接受多个camel上下文的问题相关添加更多信息: 我希望在一个大的路由中构建完整的处理工作流程,其中包含许多具有特定任务的小路由。我倾向于使用XML DSL而不是Java以便使用图形编辑器。
主要的处理工作流程将自动生成(不可修改),然后开发团队只需实现具有特定任务的小路由。其中一个要求是我必须使用Spring Boot。 第一次尝试:一个Camel上下文,并通过routeContext导入路由。使用直接端点来通信路由。
文件mainWorkFlow.xml
<!-- Import routerContexts-->
<import resource="tranformationIN_route.xml"/>
<import resource="tranformationOUT_route.xml"/>
<camelContext id="mainWorkFlow">        
    <!-- refer to custom routes -->
    <routeContextRef ref="tranformationIN"/>
    <routeContextRef ref="tranformationOUT"/>
    <route id="main">
        <from id="_inRequest" uri="cxf:bean:exposedWS"/>
        <to id="_validation" uri="inputData.xsd"/>
        <!-- Call route in another context for transformation data received to a backend service data model -->
        <to id="_toTransformationInRoute" uri="direct:appTransformationInRoute"/> 
        <!-- Call backend service -->
        <to id="_wsBE" uri="cxf:bean:backendWS"/>
        <!-- Call route in another context for transformation data from backend service response to exposed service data model -->
        <to id="_toTransformationOutRoute" uri="direct:appTransformationOutRoute"/>
    </route>
</camelContext>

File tranformationIN_route.xml

<routeContext ...>  
    <endpoint id="reqTrans" uri="dozer:...req_transformation.xml"/>
    <!--
        Declare dataFormats used by dozer           
    -->
    <dataFormats>
        <jaxb contextPath="some.package" id="someID"/>
    </dataFormats>
    <route id="tranformationIN">
        <from uri="direct:appTransformationInRoute"/>
        <to id="_to1" uri="ref:reqTrans"/>
    </route>
</routeContext>

File tranformationOUT_route.xml

<routeContext ...>  
    <endpoint id="reqTrans" uri="dozer:...resp_transformation.xml"/>
    <!--
        Declare dataFormats used by dozer           
    -->
    <dataFormats>
        <jaxb contextPath="some.package" id="someID"/>
    </dataFormats>
    <route id="tranformationOUT">
        <from uri="direct:appTransformationOutRoute"/>
        <to id="_to1" uri="ref:respTrans"/>
    </route>
</routeContext>

看起来我们不能在路由上下文中使用数据格式:

    Caused by: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: 
    Line 6 in XML document from class path resource [spring/custom-routes.xml] is invalid; 
    nested exception is org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 22; cvc-complex-type.2.4.a: Se ha encontrado contenido no válido a partir del elemento 'dataFormats'. 
    Se esperaba uno de '{"http://camel.apache.org/schema/spring":route}'...

第二次尝试: 多个CamelContext。使用direct-vm端点来通信路由。

文件 mainWorkFlow.xml

<camelContext id="mainWorkFlow">
    <route id="main">
        <from id="_inRequest" uri="cxf:bean:exposedWS"/>
        <to id="_validation" uri="inputData.xsd"/>
        <!-- Call route in another context for transformation data received to a backend service data model -->
        <to id="_toTransformationInRoute" uri="direct-vm:appTransformationInRoute"/> 
        <!-- Call backend service -->
        <to id="_wsBE" uri="cxf:bean:backendWS"/>
        <!-- Call route in another context for transformation data from backend service response to exposed service data model -->
        <to id="_toTransformationOutRoute" uri="direct-vm:appTransformationOutRoute"/>
    </route>
</camelContext>

File appContextTranformationIn_context.xml

<camelContext id="appContextTranformationIn">
    <endpoint id="reqTrans" uri="dozer:...req_transformation.xml"/>
    <!--
        Data forman generated automatically by dozer
        If necessary, here I could use dataFormat, onException and interceptor
    -->
     <dataFormats>
        <jaxb contextPath="some.package" id="someID"/>
    </dataFormats>
    <!--  -->
    <route id="tranformationIN">
        <from uri="direct-vm:appTransformationInRoute"/>
        <to id="_to1" uri="ref:reqTrans"/>
    </route>
</camelContext> 

File appContextTranformationOut_context.xml

<camelContext id="appContextTranformationOut">
    <endpoint id="reqTrans" uri="dozer:...resp_transformation.xml"/>
    <!--
        Data forman generated automatically by dozer
        If necessary, here I could use dataFormat, onException and interceptor
    -->
    <dataFormats>
        <jaxb contextPath="some.package" id="someID"/>
    </dataFormats>
    <route id="tranformationOUT">
        <from uri="direct-vm:appTransformationOutRoute"/>
        <to id="_to1" uri="ref:respTrans"/>
    </route>
</camelContext> 

问题 Spring Boot不喜欢在其中运行超过一个camelcontext :/ * 路由转换IN(appContextTranformationIn)和转换OUT(appContextTranformationOut)应该在一个camelContext中,但是Spring Boot的问题是相同的。


你真的需要将这些路由导入到特定的路由类中吗?一旦它们通过Spring/Camel注册,你应该能够通过.to(...)直接引用它们或者通过在你的路由中定义的消费者(例如directseda等)接收它们。你能解释一下为什么需要导入路由吗?你是否使用XML配置的路由或直接通过Java配置的路由(自从几个Camel版本以来推荐使用)? - Roman Vottner
谢谢回复!!我添加了更多信息。 - Ángel
1个回答

7
您可以从每个路由中重复使用Camel上下文,并不受其它路由的限制,这只与您的路由设计有关。
您可以在一个大型路由中构建完整的处理工作流程。但是如果构建第二个工作流程,则不能使用第一个路由的任何内容,完全无法重复使用。
但是,如果使用许多小路由构建相同的工作流程,其中每个路由都有特定任务要执行,那么您可以构建第二个工作流程,该工作流程几乎可以使用第一个工作流程的每个块。
通常,这些小路由看起来像这样:
from(direct:validation)
    .bean(...)
  • 它们有一个direct端点,可以轻松地从每个其他路由调用它们(同步)。
  • 它们只执行一项任务。
  • 它们没有to()“退出”,因为它们是请求/响应,因此当路由完成时返回给调用者。

如果您构建这样的可重用块,则可以从每个“主”路由调用它们。

from(...)
    .to("direct:validation")
    .to("direct:transform")
    .to("direct:enrich")
    ...

由于问题中提供了更多信息,因此进行补充:

对于您的第一次尝试:您不能在routeContext中使用dataFormat。您需要将其移至camelContext并从routeContext中引用它。

以下是Camel文档中的代码片段:

注意:当您使用routeContext时,它们是分离的,不能重用现有的onExceptioninterceptdataFormats和类似的跨越功能,这些功能在camelContext中定义。换句话说,routeContext当前被隔离。

对于您的第二次尝试:如果您正在使用Spring Boot,为什么还要坚持使用XML路由?图形化编辑器可能很好,但是您所遇到的整个问题在Java路由中不存在。Spring Boot是远离Spring XML配置向Java配置的主要驱动力之一。

即使您坚持使用Spring XML配置,但编写Java路由,也不会有这个问题。您可以轻松地将所有RouteBuilders导入到Camel Context中。

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
    <routeBuilder ref="myMainRoute" />    
    <routeBuilder ref="mySpecificRoute1" />    
    <routeBuilder ref="mySpecificRoute2" />    
</camelContext>

谢谢回复!!我添加了更多信息。 - Ángel
我已经扩展了我的回答。 - burki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接