第 295 章 Camel SCR (已弃用)


从 Camel 2.15 开始提供

SCR 代表 Service 组件运行时,是 OSGi Declarative Services 规范的实施。SCR 使任何普通的旧 Java 对象能够公开和使用 without boilerplate 代码的 OSGi 服务。

JAAS 框架通过查看捆绑包中的 SCR 描述符文件,这些文件通常由 org.apache.felix:maven-scr-plugin 等插件从 Java 注解生成。

在 SCR 捆绑包中运行 Camel 是 Spring DM 和 Blueprint 的解决方案的一个好替代方法,其代码行可大大减少到 OSGi 框架之间。使用 SCR 您的捆绑包可以完全保留在 Java 世界中;无需编辑 XML 或属性文件。这使您可以完全控制一切,这意味着您选择的 IDE 准确了解您的项目中正在进行的内容。

295.1. Camel SCR 支持

camel-scr 捆绑包没有包括在 Apache Camel 版本 2.15.0 中,但工件本身可用于 2.12.0 的任何 Camel 版本。

org.apache.camel/camel-scr 捆绑包提供基本类 AbstractCamelRunner,它为您和帮助程序类管理 Camel 上下文,用于在单元测试中使用 SCR 属性。Apache Karaf 的 camel-scr 功能定义了在 SCR 捆绑包中运行 Camel 所需的所有功能和捆绑包。

AbstractCamelRunner 类将 CamelContext 的生命周期与服务组件的生命周期相关联,并通过 Camel 的 PropertiesComponent 来处理配置。您只需要使 Service 组件从 java 类中扩展它,并从 AbstractCamelRunner 扩展它,并在类级别上添加以下 org.apache.felix.scr.annotations

添加所需的注解

@Component
@References({
    @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class,
        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
        policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent")
})
Copy to Clipboard Toggle word wrap

然后,实现 getRouteBuilders () 方法,它返回您要运行的 Camel 路由:

Implement getRouteBuilders()

    @Override
    protected List<RoutesBuilder> getRouteBuilders() {
        List<RoutesBuilder> routesBuilders = new ArrayList<>();
        routesBuilders.add(new YourRouteBuilderHere(registry));
        routesBuilders.add(new AnotherRouteBuilderHere(registry));
        return routesBuilders;
    }
Copy to Clipboard Toggle word wrap

最后,提供默认配置:

注解中的默认配置

@Properties({
   @Property(name = "camelContextId", value = "my-test"),
   @Property(name = "active", value = "true"),
   @Property(name = "...", value = "..."),
   ...
})
Copy to Clipboard Toggle word wrap

这一切都是.如果您使用了 camel-archetype-scr 来生成一个项目,则已这样做。

以下是由 camel-archetype-scr 生成的完整的 Service 组件类示例:

CamelScrExample.java

// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
package example;

import java.util.ArrayList;
import java.util.List;

import org.apache.camel.scr.AbstractCamelRunner;
import example.internal.CamelScrExampleRoute;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.spi.ComponentResolver;
import org.apache.felix.scr.annotations.*;

@Component(label = CamelScrExample.COMPONENT_LABEL, description = CamelScrExample.COMPONENT_DESCRIPTION, immediate = true, metatype = true)
@Properties({
    @Property(name = "camelContextId", value = "camel-scr-example"),
    @Property(name = "camelRouteId", value = "foo/timer-log"),
    @Property(name = "active", value = "true"),
    @Property(name = "from", value = "timer:foo?period=5000"),
    @Property(name = "to", value = "log:foo?showHeaders=true"),
    @Property(name = "messageOk", value = "Success: {{from}} -> {{to}}"),
    @Property(name = "messageError", value = "Failure: {{from}} -> {{to}}"),
    @Property(name = "maximumRedeliveries", value = "0"),
    @Property(name = "redeliveryDelay", value = "5000"),
    @Property(name = "backOffMultiplier", value = "2"),
    @Property(name = "maximumRedeliveryDelay", value = "60000")
})
@References({
    @Reference(name = "camelComponent",referenceInterface = ComponentResolver.class,
        cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC,
        policyOption = ReferencePolicyOption.GREEDY, bind = "gotCamelComponent", unbind = "lostCamelComponent")
})
public class CamelScrExample extends AbstractCamelRunner {

    public static final String COMPONENT_LABEL = "example.CamelScrExample";
    public static final String COMPONENT_DESCRIPTION = "This is the description for camel-scr-example.";

    @Override
    protected List<RoutesBuilder> getRouteBuilders() {
        List<RoutesBuilder> routesBuilders = new ArrayList<>();
        routesBuilders.add(new CamelScrExampleRoute(registry));
        return routesBuilders;
    }
}
Copy to Clipboard Toggle word wrap

CamelContextIdactive 属性控制 CamelContext 的名称(默认为 "camel-runner-default"),以及是否分别启动它(默认为 "false")。除了这些之外,您还可以添加和使用尽可能多的属性。Camel 的 PropertiesComponent 处理递归属性,并在没有问题的情况下为回退添加前缀。

AbstractCamelRunner 将使这些属性可供您的 RouteBuilders 使用,并帮助 Camel 的 PropertiesComponent,并在其名称匹配时将这些值注入 Service 组件和 RouteBuilder 的字段中。可以使用任何可见性级别声明字段,并且支持许多类型(String, int, boolean, URL, …​)。

以下是 camel-archetype-scr 生成的 RouteBuilder 类示例:

CamelScrExampleRoute.java

// This file was generated from org.apache.camel.archetypes/camel-archetype-scr/2.15-SNAPSHOT
package example.internal;

import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.SimpleRegistry;
import org.apache.commons.lang.Validate;

public class CamelScrExampleRoute extends RouteBuilder {

    SimpleRegistry registry;

    // Configured fields
    private String camelRouteId;
    private Integer maximumRedeliveries;
    private Long redeliveryDelay;
    private Double backOffMultiplier;
    private Long maximumRedeliveryDelay;

    public CamelScrExampleRoute(final SimpleRegistry registry) {
        this.registry = registry;
    }

    @Override
    public void configure() throws Exception {
        checkProperties();

        // Add a bean to Camel context registry
        registry.put("test", "bean");

        errorHandler(defaultErrorHandler()
            .retryAttemptedLogLevel(LoggingLevel.WARN)
            .maximumRedeliveries(maximumRedeliveries)
            .redeliveryDelay(redeliveryDelay)
            .backOffMultiplier(backOffMultiplier)
            .maximumRedeliveryDelay(maximumRedeliveryDelay));

        from("{{from}}")
            .startupOrder(2)
            .routeId(camelRouteId)
            .onCompletion()
                .to("direct:processCompletion")
            .end()
            .removeHeaders("CamelHttp*")
            .to("{{to}}");


        from("direct:processCompletion")
            .startupOrder(1)
            .routeId(camelRouteId + ".completion")
            .choice()
                .when(simple("${exception} == null"))
                    .log("{{messageOk}}")
                .otherwise()
                    .log(LoggingLevel.ERROR, "{{messageError}}")
            .end();
        }
    }

    public void checkProperties() {
        Validate.notNull(camelRouteId, "camelRouteId property is not set");
        Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set");
        Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set");
        Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set");
        Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set");
    }
}
Copy to Clipboard Toggle word wrap

让我们更加详细地了解 CamelScrExampleRoute

    // Configured fields
    private String camelRouteId;
    private Integer maximumRedeliveries;
    private Long redeliveryDelay;
    private Double backOffMultiplier;
    private Long maximumRedeliveryDelay;
Copy to Clipboard Toggle word wrap

这些字段的值通过匹配其名称,设置来自属性的值。

        // Add a bean to Camel context registry
        registry.put("test", "bean");
Copy to Clipboard Toggle word wrap

如果需要为路由添加一些 beans 到 CamelContext 的 registry,您可以执行以下操作:

    public void checkProperties() {
        Validate.notNull(camelRouteId, "camelRouteId property is not set");
        Validate.notNull(maximumRedeliveries, "maximumRedeliveries property is not set");
        Validate.notNull(redeliveryDelay, "redeliveryDelay property is not set");
        Validate.notNull(backOffMultiplier, "backOffMultiplier property is not set");
        Validate.notNull(maximumRedeliveryDelay, "maximumRedeliveryDelay property is not set");
    }
Copy to Clipboard Toggle word wrap

最好检查是否设置了所需的参数,并在允许路由启动前有有意义的值。

        from("{{from}}")
            .startupOrder(2)
            .routeId(camelRouteId)
            .onCompletion()
                .to("direct:processCompletion")
            .end()
            .removeHeaders("CamelHttp*")
            .to("{{to}}");


        from("direct:processCompletion")
            .startupOrder(1)
            .routeId(camelRouteId + ".completion")
            .choice()
                .when(simple("${exception} == null"))
                    .log("{{messageOk}}")
                .otherwise()
                    .log(LoggingLevel.ERROR, "{{messageError}}")
            .end();
Copy to Clipboard Toggle word wrap

请注意,路由中的所有内容都配置有属性。这基本上使 RouteBuilder 成为模板。SCR 允许您通过提供其他配置来创建更多路由实例。在本节中,使用 Camel SCR 捆绑包作为模板 的更多信息。

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2025 Red Hat