使用Java接口或Bean启动Camel路由是否可行?

14

我想设置一个Spring bean(可以通过接口或bean类)来“启动”一个Route。

在这个简单的例子中,当我从代码中调用sayHello(“world”)时,我希望它将sayHello方法的返回值路由到将其写入文件的端点。

是否有人知道是否可能实现这一点,或如何去做? 我知道我可以通过CXF公开相同的接口并使其工作,但我只是想调用一个方法,而不是经历发送JMS消息或调用Web服务的麻烦。

public interface Hello{
   public String sayHello(String value);
}

from("bean:helloBean").to("file:/data/outbox?fileName=hello.txt");
5个回答

16

您可以使用ProducerTemplate:

import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Component
public class HelloImpl implements Hello {

    @Produce(uri = "direct:start")
    private ProducerTemplate template;

    @Override
    public Object sayHello(String value) throws ExecutionException, InterruptedException {
        Future future = template.asyncSendBody(template.getDefaultEndpoint(), value);
        return future.get();
    }
}

你的骆驼路由应该如下所示:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
         http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.mycompany.camel"/>

    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="direct:start"/>
            <to uri="log:com.mycompany.camel?level=DEBUG"/>
        </route>
    </camelContext>

</beans>

10

谢谢回答我的问题。我想我需要更新一下我的 MEAP 书籍。对于第14章,它说TBD。不过这本书还是非常有帮助的! - ScArcher2

2

我需要查看Claus的答案,但为了快速简单地创建UI,我采用了不同的方法。

我正在使用Spring MVC 3.1.X,并为我的应用程序中的各种项目编写了管理控制台。我编写了一个控制器来显示路由及其状态,并提供启动和停止路由的链接。以下是一些代码:

@Controller
public class CamelController {
    private static final Log LOG = LogFactory.getLog(CamelController.class);

    @Autowired
    @Qualifier("myCamelContextID")
    private CamelContext camelContext;

    @RequestMapping(value = "/dashboard", method = RequestMethod.GET)
    public String dashboard(Model model) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("camel context is suspended : " + camelContext.isSuspended());
        }

        List<Route> routes = camelContext.getRoutes();
        List<RouteStatus> routeStatuses = new ArrayList<RouteStatus>();
        for (Route r : routes) {
            RouteStatus rs = new RouteStatus();
            rs.setId(r.getId());
            rs.setServiceStatus(camelContext.getRouteStatus(r.getId()));
            routeStatuses.add(rs);
        }

        model.addAttribute("routeStatuses", routeStatuses);

        return "dashboard";
    }

    @RequestMapping(value = "/dashboard/{routeId}/start", method = RequestMethod.GET)
    public String startRoute(@PathVariable String routeId) {
        try {
            camelContext.startRoute(routeId);
            if (LOG.isDebugEnabled()) {
                LOG.debug("camel context is starting route [" + routeId + "]");
            }
        } catch (Exception e) {
            LOG.error("failed to start camel context [" + camelContext + "]");
        }

        return "redirect:/dashboard";
     }

    @RequestMapping(value = "/dashboard/{routeId}/stop", method = RequestMethod.GET)
    public String stopRoute(@PathVariable String routeId) {
        try {
            camelContext.stopRoute(routeId);
            if (LOG.isDebugEnabled()) {
                LOG.debug("camel context is stopping route [" + routeId + "]");
            }
        } catch (Exception e) {
            LOG.error("failed to stop camel context [" + camelContext + "]");
        }
        return "redirect:/dashboard";
        }
    }
}

有一个我做的小POJO与之配合:

public class RouteStatus {
    private String id;
    private ServiceStatus serviceStatus;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public ServiceStatus getServiceStatus() {
        return serviceStatus;
    }

    public void setServiceStatus(ServiceStatus serviceStatus) {
        this.serviceStatus = serviceStatus;
    }
}

2

其他的答案对我都不起作用,它们都编译成功并且是有效的,但路由没有触发。

这是我最终使用的解决方案:

import org.apache.camel.Handler;

public class Hello{

   @Produce(uri = "direct:start")
   private ProducerTemplate producer;

   @Handler   
   public void sayHello() {
       producer.sendBody("hello")
   }
}

from("timer:hubspotContacts?repeatCount=1").bean(Hello.class);
from("direct:start").to("log:hello");
  • 第一条路由中的定时器组件是我缺失的关键部分。使用repeatCount=1,它仅在启动时触发一次,并导致调用bean方法。如果需要多次调用该方法,则还支持调用速率或延迟。
  • @Handler注释作为标记,因此不必在路由配置中显式指定方法名称
  • 直接组件将生产者与其消费者连接起来

0

由于我的路由是使用CamelConfiguration的Spring组件,因此我按照以下步骤在camel路由中使用我的接口。

@Component
public class SomeRoute extends RouteBuilder {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void configure() throws Exception {
        from("direct:someroute")
        .bean(applicationContext.getBean(SomeInterface.class).getClass(), "someAbstractMethod")
        .to("direct:otherroute");
    }
}

这是一个非常简单的情况,如果您有多个使用相同接口或抽象类的bean,则在对bean使用.getClass()之前可能需要进行一些逻辑处理。


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