【问题标题】:How to use a custom processor if defined (not null)?如果定义(非空)如何使用自定义处理器?
【发布时间】:2019-10-08 15:36:34
【问题描述】:

我想要一个允许使用可选自定义处理器的基本 RouteBuilder 类。如果子类指定了它,则将其添加到路由中,否则不要。

我一直在尝试使用choice() when() otherwise() 构造,但不用说没有成功。我是使用 Apache Camel 的新手,所以我不确定如何解释/修复错误消息。如果定义了自定义处理器,它可以正常工作,但如果它为 null,我会收到下面的错误消息。

package test;

import org.apache.camel.CamelContext;
import org.apache.camel.LoggingLevel;
import org.apache.camel.Predicate;
import org.apache.camel.Processor;
import org.apache.camel.builder.PredicateBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class SimpleApp {
  public static final long FIVE_MINUTES = 5 * 60 * 1000;

  public SimpleApp() {
    try {
      CamelContext ctx = new DefaultCamelContext();
      ctx.addRoutes( new SimpleRouteBuilder() );
      ctx.addRoutes(new org.apache.camel.builder.RouteBuilder() {
        @Override
        public void configure() throws Exception {
          Processor proc = new SimpleProcessor();
          // proc = null;
          Predicate useProc = PredicateBuilder.isNotNull( constant( proc ) );

          from("timer://myTimer?period=3000")
          .setBody()
            .simple("Creating a new message at ${header.firedTime}")
          .log(LoggingLevel.WARN,  "Message Generated at ${header.firedTime}")
          .to("stream:out")
          .choice()
            .when(useProc)
              .log(LoggingLevel.WARN, "Using Custom Processor (is not null)")
              .process( proc )
              .to("stream:out")
              .endChoice()
            .otherwise()
              .log(LoggingLevel.WARN, "Skipping Custom Processor (is null)")
              .endChoice()
          .end()
          .log(LoggingLevel.WARN, "Ended choice construct")
          .to("stream:out");
        }
      });
      ctx.start();
      System.out.println("Started....");
      Thread.sleep( FIVE_MINUTES );
      System.out.println("Done waiting, exiting");
      ctx.stop();
    }
    catch( Exception e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    new SimpleApp();
  }

}

处理器是一个虚拟占位符,但无论如何这里是代码。

package test;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;

public class SimpleProcessor implements Processor {

  public SimpleProcessor() {
    System.out.println("Running Simple Processor");
  }

  @Override
  public void process(Exchange exchange) throws Exception {
    System.out.println("Processing Exchange");
  }

}

即使我设置了 proc = null,我也希望能够工作,但我却收到以下错误消息:

19-10-08 11:30:15.710] test.SimpleProcessor:14 [INFO  ] => Running Simple Processor
org.apache.camel.FailedToCreateRouteException: Failed to create route route2 at: >>> Choice[[When[{null is not null} -> [Log[Using Custom Processor (is not null)], process[Processor@0x0], To[stream:out]]]] Otherwise[[Log[Skipping Custom Processor (is null)]]]] <<< in route: Route(route2)[[From[timer://myTimer?period=3000]] -> [SetBod... because of ref must be specified on: process[Processor@0x0]
    at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:1352)
    at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:212)
    at org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:1140)
    at org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:3735)
    at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:3440)
    at org.apache.camel.impl.DefaultCamelContext$4.call(DefaultCamelContext.java:3248)
    at org.apache.camel.impl.DefaultCamelContext$4.call(DefaultCamelContext.java:3244)
    at org.apache.camel.impl.DefaultCamelContext.doWithDefinedClassLoader(DefaultCamelContext.java:3267)
    at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:3244)
    at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:72)
    at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:3160)
    at test.SimpleApp.<init>(SimpleApp.java:47)
    at test.SimpleApp.main(SimpleApp.java:61)
Caused by: java.lang.IllegalArgumentException: ref must be specified on: process[Processor@0x0]

【问题讨论】:

    标签: java apache apache-camel


    【解决方案1】:

    对于processor 组件,它需要在创建路由时实现java interface Processor 的类的java 实例。显然null不符合要求。

    要解决此问题,请创建两个函数来返回 RouteBuilder,一个没有处理器,一个有处理器(通过变量传递)。然后具有选择使用哪个RouteBuilder的功能。

    // Sample code - function with processor (pass by variable)
    protected static RouteBuilder createRouteBuilder(final Processor myProcessor) throws Exception{
    
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("timer://myTimer?period=3000")
                    // omit steps
                    .process(myProcessor)
                    // omit steps
                    .to("stream:out");
            }
        };
    }
    

    【讨论】:

    • 感谢您的回答。你是对的, null 不是处理器,这就是谓词的目的。根本问题是(如果可行)我如何使用choice() when() 来测试处理器是否为空,如果不为空则将其添加到路由中,如果为空则跳过它
    • @OegBizz Camel RouteBuilder 要求处理器在何时创建路由时明确定义,而谓词仅在交换通过时有效(即之后 b> 路线已创建)。解决方法是建议您将控件从 Camel RouteBuilder 转移到 java 函数。
    【解决方案2】:

    @hk6279 的评论是有效的,但不是我需要的方法,因为如果我想要/需要多个处理器,那么定义不同方法的 if 条件将涉及太多。

    我更改了应用程序并使用 XML 文件和 Spring 来挂钩提供所有组件。它使用命名组件,应用程序通过名称获取它们。在我的 RouteBuilder 配置方法中,我获取对象并创建谓词;

    Processor reqProc = 
           this.getContext().getRegistry().lookupByNameAndType("requestProcessor", Processor.class);
    Predicate useReqProc = PredicateBuilder.isNotNull( constant( reqProc ) );
    

    无论出于何种原因,如果我从 XML 中定义的 bean 获取处理器,我可以使用我需要的 choice() when() otherwise() 构造。如果我直接尝试,如问题所示,我不能。一旦我从上面得到谓词,我就可以做到以下几点:

    from( sources.toArray(new String[0]) )
          .split().method(RequestSplitter.class, "splitMessage")
          .choice()
            .when(useReqProc)
              .log(LoggingLevel.INFO, "Found the request processor using it")
              .to("bean:" + "requestProcessor")
            .endChoice()
            .otherwise()
              .log(LoggingLevel.ERROR, "requestProcessor not found, stopping route")
              .stop()
            .endChoice()
          .end()
          .log("Sending the request the ARES URI")
          .recipientList(header(Constants.HDR_TARGET_URI));
    

    我希望这对其他人有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-12
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2011-08-16
      • 1970-01-01
      相关资源
      最近更新 更多