第 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")
})
然后,实现 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;
}
最后,提供默认配置:
注解中的默认配置
@Properties({
@Property(name = "camelContextId", value = "my-test"),
@Property(name = "active", value = "true"),
@Property(name = "...", value = "..."),
...
})
这一切都是.如果您使用了 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;
}
}
CamelContextId 和 active 属性控制 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");
}
}
让我们更加详细地了解 CamelScrExampleRoute。
// Configured fields
private String camelRouteId;
private Integer maximumRedeliveries;
private Long redeliveryDelay;
private Double backOffMultiplier;
private Long maximumRedeliveryDelay;
这些字段的值通过匹配其名称,设置来自属性的值。
// Add a bean to Camel context registry
registry.put("test", "bean");
如果需要为路由添加一些 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");
}
最好检查是否设置了所需的参数,并在允许路由启动前有有意义的值。
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();
请注意,路由中的所有内容都配置有属性。这基本上使 RouteBuilder 成为模板。SCR 允许您通过提供其他配置来创建更多路由实例。在本节中,使用 Camel SCR 捆绑包作为模板 的更多信息。