
As an example, a service-unit for the XSLT service-engine must contain a XSL file. This file is used by the component to run XSL transformations, the transformation being based on this XSL sheet.
A service-unit embeds:
* A *JBI descriptor* (META-INF/jbi.xml file), which defines the provided and consumed services.
Each service is described with an interface name, a service name, an end-point name, plus additional parameters. The JBI descriptor is what was called “service-unit configuration”.
* A *WSDL file*, which is the interface of the service created by the component from this configuration. It is referenced in the JBI descriptor.
* Depending on the component task, some *other resources* (e.g. Java code), directly or indirectly referenced by the JBI descriptor (Java libraries are indirectly referenced through a class name).
\\
The provided WSDL is the interface of the service that will be created by the component from the configuration. Every service in Petals should have a WSDL interface, so that it can be called (e.g. in an orchestration). In the case where a service-unit does not provide a WSDL, and if it makes sense for your component, your component should provide a default WSDL that can be used for the service-unit.
As an example, this what the Mail and the FTP components offer. The components have generic operations like send(), put(), get() and so on. Therefore, they can provide a WSDL by default. In this case, we speak of native services provided by the component. The configuration then simply provides parameters for these services.
If a service-unit does not embed a WSDL file, and if your component does not have a default one, the Petals kernel generates one by default (setting information from the service-unit jbi.xml file). But this is definitely a situation to avoid, because the generated WSDL has no operation and consequently, cannot be used in WSDL-driven calls.
h1. The CDK
In Petals, components interact with the container according to a standard called *JBI (Java Business Integration)*. This standard defines interfaces that a component must implement to interact with the JBI environment. To simplify the development of these components, Petals provides a framework providing an API which implement the required interfaces and makes the work lighter. This framework, known as the *Component Development Toolkit (CDK)*, also provides utility methods and a common basis for all the Petals components.
Implementing a Petals component based on the CDK reduces the amount of code to write. There are only few interfaces or abstract classes to extend and complete.
When you go through the steps given in the previous pages, the built code relies on the CDK.
One element that must be insisted on, is that *the CDK is a framework*.
It means you can use the code it provides to develop components quite easily.
But *it also requires to be configured*. The configuration is made in both the component configuration files, and in the service-unit configurations.
Concretely, it is illustrated by the presence of a CDK section in the JBI descriptors of a component and of a service-unit.
h1. Providers vs. Consumers
In Petals, there are two roles a component can hold.
* A component may act as a provider, which means it provides a service (receives calls).
* Or it may act as a consumer, which means it consumes services (sends calls).
* A component may have both roles.
However, not all the roles may be configured.
Here is a short presentation of some Petals components and their roles:
* The SOAP BC can be a provider.
In this case, the service-units are configured in provides mode.
* The SOAP BC can also act as a consumer.
In this case, the service-units are configured in consumes mode.
For a given service, the SOAP BC is either provider, or consumer. Never both.
* The BPEL SE is able to run BPEL processes. It is both a consumer and a provider. It exposes the BPEL process as a service, but it also calls the services referenced by the BPEL process.
However, the BPEL SE can only be configured in provides mode.
The consumes mode resides in the component implementation, and cannot be configured.
* The EIP SE acts somehow the same way the BPEL SE. It exposes a service, and the implementation of this service calls other services.
The difference with the BPEL SE is in the fact that consumed services are declared in the service-unit configuration. It means the EIP SE can be configured in both provides and consumes mode. Actually, it has to be both at the same time.
\\
The questions you have to think about when creating a component, are *whether your component is a service provider, a service consumer, or both*, and which roles are explicitly configurable and which ones are implicit. A role is *explicitly configurable* if the service-unit can configure the role.
{note}
Remember, service-units have a JBI descriptor (jbi.xml) file.
If this JBI descriptor has a *provides* section, then the component is configured as a provider for this service.
If it has a *consumes* section, then the component is configured as a consumer for this service.
{note}
{note}
If a service-unit declares a section for a role that is not supported by the component, it will not work.
Either an error will occur on deployment, or the invalid section will be skipped. The behavior depends on the component implementation, not on the CDK.
{note}
h1. Component's job
A component, in Petals, is responsible for:
* The deployment of a service-unit for this component.
* The management of the resources brought by service-units.
* The reception of messages targeting a service created from one of its service-units.
Hopefully, the deployment part is performed by the CDK (though it can be overridden).
When you create your component, as explained in the first part of this document, the only mandatory work is to complete the generated listeners. These (message) listeners define the behavior of the component when it receives messages.
And this is the point. *Messages do not reach directly the services. They are sent to components.*
The component receives the messages and must use the service-unit to compute and serve the request. This is also why we could say services are emulated. They completely depend on the component. The advantage of this, however, is to reuse the same basis code for all the services. You do not duplicate or reinvent the wheel when you create a service.
There are two kinds of message listeners to complete:
* *JBIListeners* listen to messages coming from inside the bus.
When you complete this class, you define the behavior of your component when it is called by another Petals service. Such a listener must be implemented for both a service engine and a binding-component.
* *ExternalListeners* react to external events, that is to say occurring outside the bus.
When you complete this class, you define the way your component handles these events and how they are propagated in Petals. Events can be a file dropped in a directory, or receive an external call through a given protocol.
Only binding components may implement an external listener.
Other classes have a default implementation in the CDK, but can be overridden if necessary.
These classes are discussed in the next pages.
h1. Message dispatching to message listeners
One important thing to know before going deeper about how to handle messages in your component, is the way Petals dispatches messages.
*External messages* (or events) are not accepted by the bus, but directly handled by the component, in the *ExternalListener class*.
There is no queue or mechanism provided by the CDK apart the AbstractExternalListener superclass.
Each *consumes* section in a service-unit configuration results in the creation of an ExternalListener.
For *internal messages*, that is to say messages coming from the bus, it all relies on the way the kernel dispatches the messages.
\\
For every component based on the CDK, the component JBI descriptor (the jbi.xml file in the component) inherits some fields from the CDK.
{code:lan=xml}
<petalsCDK:acceptor-pool-size>5</petalsCDK:acceptor-pool-size>
<petalsCDK:processor-pool-size>10</petalsCDK:processor-pool-size>
{code}
\\
The *acceptor pool size* defines the number of threads that can accept messages from the bus in concurrency.
Once a message is accepted by an acceptor, this message is added to a queue, waiting to by processed by a thread from the processor pool.
Since acceptors have few work to do, their number does not have to be high.
The *processor pool* is in charge of processing the messages added in the waiting queue.
Each thread from the processor pool owns a JBI listener instance.
For every message to process, the processor thread initializes the configuration in the JBI listener instance and calls the _onJBIMessage()_ method.
Messages are picked up by the processor pool in FIFO order.