46.3. 생성된 구성 요소 하위 프로젝트

46.3.1. 개요

새 구성 요소를 구축하기 위한 Maven 하위 프로젝트는 camel-api-example/camel-api-example-component 프로젝트 디렉터리에 있습니다. 이 섹션에서는 생성된 예제 코드를 자세히 살펴보고 작동 방식을 설명합니다.

46.3.2. 구성 요소 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>

46.3.3. 구성 요소 POM에 Javadoc 메타데이터 제공

Java API의 전체 또는 일부에 Javadoc 메타데이터를 사용하는 경우 Javadoc을 구성 요소 POM의 종속성으로 제공해야 합니다. 이 종속성에 대해 알아야 할 두 가지 사항이 있습니다.

  • Javadoc의 Maven 좌표는 다음과 같이 분류자 요소도 지정해야 한다는 점을 제외하고 Java API와 거의 동일합니다.

    <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>

46.3.4. 예제 파일 Hello의 파일 메타데이터 정의

ExampleFileHello 의 메타데이터는 서명 파일에 제공됩니다. 일반적으로 이 파일은 수동으로 생성해야 하지만 메서드 서명 목록으로 구성된 간단한 형식(각 줄에 하나씩)이 있습니다. 예제 코드는 다음 콘텐츠가 포함된 서명 파일 file-sig-api.txt 디렉터리에 camel-api-example-component/signatures 를 제공합니다.

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

서명 파일 형식에 대한 자세한 내용은 “서명 파일 메타데이터” 을 참조하십시오.

46.3.5. API 매핑 구성

API 구성 요소 프레임워크의 주요 기능 중 하나는 API 매핑 을 수행하기 위해 자동으로 코드를 생성한다는 것입니다. 즉, 엔드포인트 URI를 Java API에서 메서드 호출에 매핑하는 스텁 코드를 생성합니다. API 매핑의 기본 입력은 Java API, Javadoc 메타데이터 및/또는 서명 파일 메타데이터입니다.

API 매핑을 수행하는 구성 요소는 POM 구성 요소에 구성된 camel-api-component-maven-plugin Maven 플러그인입니다. 구성 요소 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>

플러그인은 Java API의 클래스를 구성하는 단일 apis 하위 요소가 포함된 구성 요소로 구성됩니다. 각 API 클래스는 다음과 같이 api 요소에 의해 구성됩니다.

apiName

API 이름은 API 클래스의 짧은 이름이며 엔드포인트 URI의 엔드포인트-접 두사 부분으로 사용됩니다.

참고

API가 단일 Java 클래스로 구성된 경우 apiName 요소를 비워 두어 끝점 이 중복되게 하고 “단일 API 클래스의 URI 형식” 에 표시된 형식을 사용하여 끝점 URI를 지정할 수 있습니다.

proxyClass
proxy class 요소는 API 클래스의 정규화된 이름을 지정합니다.
fromJavadoc
API 클래스가 Javadoc 메타데이터와 함께 제공되는 경우 fromJavadoc 요소를 포함하여 이를 지정해야 하며 Javadoc 자체는 Maven 파일에 제공된 종속성으로 지정해야 합니다( “구성 요소 POM에 Javadoc 메타데이터 제공”참조).
fromSignatureFile

API 클래스가 서명 파일 메타데이터와 함께 이 클래스의 콘텐츠가 서명 파일의 위치를 지정하는 fromSignatureFile 요소를 포함하여 이를 표시해야 합니다.

참고

서명 파일은 런타임이 아닌 빌드 시에만 필요하므로 Maven에서 빌드한 최종 패키지에 포함되지 않습니다.

46.3.6. 생성된 구성 요소 구현

API 구성 요소는 camel-api-example-component/src/main/java 디렉터리에 있는 다음 코어 클래스(모든 Camel 구성 요소에 구현되어야 함)로 구성됩니다.

ExampleComponent
구성 요소 자체를 나타냅니다. 이 클래스는 끝점 인스턴스의 팩토리 역할을 합니다(예: ExampleEndpoint의 인스턴스).
ExampleEndpoint
엔드포인트 URI를 나타냅니다. 이 클래스는 소비자 끝점(예: ExampleConsumer)의 팩토리 역할을 하며 생산자 끝점(예: ExampleProducer)의 팩토리 역할을 합니다.
ExampleConsumer
엔드포인트 URI에 지정된 위치에서 메시지를 사용할 수 있는 소비자 끝점의 구체적인 인스턴스를 나타냅니다.
ExampleProducer
생산자 엔드포인트의 구체적인 인스턴스를 나타내며 엔드포인트 URI에 지정된 위치로 메시지를 전송할 수 있습니다.
예제Configuration

을 사용하여 엔드포인트 URI 옵션을 정의할 수 있습니다. 이 구성 클래스에서 정의한 URI 옵션은 특정 API 클래스에 연결되지 않습니다. 즉, 이러한 URI 옵션을 API 클래스 또는 메서드와 결합할 수 있습니다. 예를 들어 원격 서비스에 연결하기 위해 사용자 이름 및 암호 자격 증명을 선언해야 하는 경우 이 기능이 유용할 수 있습니다. ExampleConfiguration 클래스의 기본 목적은 API 클래스 또는 API 인터페이스를 구현하는 클래스를 인스턴스화하는 데 필요한 매개변수 값을 제공하는 것입니다. 예를 들어 생성자 매개 변수 또는 팩토리 메서드 또는 클래스의 매개 변수 값이 될 수 있습니다.For example, these could be constructor parameters, or parameter values for a factory method or class.

URI 옵션을 구현하려면 옵션 (옵션)을 구현하려면 접근자 메서드 쌍을 구현하고 옵션가져오기 및 옵션을 설정합니다. 구성 요소 프레임워크는 엔드포인트 URI를 자동으로 구문 분석하고 런타임에 옵션 값을 삽입합니다.

46.3.7. ExampleComponent 클래스

생성된 ExampleComponent 클래스는 다음과 같이 정의됩니다.

// 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 입니다. 일반적으로 구성 요소 클래스의 기본 코드를 변경할 필요가 없습니다. 그러나 이 구성 요소와 동일한 라이프 사이클이 있는 다른 개체가 있는 경우 구성 요소 클래스에서 해당 개체를 사용할 수 있도록 할 수 있습니다(예: 해당 개체를 만드는 메서드를 추가하거나 해당 개체를 구성 요소에 삽입하여).

46.3.8. ExampleEndpoint 클래스

생성된 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에 나타나는 엔드포인트-접 두사에 따라 적절한 API 클래스를 선택해야 합니다(UU에 일반 형식인 scheme://endpoint-prefix/endpoint).

46.3.9. 예제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);
    }

}

46.3.10. ExampleProducer 클래스

생성된 ExampleProducer 클래스는 다음과 같이 정의됩니다.

// 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());
    }
}

46.3.11. 구성 클래스 예

생성된 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 옵션, 옵션 , 옵션을 이 클래스에 추가하고, 적절한 유형의 필드를 정의하고, 해당 접근자 메서드 쌍을 구현하려면 옵션을 가져오고 옵션을 설정합니다. 구성 요소 프레임워크는 엔드포인트 URI를 자동으로 구문 분석하고 런타임에 옵션 값을 삽입합니다.

참고

이 클래스는 모든 API 메서드와 결합할 수 있는 일반 URI 옵션을 정의하는 데 사용됩니다. 특정 API 메서드에 연결된 URI 옵션을 정의하려면 API 구성 요소 Maven 플러그인에서 추가 옵션을 구성합니다. 자세한 내용은 47.7절. “추가 옵션” 을 참조하십시오.

46.3.12. URI 형식

API 구성 요소 URI의 일반 형식을 상기합니다.

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

일반적으로 URI는 Java API에서 특정 메서드 호출에 매핑됩니다. 예를 들어 API 메서드 ExampleJavadocHello. CryostatMe("Jane Doe") 를 호출하려는 경우 다음과 같이 URI가 구성됩니다.

스키마
Maven archetype을 사용하여 코드를 생성할 때 지정된 API 구성 요소 체계입니다. 이 경우 스키마는 예제 입니다.
endpoint-prefix

camel-api-component-maven-plugin Maven 플러그인 구성으로 정의된 API 클래스에 매핑되는 API 이름입니다. ExampleJavadocHello 클래스의 경우 관련 구성은 다음과 같습니다.

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

필수 endpoint-prefixhello-javadoc 임을 보여줍니다.

endpoint
엔드포인트 는 메서드 이름( Me )에 매핑됩니다.
Option1=Value1
URI 옵션은 메서드 매개변수를 지정합니다. Cryo statMe(String name) 메서드는 name =Jane%20Doe 로 지정할 수 있는 단일 매개변수인 name을 사용합니다. 옵션에 대한 기본값을 정의하려면 interceptProperties 메서드를 재정의하여 이 작업을 수행할 수 있습니다( 46.4절. “프로그래밍 모델”참조).

URI 조각을 통합하면 다음 URI를 사용하여 ExampleJavadocHello. CryostatMe("Jane Doe") 를 호출할 수 있습니다.

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

46.3.13. 기본 구성 요소 인스턴스

예제 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 구성 요소의 기본 인스턴스를 생성할 수 있습니다. 이 파일을 편집해야 하는 유일한 시간은 구성 요소 클래스의 이름을 리팩터링하는 것입니다.