46.3. 生成的组件子项目


概述

用于构建新组件的 Maven 子项目位于 camel-api-example/camel-api-example-component 项目目录下。在本节中,我们将仔细查看生成的示例代码并描述它的工作原理。

在组件 POM 中提供 Java API

Java API 必须在组件 POM 中提供为依赖项。例如,示例 Java API 在组件 POM 文件中定义为依赖项,camel-api-example-component/pom.xml 如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <dependencies>
    ...
    <dependency>
      <groupId>org.jboss.fuse.example</groupId>
      <artifactId>camel-api-example-api</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
  </dependencies>
  ...
</project>

在组件 POM 中提供 Javadoc 元数据

如果您要将 Javadoc 元数据用于所有或部分 Java API,则必须提供 Javadoc 作为组件 POM 中的依赖项。关于这个依赖项,需要注意以下两点:

  • Javadoc 的 Maven 协调几乎与 Java API 相同,但您还必须指定一个 classifier 元素,如下所示:

    <classifier>javadoc</classifier>
  • 您必须声明 Javadoc 来提供 范围,如下所示:

    <scope>provided</scope>

例如,在组件 POM 中,Javadoc 依赖项定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <dependencies>
    ...
    <!-- Component API javadoc in provided scope to read API signatures -->
    <dependency>
      <groupId>org.jboss.fuse.example</groupId>
      <artifactId>camel-api-example-api</artifactId>
      <version>1.0-SNAPSHOT</version>
      <classifier>javadoc</classifier>
      <scope>provided</scope>
    </dependency>
    ...
  </dependencies>
  ...
</project>

定义 Example File Hello 的文件元数据

ExampleFileHello 的元数据在签名文件中提供。通常,必须手动创建此文件,但它有简单的格式,它由一个方法签名列表组成(每行一个)。示例代码在 目录中提供签名文件 file-sig -api.txt,其具有以下内容:

public String sayHi();
public String greetMe(String name);
public String greetUs(String name1, String name2);

有关签名文件格式的详情,请参考 “签名文件元数据”一节

配置 API 映射

API 组件框架的主要功能之一是它自动生成代码来执行 API 映射。也就是说,生成将端点 URI 映射到 Java API 上方法调用的 stub 代码。API 映射的基本输入有:Java API、Javadoc 元数据和/或签名文件元数据。

执行 API 映射的组件是 camel-api-component-maven-plugin Maven 插件,插件在组件 POM 中配置。以下从组件 POM 中提取的显示如何配置 camel-api-component-maven-plugin 插件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  ...
  <build>
    <defaultGoal>install</defaultGoal>

    <plugins>
      ...
      <!-- generate Component source and test source -->
      <plugin>
        <groupId>org.apache.camel</groupId>
        <artifactId>camel-api-component-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>generate-test-component-classes</id>
            <goals>
              <goal>fromApis</goal>
            </goals>
            <configuration>
              <apis>
                <api>
                  <apiName>hello-file</apiName>
                  <proxyClass>org.jboss.fuse.example.api.ExampleFileHello</proxyClass>
                  <fromSignatureFile>signatures/file-sig-api.txt</fromSignatureFile>
                </api>
                <api>
                  <apiName>hello-javadoc</apiName>
                  <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass>
                  <fromJavadoc/>
                </api>
              </apis>
            </configuration>
          </execution>
        </executions>
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>

该插件由 configuration 元素配置,它包含单个 apis 子元素来配置 Java API 的类。每个 API 类由 api 元素配置,如下所示:

apiName

API 名称是 API 类的简短名称,用作 端点 URI 的端点前缀 部分。

注意

如果 API 仅包含一个 Java 类,您可以将 apiName 元素留空,以便 端点前缀 变为冗余,然后使用 “单个 API 类的 URI 格式”一节 中显示的格式指定端点 URI。

proxyClass
proxy class 元素指定 API 类的完全限定名称。
fromJavadoc
如果 API 类附带 Javadoc 元数据,您必须通过包括 fromJavadoc 元素和 Javadoc 本身等内容来指示这一点,且 Javadoc 本身还必须在 Maven 文件中指定,作为 提供的 依赖项(请参阅 “在组件 POM 中提供 Javadoc 元数据”一节)。
fromSignatureFile

如果 API 类与签名文件元数据相配,您必须通过包含 fromSignatureFile 元素来指示这一点,其中此元素的内容指定了签名文件的位置。

注意

签名文件 不会 包含在 Maven 构建的最终软件包中,因为仅构建时不需要这些文件,所以在运行时不需要这些文件。

生成的组件实现

API 组件由以下核心类组成(必须为每个 Camel 组件实施),位于 camel-api-example-component/src/main/java 目录:

ExampleComponent
代表组件本身。此类充当端点实例(如 ExampleEndpoint的实例)的工厂。
ExampleEndpoint
代表端点 URI。此类充当使用者端点(例如,Examper )和制作者端点(如 ExampleProducer)的工厂。
ExampleConsumer
代表消费者端点的关联实例,它可以消耗来自端点 URI 中指定的位置的消息。
ExampleProducer
代表制作者端点的传递实例,它能够将消息发送到端点 URI 中指定的位置。
ExampleConfiguration

可用于定义端点 URI 选项。此配置类定义的 URI 选项 不与任何 特定的 API 类绑定。也就是说,您可以将这些 URI 选项与任何 API 类或方法组合。例如,这将非常有用,例如,您需要声明用户名和密码凭证以连接到远程服务。ExampleConfiguration 类的主要用途是为实例化 API 类或实施 API 接口的类所需的参数提供值。例如,这些选项可以是构造器参数,也可以是工厂方法或类的参数值。

要实施 URI 选项,在本课程中的选项,您需要做的就是实施 accessor 方法的对,以获得 选项和设置 选项组件框架自动解析端点 URI,并在运行时注入选项值。

Component 类示例

生成的 Component 类定义如下:

// Java
package org.jboss.fuse.example;

import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.util.component.AbstractApiComponent;

import org.jboss.fuse.example.internal.ExampleApiCollection;
import org.jboss.fuse.example.internal.ExampleApiName;

/**
 * Represents the component that manages {@link ExampleEndpoint}.
 */
@UriEndpoint(scheme = "example", consumerClass = ExampleConsumer.class, consumerPrefix = "consumer")
public class ExampleComponent extends AbstractApiComponent<ExampleApiName, ExampleConfiguration, ExampleApiCollection> {

    public ExampleComponent() {
        super(ExampleEndpoint.class, ExampleApiName.class, ExampleApiCollection.getCollection());
    }

    public ExampleComponent(CamelContext context) {
        super(context, ExampleEndpoint.class, ExampleApiName.class, ExampleApiCollection.getCollection());
    }

    @Override
    protected ExampleApiName getApiName(String apiNameStr) throws IllegalArgumentException {
        return ExampleApiName.fromValue(apiNameStr);
    }

    @Override
    protected Endpoint createEndpoint(String uri, String methodName, ExampleApiName apiName,
                                      ExampleConfiguration endpointConfiguration) {
        return new ExampleEndpoint(uri, this, apiName, methodName, endpointConfiguration);
    }
}

此类中的重要方法是 createEndpoint,它用于创建新端点实例。通常,您不需要更改组件类中的任何默认代码。如果有任何生命周期与这个组件相同的生命周期,您可能想让这些对象从组件类提供(例如,通过添加创建这些对象的方法来创建这些对象或将这些对象注入组件)。

Endpoint 类示例

生成的 ExampleEndpoint 类定义如下:

// Java
package org.jboss.fuse.example;

import java.util.Map;

import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.util.component.AbstractApiEndpoint;
import org.apache.camel.util.component.ApiMethod;
import org.apache.camel.util.component.ApiMethodPropertiesHelper;

import org.jboss.fuse.example.api.ExampleFileHello;
import org.jboss.fuse.example.api.ExampleJavadocHello;
import org.jboss.fuse.example.internal.ExampleApiCollection;
import org.jboss.fuse.example.internal.ExampleApiName;
import org.jboss.fuse.example.internal.ExampleConstants;
import org.jboss.fuse.example.internal.ExamplePropertiesHelper;

/**
 * Represents a Example endpoint.
 */
@UriEndpoint(scheme = "example", consumerClass = ExampleConsumer.class, consumerPrefix = "consumer")
public class ExampleEndpoint extends AbstractApiEndpoint<ExampleApiName, ExampleConfiguration> {

    // TODO create and manage API proxy
    private Object apiProxy;

    public ExampleEndpoint(String uri, ExampleComponent component,
                         ExampleApiName apiName, String methodName, ExampleConfiguration endpointConfiguration) {
        super(uri, component, apiName, methodName, ExampleApiCollection.getCollection().getHelper(apiName), endpointConfiguration);

    }

    public Producer createProducer() throws Exception {
        return new ExampleProducer(this);
    }

    public Consumer createConsumer(Processor processor) throws Exception {
        // make sure inBody is not set for consumers
        if (inBody != null) {
            throw new IllegalArgumentException("Option inBody is not supported for consumer endpoint");
        }
        final ExampleConsumer consumer = new ExampleConsumer(this, processor);
        // also set consumer.* properties
        configureConsumer(consumer);
        return consumer;
    }

    @Override
    protected ApiMethodPropertiesHelper<ExampleConfiguration> getPropertiesHelper() {
        return ExamplePropertiesHelper.getHelper();
    }

    protected String getThreadProfileName() {
        return ExampleConstants.THREAD_PROFILE_NAME;
    }

    @Override
    protected void afterConfigureProperties() {
        // TODO create API proxy, set connection properties, etc.
        switch (apiName) {
            case HELLO_FILE:
                apiProxy = new ExampleFileHello();
                break;
            case HELLO_JAVADOC:
                apiProxy = new ExampleJavadocHello();
                break;
            default:
                throw new IllegalArgumentException("Invalid API name " + apiName);
        }
    }

    @Override
    public Object getApiProxy(ApiMethod method, Map<String, Object> args) {
        return apiProxy;
    }
}

在 API 组件框架上下文中,端点类执行的一个关键步骤之一是创建 API 代理。API 代理是一个来自目标 Java API 的实例,其方法由端点调用。因为 Java API 通常由多个类组成,因此需要根据 端点前缀 出现在 URI 中(记住 URI 具有常规形式 ://端点前缀/端点)。

Consumer 类示例

生成的 ExampleConsumer 类定义如下:

// Java
package org.jboss.fuse.example;

import org.apache.camel.Processor;
import org.apache.camel.util.component.AbstractApiConsumer;

import org.jboss.fuse.example.internal.ExampleApiName;

/**
 * The Example consumer.
 */
public class ExampleConsumer extends AbstractApiConsumer<ExampleApiName, ExampleConfiguration> {

    public ExampleConsumer(ExampleEndpoint endpoint, Processor processor) {
        super(endpoint, processor);
    }

}

Producer 类示例

生成的 示例Producer 类定义如下:

// Java
package org.jboss.fuse.example;

import org.apache.camel.util.component.AbstractApiProducer;

import org.jboss.fuse.example.internal.ExampleApiName;
import org.jboss.fuse.example.internal.ExamplePropertiesHelper;

/**
 * The Example producer.
 */
public class ExampleProducer extends AbstractApiProducer<ExampleApiName, ExampleConfiguration> {

    public ExampleProducer(ExampleEndpoint endpoint) {
        super(endpoint, ExamplePropertiesHelper.getHelper());
    }
}

Configuration 类示例

生成的 ExampleConfiguration 类定义如下:

// Java
package org.jboss.fuse.example;

import org.apache.camel.spi.UriParams;

/**
 * Component configuration for Example component.
 */
@UriParams
public class ExampleConfiguration {

    // TODO add component configuration properties
}

要将 URI 选项( 选项 )添加到此类中,定义相应类型的字段,并实施对应的访问者方法、get 选项和 设置选项。 组件框架自动解析端点 URI,并在运行时注入选项值。

注意

此类用于定义 通用 URI 选项,这些选项可与任何 API 方法组合使用。要定义与特定 API 方法关联的 URI 选项,请在 API 组件 Maven 插件中配置额外的选项。详情请查看 第 47.7 节 “额外选项”

URI 格式

回想 API 组件 URI 的一般格式:

scheme://endpoint-prefix/endpoint?Option1=Value1&...&OptionN=ValueN

通常,URI 映射到 Java API 上的特定方法调用。例如,假设您要调用 API 方法,示例JavadocHello.greetMe ("Jane Doe") 将被构建,如下所示:

scheme
API 组件方案,如使用 Maven archetype 生成代码时指定。在这种情况下,方案是 示例
endpoint-prefix

API 名称,映射到由 camel-api-component-maven-plugin Maven 插件配置定义的 API 类。对于 ExampleJavadocHello 类,相关的配置是:

<configuration>
  <apis>
    <api>
      <apiName>hello-javadoc</apiName>
      <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass>
      <fromJavadoc/>
    </api>
    ...
  </apis>
</configuration>

这表明所需的 端点前缀为 hello-javadoc

端点
端点 映射到方法名称,即 greetMe
Option1=Value1
URI 选项指定方法参数。greetMe (String name) 方法采用单参数,即 name,它可以指定为 name=Jane%20Doe。如果要为选项定义默认值,可以通过覆盖拦截器 Properties 方法(请参阅 第 46.4 节 “编程模型”)来执行此操作。

将 URI 放在一起,我们发现我们可以使用以下 URI 调用 ExampleJavadocHello.greetMe ("Jane Doe")

example://hello-javadoc/greetMe?name=Jane%20Doe

默认组件实例

要将 示例 URI 方案映射到默认组件实例,Maven archetype 会在 camel-api-example-component 子项目下创建以下文件:

src/main/resources/META-INF/services/org/apache/camel/component/example

此资源文件可让 Camel 核心识别与 示例 URI 架构关联的组件。每当您在路由中使用 example:// URI 时,Camel 会搜索 classpath 以查找对应的 示例 资源文件。示例文件 包含以下内容:

class=org.jboss.fuse.example.ExampleComponent

这可让 Camel 核心创建 ExampleComponent 组件的默认实例。如果您重构组件类的名称,您只需要编辑此文件的唯一时间。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.