Chapter 46. Getting Started with the Framework Abstract This chapter explains the basic principles of implementing a Camel component using the API component framework, based on code generated using the camel-archetype-api-component Maven archetype. 46.1. Generate Code with the Maven Archetype Maven archetypes A Maven archetype is analogous to a code wizard: given a few simple parameters, it generates a complete, working Maven project, populated with sample code. You can then use this project as a template, customizing the implementation to create your own application. The API component Maven archetype The API component framework provides a Maven archetype, camel-archetype-api-component , that can generate starting point code for your own API component implementation. This is the recommended approach to start creating your own API component. Prerequisites The only prerequisites for running the camel-archetype-api-component archetype are that Apache Maven is installed and the Maven settings.xml file is configured to use the standard Fuse repositories. Invoke the Maven archetype To create an Example component, which uses the example URI scheme, invoke the camel-archetype-api-component archetype to generate a new Maven project, as follows: Note The backslash character, \ , at the end of each line represents line continuation, which works only on Linux and UNIX platforms. On Windows platforms, remove the backslash and put the arguments all on a single line. Options Options are provided to the archetype generation command using the syntax, -D Name = Value . Most of the options should be set as shown in the preceding mvn archetype:generate command, but a few of the options can be modified, to customize the generated project. The following table shows the options that you can use to customize the generated API component project: Name Description groupId (Generic Maven option) Specifies the group ID of the generated Maven project. By default, this value also defines the Java package name for the generated classes. Hence, it is a good idea to choose this value to match the Java package name that you want. artifactId (Generic Maven option) Specifies the artifact ID of the generated Maven project. name The name of the API component. This value is used for generating class names in the generated code (hence, it is recommended that the name should start with a capital letter). scheme The default scheme to use in URIs for this component. You should make sure that this scheme does not conflict with the scheme of any existing Camel components. archetypeVersion (Generic Maven option) Ideally, this should be the Apache Camel version used by the container where you plan to deploy the component. If necessary, however, you can also modify the versions of Maven dependencies after you have generated the project. Structure of the generated project Assuming that the code generation step completes successfully, you should see a new directory, camel-api-example , which contains the new Maven project. If you look inside the camel-api-example directory, you will see that it has the following general structure: At the top level of the project is an aggregate POM, pom.xml , which is configured to build two sub-projects, as follows: camel-api-example-api The API sub-project (named as ArtifactId -api ) holds the Java API which you are about to turn into a component. If you are basing the API component on a Java API that you wrote yourself, you can put the Java API code directly into this project. The API sub-project can be used for one or more of the following purposes: To package up the Java API code (if it is not already available as a Maven package). To generate Javadoc for the Java API (providing the needed metadata for the API component framework). To generate the Java API code from an API description (for example, from a WADL description of a REST API). In some cases, however, you might not need to perform any of these tasks. For example, if the API component is based on a third-party API, which already provides the Java API and Javadoc in a Maven package. In such cases, you can delete the API sub-project. camel-api-example-component The component sub-project (named as ArtifactId -component ) holds the implementation of the new API component. This includes the component implementation classes and the configuration of the camel-api-component-maven plug-in (which generates the API mapping classes from the Java API). 46.2. Generated API Sub-Project Overview Assuming that you generated a new Maven project as described in Section 46.1, "Generate Code with the Maven Archetype" , you can now find a Maven sub-project for packaging the Java API under the camel-api-example/camel-api-example-api project directory. In this section, we take a closer look at the generated example code and describe how it works. Sample Java API The generated example code includes a sample Java API, on which the example API component is based. The sample Java API is relatively simple, consisting of just two Hello World classes: ExampleJavadocHello and ExampleFileHello . ExampleJavadocHello class Example 46.1, "ExampleJavadocHello class" shows the ExampleJavadocHello class from the sample Java API. As the name of the class suggests, this particular class is used to show how you can supply mapping metadata from Javadoc. Example 46.1. ExampleJavadocHello class ExampleFileHello class Example 46.2, "ExampleFileHello class" shows the ExampleFileHello class from the sample Java API. As the name of the class suggests, this particular class is used to show how you can supply mapping metadata from a signature file. Example 46.2. ExampleFileHello class Generating the Javadoc metadata for ExampleJavadocHello Because the metadata for ExampleJavadocHello is provided as Javadoc, it is necessary to generate Javadoc for the sample Java API and install it into the camel-api-example-api Maven artifact. The API POM file, camel-api-example-api/pom.xml , configures the maven-javadoc-plugin to perform this step automatically during the Maven build. 46.3. Generated Component Sub-Project Overview The Maven sub-project for building the new component is located under the camel-api-example/camel-api-example-component project directory. In this section, we take a closer look at the generated example code and describe how it works. Providing the Java API in the component POM The Java API must be provided as a dependency in the component POM. For example, the sample Java API is defined as a dependency in the component POM file, camel-api-example-component/pom.xml , as follows: Providing the Javadoc metadata in the component POM If you are using Javadoc metadata for all or part of the Java API, you must provide the Javadoc as a dependency in the component POM. There are two things to note about this dependency: The Maven coordinates for the Javadoc are almost the same as for the Java API, except that you must also specify a classifier element, as follows: You must declare the Javadoc to have provided scope, as follows: For example, in the component POM, the Javadoc dependency is defined as follows: Defining the file metadata for Example File Hello The metadata for ExampleFileHello is provided in a signature file. In general, this file must be created manually, but it has quite a simple format, which consists of a list of method signatures (one on each line). The example code provides the signature file, file-sig-api.txt , in the directory, camel-api-example-component/signatures , which has the following contents: For more details about the signature file format, see the section called "Signature file metadata" . Configuring the API mapping One of the key features of the API component framework is that it automatically generates the code to perform API mapping . That is, generating stub code that maps endpoint URIs to method invocations on the Java API. The basic inputs to the API mapping are: the Java API, the Javadoc metadata, and/or the signature file metadata. The component that performs the API mapping is the camel-api-component-maven-plugin Maven plug-in, which is configured in the component POM. The following extract from the component POM shows how the camel-api-component-maven-plugin plug-in is configured: The plug-in is configured by the configuration element, which contains a single apis child element to configure the classes of the Java API. Each API class is configured by an api element, as follows: apiName The API name is a short name for the API class and is used as the endpoint-prefix part of an endpoint URI. Note If the API consists of just a single Java class, you can leave the apiName element empty, so that the endpoint-prefix becomes redundant, and you can then specify the endpoint URI using the format shown in the section called "URI format for a single API class" . proxyClass The proxy class element specifies the fully-qualified name of the API class. fromJavadoc If the API class is accompanied by Javadoc metadata, you must indicate this by including the fromJavadoc element and the Javadoc itself must also be specified in the Maven file, as a provided dependency (see the section called "Providing the Javadoc metadata in the component POM" ). fromSignatureFile If the API class is accompanied by signature file metadata, you must indicate this by including the fromSignatureFile element, where the content of this element specifies the location of the signature file. Note The signature files do not get included in the final package built by Maven, because these files are needed only at build time, not at run time. Generated component implementation The API component consists of the following core classes (which must be implemented for every Camel component), under the camel-api-example-component/src/main/java directory: ExampleComponent Represents the component itself. This class acts as a factory for endpoint instances (for example, instances of ExampleEndpoint ). ExampleEndpoint Represents an endpoint URI. This class acts as a factory for consumer endpoints (for example, ExampleConsumer ) and as a factory for producer endpoints (for example, ExampleProducer ). ExampleConsumer Represents a concrete instance of a consumer endpoint, which is capable of consuming messages from the location specified in the endpoint URI. ExampleProducer Represents a concrete instance of a producer endpoint, which is capable of sending messages to the location specified in the endpoint URI. ExampleConfiguration Can be used to define endpoint URI options. The URI options defined by this configuration class are not tied to any specific API class. That is, you can combine these URI options with any of the API classes or methods. This can be useful, for example, if you need to declare username and password credentials in order to connect to the remote service. The primary purpose of the ExampleConfiguration class is to provide values for parameters required to instantiate API classes, or classes that implement API interfaces. For example, these could be constructor parameters, or parameter values for a factory method or class. To implement a URI option, option , in this class, all that you need to do is implement the pair of accessor methods, get Option and set Option . The component framework automatically parses the endpoint URI and injects the option values at run time. ExampleComponent class The generated ExampleComponent class is defined as follows: The important method in this class is createEndpoint , which creates new endpoint instances. Typically, you do not need to change any of the default code in the component class. If there are any other objects with the same life cycle as this component, however, you might want to make those objects available from the component class (for example, by adding a methods to create those objects or by injecting those objects into the component). ExampleEndpoint class The generated ExampleEndpoint class is defined as follows: In the context of the API component framework, one of the key steps performed by the endpoint class is to create an API proxy . The API proxy is an instance from the target Java API, whose methods are invoked by the endpoint. Because a Java API typically consists of many classes, it is necessary to pick the appropriate API class, based on the endpoint-prefix appearing in the URI (recall that a URI has the general form, scheme :// endpoint-prefix / endpoint ). ExampleConsumer class The generated ExampleConsumer class is defined as follows: ExampleProducer class The generated ExampleProducer class is defined as follows: ExampleConfiguration class The generated ExampleConfiguration class is defined as follows: To add a URI option, option , to this class, define a field of the appropriate type, and implement a corresponding pair of accessor methods, get Option and set Option . The component framework automatically parses the endpoint URI and injects the option values at run time. Note This class is used to define general URI options, which can be combined with any API method. To define URI options tied to a specific API method, configure extra options in the API component Maven plug-in. See Section 47.7, "Extra Options" for details. URI format Recall the general format of an API component URI: In general, a URI maps to a specific method invocation on the Java API. For example, suppose you want to invoke the API method, ExampleJavadocHello.greetMe("Jane Doe") , the URI would be constructed, as follows: scheme The API component scheme, as specified when you generated the code with the Maven archetype. In this case, the scheme is example . endpoint-prefix The API name, which maps to the API class defined by the camel-api-component-maven-plugin Maven plug-in configuration. For the ExampleJavadocHello class, the relevant configuration is: Which shows that the required endpoint-prefix is hello-javadoc . endpoint The endpoint maps to the method name, which is greetMe . Option1=Value1 The URI options specify method parameters. The greetMe(String name) method takes the single parameter, name , which can be specified as name=Jane%20Doe . If you want to define default values for options, you can do this by overriding the interceptProperties method (see Section 46.4, "Programming Model" ). Putting together the pieces of the URI, we see that we can invoke ExampleJavadocHello.greetMe("Jane Doe") with the following URI: Default component instance In order to map the example URI scheme to the default component instance, the Maven archetype creates the following file under the camel-api-example-component sub-project: This resource file is what enables the Camel core to identify the component associated with the example URI scheme. Whenever you use an example:// URI in a route, Camel searches the classpath to look for the corresponding example resource file. The example file has the following contents: This enables the Camel core to create a default instance of the ExampleComponent component. The only time you would need to edit this file is if you refactor the name of the component class. 46.4. Programming Model Overview In the context of the API component framework, the main component implementation classes are derived from base classes in the org.apache.camel.util.component package. These base classes define some methods which you can (optionally) override when you are implementing your component. In this section, we provide a brief description of those methods and how you might use them in your own component implementation. Component methods to implement In addition to the generated method implementations (which you usually do not need to modify), you can optionally override some of the following methods in the Component class: doStart() (Optional) A callback to create resources for the component during a cold start. An alternative approach is to adopt the strategy of lazy initialization (creating resources only when they are needed). In fact, lazy initialization is often the best strategy, so the doStart method is often not needed. doStop() (Optional) A callback to invoke code while the component is stopping. Stopping a component means that all of its resources are shut down, internal state is deleted, caches are cleared, and so on. Note Camel guarantees that doStop is always called when the current CamelContext shuts down, even if the corresponding doStart was never called. doShutdown (Optional) A callback to invoke code while the CamelContext is shutting down. Whereas a stopped component can be restarted (with the semantics of a cold start), a component that gets shut down is completely finished. Hence, this callback represents the last chance to free up any resources belonging to the component. What else to implement in the Component class? The Component class is the natural place to hold references to objects that have the same (or similar) life cycle to the component object itself. For example, if a component uses OAuth security, it would be natural to hold references to the required OAuth objects in the Component class and to define methods in the Component class for creating the OAuth objects. Endpoint methods to implement You can modify some of the generated methods and, optionally, override some inherited methods in the Endpoint class, as follows: afterConfigureProperties() The main thing you need to do in this method is to create the appropriate type of proxy class (API class), to match the API name. The API name (which has already been extracted from the endpoint URI) is available either through the inherited apiName field or through the getApiName accessor. Typically, you would do a switch on the apiName field to create the corresponding proxy class. For example: getApiProxy(ApiMethod method, Map<String, Object> args) Override this method to return the proxy instance that you created in afterConfigureProperties . For example: In special cases, you might want to make the choice of proxy dependent on the API method and arguments. The getApiProxy gives you the flexibility to take this approach, if required. doStart() (Optional) A callback to create resources during a cold start. Has the same semantics as Component.doStart() . doStop() (Optional) A callback to invoke code while the component is stopping. Has the same semantics as Component.doStop() . doShutdown (Optional) A callback to invoke code while the component is shutting down. Has the same semantics as Component.doShutdown() . interceptPropertyNames(Set<String> propertyNames) (Optional) The API component framework uses the endpoint URI and supplied option values to determine which method to invoke (ambiguity could be due to overloading and aliases). If the component internally adds options or method parameters, however, the framework might need help in order to determine the right method to invoke. In this case, you must override the interceptPropertyNames method and add the extra (hidden or implicit) options to the propertyNames set. When the complete list of method parameters are provided in the propertyNames set, the framework will be able to identify the right method to invoke. Note You can override this method at the level of the Endpoint , Producer or Consumer class. The basic rule is, if an option affects both producer endpoints and consumer endpoints, override the method in the Endpoint class. interceptProperties(Map<String,Object> properties) (Optional) By overriding this method, you can modify or set the actual values of the options, before the API method is invoked. For example, you could use this method to set default values for some options, if necessary. In practice, it is often necessary to override both the interceptPropertyNames method and the interceptProperty method. Note You can override this method at the level of the Endpoint , Producer or Consumer class. The basic rule is, if an option affects both producer endpoints and consumer endpoints, override the method in the Endpoint class. Consumer methods to implement You can optionally override some inherited methods in the Consumer class, as follows: interceptPropertyNames(Set<String> propertyNames) (Optional) The semantics of this method are similar to Endpoint.interceptPropertyNames interceptProperties(Map<String,Object> properties) (Optional) The semantics of this method are similar to Endpoint.interceptProperties doInvokeMethod(Map<String, Object> args) (Optional) Overriding this method enables you to intercept the invocation of the Java API method. The most common reason for overriding this method is to customize the error handling around the method invocation. For example, a typical approach to overriding doInvokeMethod is shown in the following code fragment: You should invoke doInvokeMethod on the super-class, at some point in this implementation, to ensure that the Java API method gets invoked. interceptResult(Object methodResult, Exchange resultExchange) (Optional) Do some additional processing on the result of the API method invocation. For example, you could add custom headers to the Camel exchange object, resultExchange , at this point. Object splitResult(Object result) (Optional) By default, if the result of the method API invocation is a java.util.Collection object or a Java array, the API component framework splits the result into multiple exchange objects (so that a single invocation result is converted into multiple messages). If you want to change the default behaviour, you can override the splitResult method in the consumer endpoint. The result argument contains the result of the API message invocation. If you want to split the result, you should return an array type. Note You can also switch off the default splitting behaviour by setting consumer.splitResult=false on the endpoint URI. Producer methods to implement You can optionally override some inherited methods in the Producer class, as follows: interceptPropertyNames(Set<String> propertyNames) (Optional) The semantics of this method are similar to Endpoint.interceptPropertyNames interceptProperties(Map<String,Object> properties) (Optional) The semantics of this method are similar to Endpoint.interceptProperties doInvokeMethod(Map<String, Object> args) (Optional) The semantics of this method are similar to Consumer.doInvokeMethod . interceptResult(Object methodResult, Exchange resultExchange) (Optional) The semantics of this method are similar to Consumer.interceptResult . Note The Producer.splitResult() method is never called, so it is not possible to split an API method result in the same way as you can for a consumer endpoint. To get a similar effect for a producer endpoint, you can use Camel's split() DSL command (one of the standard enterprise integration patterns) to split Collection or array results. Consumer polling and threading model The default threading model for consumer endpoints in the API component framework is scheduled poll consumer . This implies that the API method in a consumer endpoint is invoked at regular, scheduled time intervals. For more details, see the section called "Scheduled poll consumer implementation" . 46.5. Sample Component Implementations Overview Several of the components distributed with Apache Camel have been implemented with the aid of the API component framework. If you want to learn more about the techniques for implementing Camel components using the framework, it is a good idea to study the source code of these component implementations. Box.com The Camel Box component shows how to model and invoke the third party Box.com Java SDK using the API component framework. It also demonstrates how the framework can be adapted to customize consumer polling, in order to support Box.com's long polling API. GoogleDrive The Camel GoogleDrive component demonstrates how the API component framework can handle even Method Object style Google APIs. In this case, URI options are mapped to a method object, which is then invoked by overriding the doInvoke method in the consumer and the producer. Olingo2 The Camel Olingo2 component demonstrates how a callback-based Asynchronous API can be wrapped using the API component framework. This example shows how asynchronous processing can be pushed into underlying resources, like HTTP NIO connections, to make Camel endpoints more resource efficient.

Commands:
mvn archetype:generate -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-api-component -DarchetypeVersion=2.23.2.fuse-7_13_0-00013-redhat-00001 -DgroupId=org.jboss.fuse.example -DartifactId=camel-api-example -Dname=Example -Dscheme=example -Dversion=1.0-SNAPSHOT -DinteractiveMode=false
camel-api-example/ pom.xml camel-api-example-api/ camel-api-example-component/
// Java package org.jboss.fuse.example.api; /** * Sample API used by Example Component whose method signatures are read from Javadoc. */ public class ExampleJavadocHello { public String sayHi() { return "Hello!"; } public String greetMe(String name) { return "Hello " + name; } public String greetUs(String name1, String name2) { return "Hello " + name1 + ", " + name2; } }
// Java package org.jboss.fuse.example.api; /** * Sample API used by Example Component whose method signatures are read from File. */ public class ExampleFileHello { public String sayHi() { return "Hello!"; } public String greetMe(String name) { return "Hello " + name; } public String greetUs(String name1, String name2) { return "Hello " + name1 + ", " + name2; } }
<?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>
<classifier>javadoc</classifier>
<scope>provided</scope>
<?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>
public String sayHi(); public String greetMe(String name); public String greetUs(String name1, String name2);
<?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 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); } }
// 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; } }
// 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); } }
// 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()); } }
// 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 }
scheme :// endpoint-prefix / endpoint ? Option1 = Value1 &...& OptionN = ValueN
<configuration> <apis> <api> <apiName> hello-javadoc </apiName> <proxyClass>org.jboss.fuse.example.api.ExampleJavadocHello</proxyClass> <fromJavadoc/> </api> </apis> </configuration>
example://hello-javadoc/greetMe?name=Jane%20Doe
src/main/resources/META-INF/services/org/apache/camel/component/example
class=org.jboss.fuse.example.ExampleComponent
// Java private Object apiProxy; @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; }
// Java @Override protected Object doInvokeMethod(Map<String, Object> args) { try { return super.doInvokeMethod(args); } catch (RuntimeCamelException e) { // TODO - Insert custom error handling here! } }