Chapter 39. Component Interface
Abstract
This chapter describes how to implement the Component interface.
39.1. The Component Interface
Overview
To implement a Apache Camel component, you must implement the org.apache.camel.Component interface. An instance of Component
type provides the entry point into a custom component. That is, all of the other objects in a component are ultimately accessible through the Component
instance. Figure 39.1, “Component Inheritance Hierarchy” shows the relevant Java interfaces and classes that make up the Component
inheritance hierarchy.
Figure 39.1. Component Inheritance Hierarchy
The Component interface
Example 39.1, “Component Interface” shows the definition of the org.apache.camel.Component interface.
Example 39.1. Component Interface
package org.apache.camel; public interface Component { CamelContext getCamelContext(); void setCamelContext(CamelContext context); Endpoint createEndpoint(String uri) throws Exception; }
Component methods
The Component interface defines the following methods:
-
getCamelContext()
andsetCamelContext()
— References theCamelContext
to which this Component belongs. ThesetCamelContext()
method is automatically called when you add the component to aCamelContext
. -
createEndpoint()
— The factory method that gets called to createEndpoint
instances for this component. Theuri
parameter is the endpoint URI, which contains the details required to create the endpoint.
39.2. Implementing the Component Interface
The DefaultComponent class
You implement a new component by extending the org.apache.camel.impl.DefaultComponent
class, which provides some standard functionality and default implementations for some of the methods. In particular, the DefaultComponent
class provides support for URI parsing and for creating a scheduled executor (which is used for the scheduled poll pattern).
URI parsing
The createEndpoint(String uri)
method defined in the base Component interface takes a complete, unparsed endpoint URI as its sole argument. The DefaultComponent
class, on the other hand, defines a three-argument version of the createEndpoint()
method with the following signature:
protected abstract Endpoint createEndpoint( String uri, String remaining, Map parameters ) throws Exception;
uri
is the original, unparsed URI; remaining
is the part of the URI that remains after stripping off the component prefix at the start and cutting off the query options at the end; and parameters
contains the parsed query options. It is this version of the createEndpoint()
method that you must override when inheriting from DefaultComponent
. This has the advantage that the endpoint URI is already parsed for you.
The following sample endpoint URI for the file
component shows how URI parsing works in practice:
file:///tmp/messages/foo?delete=true&moveNamePostfix=.old
For this URI, the following arguments are passed to the three-argument version of createEndpoint()
:
Argument | Sample Value |
---|---|
| |
|
|
|
Two entries are set in
|
Parameter injection
By default, the parameters extracted from the URI query options are injected on the endpoint’s bean properties. The DefaultComponent
class automatically injects the parameters for you.
For example, if you want to define a custom endpoint that supports two URI query options: delete
and moveNamePostfix
. All you must do is define the corresponding bean methods (getters and setters) in the endpoint class:
public class FileEndpoint extends ScheduledPollEndpoint { ... public boolean isDelete() { return delete; } public void setDelete(boolean delete) { this.delete = delete; } ... public String getMoveNamePostfix() { return moveNamePostfix; } public void setMoveNamePostfix(String moveNamePostfix) { this.moveNamePostfix = moveNamePostfix; } }
It is also possible to inject URI query options into consumer parameters. For details, see the section called “Consumer parameter injection”.
Disabling endpoint parameter injection
If there are no parameters defined on your Endpoint
class, you can optimize the process of endpoint creation by disabling endpoint parameter injection. To disable parameter injection on endpoints, override the useIntrospectionOnEndpoint()
method and implement it to return false
, as follows:
protected boolean useIntrospectionOnEndpoint() { return false; }
The useIntrospectionOnEndpoint()
method does not affect the parameter injection that might be performed on a Consumer
class. Parameter injection at that level is controlled by the Endpoint.configureProperties()
method (see Section 40.2, “Implementing the Endpoint Interface”).
Scheduled executor service
The scheduled executor is used in the scheduled poll pattern, where it is responsible for driving the periodic polling of a consumer endpoint (a scheduled executor is effectively a thread pool implementation).
To instantiate a scheduled executor service, use the ExecutorServiceStrategy
object that is returned by the CamelContext.getExecutorServiceStrategy()
method. For details of the Apache Camel threading model, see Section 2.8, “Threading Model”.
Prior to Apache Camel 2.3, the DefaultComponent
class provided a getExecutorService()
method for creating thread pool instances. Since 2.3, however, the creation of thread pools is now managed centrally by the ExecutorServiceStrategy
object.
Validating the URI
If you want to validate the URI before creating an endpoint instance, you can override the validateURI()
method from the DefaultComponent
class, which has the following signature:
protected void validateURI(String uri, String path, Map parameters) throws ResolveEndpointFailedException;
If the supplied URI does not have the required format, the implementation of validateURI()
should throw the org.apache.camel.ResolveEndpointFailedException
exception.
Creating an endpoint
Example 39.2, “Implementation of createEndpoint()
” outlines how to implement the DefaultComponent.createEndpoint()
method, which is responsible for creating endpoint instances on demand.
Example 39.2. Implementation of createEndpoint()
public class CustomComponent extends DefaultComponent { 1 ... protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { 2 CustomEndpoint result = new CustomEndpoint(uri, this); 3 // ... return result; } }
- 1
- The CustomComponent is the name of your custom component class, which is defined by extending the
DefaultComponent
class. - 2
- When extending
DefaultComponent
, you must implement thecreateEndpoint()
method with three arguments (see the section called “URI parsing”). - 3
- Create an instance of your custom endpoint type, CustomEndpoint, by calling its constructor. At a minimum, this constructor takes a copy of the original URI string,
uri
, and a reference to this component instance,this
.
Example
Example 39.3, “FileComponent Implementation” shows a sample implementation of a FileComponent
class.
Example 39.3. FileComponent Implementation
package org.apache.camel.component.file; import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; import org.apache.camel.impl.DefaultComponent; import java.io.File; import java.util.Map; public class FileComponent extends DefaultComponent { public static final String HEADER_FILE_NAME = "org.apache.camel.file.name"; public FileComponent() { 1 } public FileComponent(CamelContext context) { 2 super(context); } protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { 3 File file = new File(remaining); FileEndpoint result = new FileEndpoint(file, uri, this); return result; } }
- 1
- Always define a no-argument constructor for the component class in order to facilitate automatic instantiation of the class.
- 2
- A constructor that takes the parent
CamelContext
instance as an argument is convenient when creating a component instance by programming. - 3
- The implementation of the
FileComponent.createEndpoint()
method follows the pattern described in Example 39.2, “Implementation ofcreateEndpoint()
”. The implementation creates aFileEndpoint
object.
SynchronizationRouteAware Interface
SynchronizationRouteAware
interface allows you to have callbacks before and after the exchange has been routed.
-
onBeforeRoute
: Invoked before the exchange has been routed by the given route. However, this callback may not get invoked, if you add theSynchronizationRouteAware
implementation to theUnitOfWork
, after starting the route. onAfterRoute
: Invoked after the exchange has been routed by the given route. However, if the exchange is being routed through multiple routes, it would generate call backs for each route.This invocation occurs before these callbacks:
-
The consumer of the route writes any response back to the caller (if in
InOut
mode) -
The
UnitOfWork
is done by calling eitherSynchronization.onComplete(org.apache.camel.Exchange)
orSynchronization.onFailure(org.apache.camel.Exchange)
-
The consumer of the route writes any response back to the caller (if in