54.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.NoteCamel guarantees that
doStop
is always called when the currentCamelContext
shuts down, even if the correspondingdoStart
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 thegetApiName
accessor. Typically, you would do a switch on theapiName
field to create the corresponding proxy class. For example:// 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); } }
getApiProxy(ApiMethod method, Map<String, Object> args)
- Override this method to return the proxy instance that you created in
afterConfigureProperties
. For example:@Override public Object getApiProxy(ApiMethod method, Map<String, Object> args) { return apiProxy; }
In special cases, you might want to make the choice of proxy dependent on the API method and arguments. ThegetApiProxy
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 thepropertyNames
set. When the complete list of method parameters are provided in thepropertyNames
set, the framework will be able to identify the right method to invoke.NoteYou can override this method at the level of theEndpoint
,Producer
orConsumer
class. The basic rule is, if an option affects both producer endpoints and consumer endpoints, override the method in theEndpoint
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 theinterceptProperty
method.NoteYou can override this method at the level of theEndpoint
,Producer
orConsumer
class. The basic rule is, if an option affects both producer endpoints and consumer endpoints, override the method in theEndpoint
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:// Java @Override protected Object doInvokeMethod(Map<String, Object> args) { try { return super.doInvokeMethod(args); } catch (RuntimeCamelException e) { // TODO - Insert custom error handling here! ... } }
You should invokedoInvokeMethod
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 thesplitResult
method in the consumer endpoint. Theresult
argument contains the result of the API message invocation. If you want to split the result, you should return an array type.NoteYou can also switch off the default splitting behaviour by settingconsumer.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”.