LibraryLink ToToggle FramesPrintFeedback

Implementing the Component Interface

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

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<E> 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():

Header 1Header 2
urifile:///tmp/messages/foo?delete=true&moveNamePostfix=.old
remaining/tmp/messages/foo
parameters

Two entries are set in java.util.Map:

  • parameter delete is boolean true

  • parameter moveNamePostfix has the string value, .old.

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<FileExchange> {
    ...
    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 Consumer 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;
}
[Note]Note

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 Implementing the Endpoint Interface).

The DefaultComponent class is capable of initializing a scheduled executor service, which schedules commands to execute periodically. In particular, the scheduled executor is used in the scheduled poll pattern, where it is responsible for driving the periodic polling of a consumer endpoint.

To instantiate a scheduled executor service, call the DefaultComponent.getExecutorService() method, which returns a java.util.concurrent.ScheduledThreadPoolExecutor instance that implements the java.util.concurrent.ScheduledExecutorService interface). The ScheduledThreadPoolExecutor instance is initialized with a thread pool containing five threads. This implies that a scheduled poll consumer can process up to five incoming requests in parallel.

[Note]Note

Instantiation of the thread pool is lazy, such that no executor service is created until you actually call getExecutorService().

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.

Example 5.2 outlines how to implement the DefaultComponent.createEndpoint() method, which is responsible for creating endpoint instances on demand.

Example 5.2. Implementation of createEndpoint()

public class CustomComponent extends DefaultComponent<CustomExchange> { 1
    ...
    protected Endpoint<CustomExchange> 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. The type argument, CustomExchange, can be a custom exchange implementation, but you can also just use Exchange here.

2

When extending DefaultComponent, you must implement the createEndpoint() method with three arguments (see 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 5.3 shows the complete implementation of the FileComponent class, which is taken from the FUSE Mediation Router file component implementation.

Example 5.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<FileExchange> {
    public static final String HEADER_FILE_NAME = "org.apache.camel.file.name";

    public FileComponent() { 1
    }

    public FileComponent(CamelContext context) { 2
        super(context);
    }

    protected Endpoint<FileExchange> 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 5.2. The implementation creates a FileEndpoint object.