如何在 Camel 中动态添加和启动路由?

How in Camel to add and start routes dynamically?

我正在尝试从 Camel 中的路线中删除一些样板文件。

例如,让我们考虑两条路线,它们是相似的并且可以生成它们的大部分内部内容。我创建了一个组件 "template",它创建了 TemplateEndpoint,并修改了一个 XML 配置以使用模板组件。

正在从 StartupListener(在 TemplateEndpoint.setSuffix 中定义)调用自定义方法 TemplateEndpoint.generateRoute(添加路由定义)。 因此,当 Camel 上下文启动时,路由定义出现在上下文中,但框架不会为它们创建路由服务,因此它们不会启动。

如何启动StartupListener中添加的路由?

可能我遇到了 XY 问题,你可以建议我一个更好的方法来解决这个问题(即动态添加和启动路线).

两条路线相似

<route id="route_A">
  <from uri="restlet:/another1?restletMethods=GET" />
  <to uri="first:run_A" />
  <to uri="second:jump_A" />     
  <to uri="third:fly_A" />
</route>

<route id="route_B">
  <from uri="restlet:/another2?restletMethods=GET" />
  <to uri="first:run_B" />
  <to uri="second:jump_B" />     
  <to uri="third:fly_B" />
</route>

修改XML

<route id="route_A">
  <from uri="restlet:/another1?restletMethods=GET" />
  <to uri="template://?suffix=A" />
</route>

<route id="route_B">
  <from uri="restlet:/another2?restletMethods=GET" />
  <to uri="template://?suffix=B" />
</route>

端点

public class TemplateEndpoint extends DefaultEndpoint {

  /* some methods omitted */ 
  // this endpoint creates a DefaultProducer, which does nothing

  public void setSuffix(final String suffix) throws Exception {

    this.getCamelContext().addStartupListener(new StartupListener() {
      @Override
      public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception {       
        generateRoute(suffix)
        .addRoutesToCamelContext(context);
      }
    });
  }

  private RouteBuilder generateRoute(final String suffix){ 
     final Endpoint endpoint = this;

     return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
          from(endpoint)
           .to("first:run_" + suffix)
           .to("second:jump_" + suffix)
           .to("third:fly_" + suffix);
       }
  }
}

我会创建一个动态路线构建器,例如

public class MyRouteBuilder extends RouteBuilder {

            private String another;
            private String letter;

            public MyRouteBuilder(CamelContext context,String another, String letter) {
                super(context);
                this.another=another;
                this.letter=letter;
            }

            @Override
            public void configure() throws Exception {
                super.configure();
                from("restlet:/"+another+"?restletMethods=GET")
                .to("first:run_"+letter)
                .to("second:jump_"+letter)
                .to("third:fly_"+letter);
            }
    }

并将其添加到某些事件中,例如

public class ApplicationContextProvider implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext context)
            throws BeansException {

        camelContext=(CamelContext)context.getBean("mainCamelContext");
        camelContext.addRoutes(new MyRouteBuilder(camelContext, "another1","A"));
        camelContext.addRoutes(new MyRouteBuilder(camelContext, "another2","B"));

..