Advanced topics and guidelines

This page gives additional and advanced information for component developers.

Contributors
No contributors found for: authors on selected page(s)

Digging into the CDK 5

This section provides additional information about the Petals Component Development Toolkit (CDK).

CDK parameters in component's JBI descriptors

These parameters are visible in the component JBI descriptor.
Component CDK parameters are among the ones you have to configure when you deploy a component into Petals.

  • jbi-listener-class-name is the name of the JBI listener class.
  • external-listener-class-name is the name of the external listener class.
  • acceptor-pool-size defines (partially) the size of the queue storing JBI messages before they are processed.
    In fact, the size of the queue has a minimal value and can grow up when required.
  • processor-pool-size defines the size of the pool of processors.
    You can set a large number if your JBI listener class does few things.
  • ignored-status indicates what status are ignored by the component.
    Typically, a component can receive a message to a call it made to another component (in this case, the component is in the role of a consumer).

The possible values are defined in the class IgnoreStatus:

  • DONE_AND_ERROR_IGNORED: all the messages with a done status or an error are ignored.
  • DONE_IGNORED: all the messages with a done status are ignored.
  • ERROR_IGNORED: all the messages with an error status are ignored.
  • NOTHING_IGNORED: no message is ignored.

DONE_AND_ERROR_IGNORED is generally used in early steps of development.
But it should be avoided in last steps of development and in production, as it may hide real problems.

CDK parameters in Service Unit's JBI descriptors

These parameters are visible in service-units' JBI descriptors.
CDK parameters of a service-unit are processed by the CDK and not directly by your component implementation.

WSDL interfaces and the CDK

The CDK provides some utility methods to work with WSDL interfaces.
A utility class related to WSDL is listed in the next chapter.

However, there are some features this utility class does not yet provide.
Indeed, the CDK cannot ensure that the called operation is in the service interface, or that the input message is valid with respect to the operation schema.

Therefore, working with WSDLs in component implementations is managed by hand.
In particular, the following elements are not performed by default by the CDK:

  • The exchange's called operation is defined in the WSDL.
  • The exchange's in message content is valid with respect to the operation XML schema.
  • The exchange returned by your component respects the operation XML schema (messages and faults).

Utility methods within the CDK

The CDK offers several utility methods, available in org.ow2.petals.component.framework.util.

Here is a partial list of these CDK utility classes:

  • org.ow2.petals.component.framework.util.ClassLoaderUtil
  • org.ow2.petals.component.framework.util.FileNamePatternUtil
  • org.ow2.petals.component.framework.util.IDGenerator
  • org.ow2.petals.component.framework.util.NormalizedMessageUtil
  • org.ow2.petals.component.framework.util.SourceUtilImpl
  • org.ow2.petals.component.framework.util.StringHelper
  • org.ow2.petals.component.framework.util.UtilFactory
  • org.ow2.petals.component.framework.util.WSDLUtilImpl
  • org.ow2.petals.component.framework.util.XMLUtil

You can refer to the Java doc of these classes for more details.

JBI listeners, the CDK and Exception handling

The problematic

The exception handling in JBI listeners is a little bit specific, compared to other classes.
This section explains how to determine the exceptions to process in your component, and those the CDK can handle itself.

A JBI listener receives an exchange, processes, completes and returns it. Always.
The content of the returned exchange depends on the Message Exchange Pattern (MEP).
The exception handling depends on the used MEP.

An example

Let's take the example of the InOnly MEP. With this MEP, you can only set a status on the exchange.
If the reception results in an exception, then an error should be set on the returned exchange.
You can do that in two ways:

  • If the qualified name of the exception starts with java., org.w3c. or org.xml., you can directly use
    exchange.setError( yourException );
  • Otherwise, you must create a MessagingException and copy the stack trace of the caught exception.
    This is achieved with:
    MessagingException msgException =  new MessagingException( ExceptionUtil.getExtendedMessage( yourException ));
    exchange.setError( msgException );
    


This difference in the exception handling is true for all the MEPs with the Error status.
For faults, things are different. A fault must be defined in the WSDL of the service-unit.
It can be set from the caught exception using

exchange.setFault( yourException );

Concretely

Eventually, to ease this thin handling, you should avoid to catch every exception, that is to say avoid:

try {
     // Process the received exchange
     ...

} catch( Exception e ) {
     // Log or something
     ...
}


Instead, process each possible exception separately:

try {
     // Process the received exchange
     ...

} catch( TransformerException e ) {
     // Log or something
     ...

} catch( MessagingException e ) {
     // Log or something
     ...

} catch( IOException e ) {
     // Log or something
     ...
}


What would happen if a NullPointerException is thrown during the processing?
Well, that's simple. The CDK will catch it and make the appropriate move.

If you wanted to catch every exception, you should test its name and take the appropriate decision then.
But it is already done in the CDK. Why would you reinvent the wheel?

Summary

If an exception handler updates the exchange, you must be careful to the exception type.
If the handler does not modify the exchange, do what you want in it.
If the exception handler sets an error on the exchange, it must act differently in function of the exception name.
java., org.w3c. and org.xml. exceptions can directly be set on the exchange as errors.
Other exceptions must be transformed in a MessagingException that will be set as an error on the exchange.

Working with drivers (shared libraries)

Shared Libraries are JBI artifacts that act as drivers.
As an example, the Petals EJB component can interact with several JEE servers. However, each JEE server may have different implementations or interfaces. This is in particular true for JNDI implementations. This is why to make the EJB SE work, you have to install and configure this SE with a shared library (SL) for the use JEE server. The shared library acts as a driver.

Shared Libraries simply embed Java libaries.
When a component is configured to use a SL, its class path will contain the libraries of this SL.
In practice, one component instance should be configured to work with only one shared library.

Using logs correctly in components

Components have access to a logger (java.util.logging.Logger) which is initially configured by the CDK.
This logger can be got by using the method AbstractComponent#getLogger().

In the different component classes, such as the message listeners or the service-unit manager, you can access the component and its logger.
However, you have to be careful about the way you log things.


For the moment, logs mix both messages and exceptions that occur in the component.
Unfortunately, it is not possible to proceed differently for the moment.
This should be changed in future versions of the CDK.

Logs format can also be configured, but it is not easy.
A potential good practice to make your log more readable would be to append the name of your component as a prefix to the first message.
The timestamp is logged by default.

Here are some good-practices to respect when you use logs in your component.


Log guideline 1
Make your message have less than 80 characters per line.

Logs may be displayed in a shell.
Therefore, this limitation of 80 characters should be respected as much as possible.

Line 1: a message of less than 80 characters.
Following lines (optional): a stack trace.


Log guideline 2
Check the log level before logging (This is highly recommended when logging contains expressions and time consuming things such as XML serialization!!!).

This will increase performances by avoiding useless or undesired logs.
Example:

Logger log = getLogger();
if( log.isLoggable( Level.INFO ))
    log.info( "your log message" );

Logger log = getLogger();
if( log.isLoggable( Level.DEBUG ))
    log.debug( "your log message" );


Log guideline 3
Use the severe() method only for events that should not have happened or for critical things.

This log method means an error occurred.
When an error occurs, an error should also be set on the exchange, and not just be logged as an error.


Log guideline 4
Do not hesitate to use the debug() method.

It will definitely help to maintain the component.


Log guideline 5
For every exchange your component processes, leave a debug message.


Log guideline 6
Use warning() only for caught exceptions, that do not result in a fault or an error.

Faults and errors are sent back.
It is useless to handle them twice.


Log guideline 7
Some exceptions should result in faults and errors, not in logs.

Faults are business faults. It means something went wrong with respect to the application mission.
Errors are technical errors, that arrive at the bus level.
Faults and errors must be set on the exchange.


Log guideline 8
Logs written during the processing of an exchange should start with the exchange ID.

Each exchange has an ID.
When processing an exchange, this ID should be the first thing to be logged, followed by a log message.
A typical place where this must be applied is in JBI listeners.


Log guideline 9
Logs written during the life cycle update of a service-unit should start with the service-unit name.

Each service-unit has a name.
Whe updating the life cycle of a service-unit, this name should be the first thing to be logged, followed by a log message.
A typical place where this must be applied is in service-unit managers.


Log guideline 10
Do not add timetamps, class names (or similar things) programmatically.

This is time consuming and can be configured with the logger configuration file if needed.

Last minute check list

So, that's it? You have created and implemented your component.
Maybe you also tested it. Before going further, check some little things.

Checking code quality


Guideline 1.a
Class organization is easy to explain and to understand for a developer having read this document.

Generally, components code is not huge.
But it can be very complicated. High cohesion and low coupling are essential in object-oriented programming.
Working on these aspects ease the maintenance of your component.


Guideline 1.b
The component implementation has been reviewed or checked with tools like FindBugs.

Sometimes, inattention errors or multiple code updates can lead to errors and problems at runtime.
Use IDE tools to check your code. Tools like FindBugs bring you a 1-click check and highlights programming errors.


Guideline 1.c
Overridden CDK classes were overridden for a valid reason.

If you override CDK classes, there must be a reason.
By default, only two classes need be completed: the JBI and the external listeners. Overriding CDK classes if it is not necessary increases the complexity of your component and its maintenance.


Guideline 1.d
Shared-libraries were used when possible.

Some components need additional libraries. Sometimes, several components need the same library.
Petals offers the possibility to share a same library in a common artifact called a shared-library. This requires the components to have a dependency to the same version of a library. The advantage is that it makes your component size lighter.

Checking XML schema


Guideline 2.a
Every element in the component XML schema is processed in the implementation.

One detail to take care of, is the coherence of the component XML schema with the parameters processed in the component implementation.


Guideline 2.b
Every element defined in the component XML schema is meaningful.

Another bad habit is to drag useless or temporary parameters in XML schema.
Modify configurations structures result in migration issues. Therefore, an effort brought on this part can avoid future troubles.


Guideline 2.c
Names from XML schema elements are meaningful. Composed names are separated by a '-' character.

Element names should have a clear meaning and not be ambiguous. Composed names are encouraged and should be separated with a '-' symbol.


Guideline 2.d
Names from XML schema elements are valid English words or known acronyms.

Element names should be valid English words or acronyms that anyone can understand (use a dictionary if necessary).


Guideline 2.e
XML schema should have a minimal number of complex types and use simple types as much as possible.

Keep your XML schema simple.
Prefer two simple fields with a composed name rather than a complex type with two simples fields.
In particular when the complex type cannot appear more than once.


Guideline 2.f
The CDK version in the pom.xml matches the one mentioned in the component XML schema.

Another usual error is related to the version of the CDK.
It sometimes happen that the CDK version specified in the pom.xml file does not match the version specified in the component XML schema.
If you use the version 5.0 in your pom.xml, then the CDK name space in the XML schema must be 5.

Checking coherence


Guideline 3.a
Your component provides a default WSDL in case where a service-unit does not have one.

Every configuration should provide a WSDL file.
However, in some cases, it happens that no WSDL is provided. In which case your component should provide one.


Guideline 3.b
Operations and MEPs, as processed in the component, are coherent with the WSDL content.

If your component checks operation names and/or message exchange patterns, you should make sure these treatments are compatible with the WSDL elements.
At least, in the one provided by your component.


Guideline 3.c
Faults, as processed in the component, are coherent with the WSDL content.

In the same way, if your component sets faults on exchanges, these faults should be declared in the WSDLs.
At least, in the one provided by your component.


Guideline 3.d
Returned messages, as built in the component, are coherent with the WSDL content.

If your component returns messages, the structure of these messages should be coherent with the WSDL operation messages.
At least, in the one provided by your component.


Guideline 3.e
All the actions performed on the exchange are compatible with the processed MEP.

Message exchange patterns define very strictly the actions you can do on an exchange.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.