BEA Logo BEA 

WebLogic Integration Release 2.1 Service Pack 1

  BEA Home  |  Events  |  Solutions  |  Partners  |  Products  |  Services  |  Download  |  Developer Center  |  WebSUPPORT

 

   WebLogic Integration Doc Home   |   AI Topics   |   Developing Adapters   |   Previous Topic   |   Next Topic   |   Contents   |   Index   |   View as PDF

Developing an Event Adapter

 

Event adapters propagate information from an EIS into the WebLogic Integration environment. These types of adapters can be described as publishers of information. All WebLogic Integration event adapters perform the following three functions:

WebLogic Integration implements the aspects of these three functions that are generic across all event adapters. You only need to focus on the EIS specific aspects of your adapter.

This section contains information on the following subjects:

 


Event Adapters in the Run-time Environment

The behavior of an Event in the run-time environment is depicted in Figure 7-1.


 

Figure 7-1 Event Adapters in the Run-time Environment


 


 


 

 


The Flow of Events

Figure 7-2 outlines the steps required to develop an Event Adapter.

Figure 7-2 Event Adapter Flow of Events


 

 


Step 1: Development Considerations

These are the items you need to consider before commencing with event adapter development. The Adapter Setup Worksheet will provide much of this information. See Adapter Setup Worksheet.

  1. Determine the event types.

    You need to identify what exactly comprises the event:

  2. Determine the data extraction method.

    Next, you need to decide which method of data extraction will be used:

    Use the pull method when your adapter needs to poll the EIS to determine a change-of-state. Use a push event when you want to implement an event generation that works more like a publish/subscribe model.

 


Step 2: Configuring the Development Environment

This step describes the processes you must complete to prepare your computer for adapter development.

Step 2a: Set up the File Structure

The file structure necessary to build an event adapter is the same as that required for service adapters. See Step 2a: Set Up the File Structure in Developing a Service Adapter.

Step 2b: Assign the Adapter Logical Name

Next, you need to assign the adapter's logical name. By convention, this name is comprised of the vendor name, the type of EIS connected to the adapter, and the version number of the EIS and is expressed as vendor_EIS-type_EIS version. For example, BEA_WLS_SAMPLE_ADK, where:

Step 2c: Set Up the Build Process

WebLogic Integration employs a build process based upon Ant, a 100% pure Java-based build tool. For more information on Ant, please see Ant-Based Build Process. For more information on using Ant, go to:

http://jakarta.apache.org/ant/index.html

The sample adapter shipped with WebLogic Integration (located in WLI_HOME/adapters/sample) contains the file build.xml (located in WLI_HOME/adapters/sample/project). This is the Ant build file for the sample adapter. It contains the tasks needed to build a J2EE-compliant adapter. Running the GenerateAdapterTemplate utility to clone a development tree for your adapter creates a build.xml file specifically for that adapter. This will free you from having to customize the sample build.xml and will ensure that the code is correct. For information on using the GenerateAdapterTemplate utility, see Creating a Custom Development Environment.

For more information on the build process, see Step 2c: Setting Up the Build Process, in Developing a Service Adapter.

Step 2d: Create the Message Bundle

Any message destined for the end-user should be placed in a message bundle. The message bundle is simply a .properties text file that contains key=value pairs that allow you to internationalize messages. When a locale and national language are specified at run time, the contents of the message is interpreted, based upon the key=value pair, and the message is presented to the user in the correct language for his or her locale.

For instructions on creating a message bundle, please refer to the JavaSoft tutorial on internationalization at:

http://java.sun.com/docs/books/tutorial/i18n/index.html

Step 2e: Configure Logging

The final step in configuring your development environment is to configure logging. Before you begin, read more about logging in Concepts. Logging is accomplished using the logging tool Log4j, developed as part of the Apache Jakarta project. For information on using this tool, please see Using the Logging Toolkit.

Create an Event Generation Logging Category

For event adapters, you will need to create a logging category specifically for event generation (for more information on logging categories, see Message Categories). Edit the logging configuration file for the specific adapter (adapter_logical_name.xml in WLI_HOME/adapters/ADAPTER/src/ where ADAPTER is the adapter you are building) by adding the code in Listing 7-1.

Listing 7-1 Sample Code Creating an Event Generation Logging Category

<category name='BEA_WLS_SAMPLE_ADK.EventGenerator' class='com.bea.
logging.LogCategory'>
</category>

You must replace BEA_WLS_SAMPLE_ADK with your adapter logical name.

By not setting any specific parameters for this category, it will inherit all of the parent category's property settings. In this example, the parent category is BEA_WLS_SAMPLE_ADK.

 


Step 3: Implementing the Adapter

Implementing an event adapter is a two-step process. You need to:

This section shows you how to accomplish these tasks.

Step 3a: Create an Event Generator

Event generation provides an adapter with a mechanism to either receive notification from an EIS or poll an EIS for the specific occurrence of an event. The event generation provided by the WebLogic Integration engine is very powerful in that a single event generator can support multiple types of events. An event type is defined by the configuration properties for an event.

Typically event properties are defined by the properties associated with an event at design time. When configuring an event adapter, the adapter may have one or more Web pages that it uses to collect event properties. These properties are saved with the application view descriptor and passed back to the event at run time. The WebLogic Integration engine uses the properties and the source application view to determine how to route back to the listeners. For instance, two separate deployments of the same event generator with identical properties will result in only a single IEventDefinition being created by the WebLogic Integration engine. Whereas, a single IEventDefinition will be created for every deployment of a single event adapter where the properties are different. It is the responsibility of the event generator to determine which IEventDefinition to use in the routing process. This is typically done based on property values and specific event occurrences.

The IEventDefinition objects are used by your implementation of the event generator to route specific events back to their listener. As discussed before, the WebLogic Integration engine will create IEventDefinition objects for deployed application views containing events. You will use the IEventDefinition objects to extract specific properties regarding the deployment of an application view, or to access schema and routing objects. You need to employ these attributes when routing an event.

How the Data Extraction Mechanism is Implemented

WebLogic Integration supports two mechanisms for data extraction:

The "Pull" Mechanism

The mechanism relies on a polling technique to determine if an event has taken place. To implement a Pull scenario you must derive your event generator from the AbstractPullEventGenerator in the com.bea.adapter.event package.

Note: adk-eventgenerator.jar file must be included in your .war make file. adk-eventgenerator.jar contains the ADK base classes required to implement an event generator.

The ADK supplies several abstract methods in the AbstractPullEventGenerator that you must override in your implementation. These methods are described in Table 7-1.

Table 7-1 AbstractPullEventGenerator Methods

Method

Description

postEvents()

The postEvents() method is called from the run method in the AbstractPullEventGenerator at an interval that is determined by the Event Router configuration files. The postEvents() method is where you add any polling and routing code. The postEvents()method is the control method for the rest of your event generation, message transformation, and routing code.

setupNewTypes()

The setupNewTypes() method is used to preprocess any IEventDefinition object being deployed. Only valid new IEventDefinition objects are passed to the setupNewTypes() method.

removeDeadTypes()

The removeDeadTypes() method is used to handle any clean up required for IEventDefinition objects that are being un-deployed. The WebLogic Integration engine calls removeDeadTypes() when application views with associated events are being un-deployed.

doInit()

doInit() is called while the event generator is being constructed. During the initialization process the event generator can use pre-defined configuration values to setup the necessary state or connections for the event generation process.

doCleanUpOnQuit()

doCleanUpOnQuit() is called before ending the thread driving the event generation process. Use this method to free any resources allocated by your event generation process.


 

The "Push" Mechanism

The Push scenario uses notification to trigger the routing of an event. To implement the Push scenario you must derive your event generator from the AbstractPushEventGenerator class in the com.bea.adapter.event package. There are several other supporting classes included in the event package. These classes are described in Table 7-2.

Note: adk-eventgenerator.jar must be included in your .war make file. adk-eventgenerator.jar contains the WebLogic Integration base classes required to implement an event generator.

Table 7-2 AbstractPushEventGenerator Classes

Class

Description

AbstractPushEventGenerator

The AbstractPushEventGenerator class contains the same abstract and concrete methods as the AbstractPullEventGenerator. These methods are intended to be used in the same manner as the AbstractPullEventGenerator implementation. See Table 7-1 for a list of these methods and responsibilities.

IPushHandler

The IPushHandler is an interface provided primarily to abstract the generation of an event from the routing of an event; however, it is not required to implement a Push scenario. The IPushHandler is intended to be tightly coupled with the PushEventGenerator. It is the PushEventGenerator that will initialize, subscribe, and clean up the PushHandler implementation. The IPushHandler provides a simple interface to abstract the generation logic. The interface provides methods to initialize, subscribe to Push events, and clean up resources.

PushEvent

The PushEvent is an event object derived from java.util.EventObject. The PushEvent is intended to wrap an EIS notification and be sent to any IPushEventListener objects.

EventMetaData

The EventMetaData class is intended to wrap any data necessary for event generation. The EventMetaData class is passed to the IPushHandler on initialization. To see a sample usage for these objects refer to the e-mail sample code.


 

How the Event Generator is Implemented

An event generator implementation typically follows this flow of control:

The following is a series of code samples that implement an event generator with a Pull mechanism.

Listing 7-2 shows the class declaration for the sample adapter's (Pull) event generator.

Note: The AbstractPullEventGenerator implements the Runnable interface, which enables it to run on its own thread.

Listing 7-2 Sample Code Implementing a Pull Data Extraction Mechanism

public class EventGenerator
extends AbstractPullEventGenerator

Sample EventGenerator

Listing 7-3 shows the simple constructor for an event generator. You must invoke the parent's constructor so that the parent's members get initialized correctly. The listing then shows how the doInit() method receives configuration information from the map variable and validates the parameters. The sample contains any parameters associated with the event generator at design time.

Listing 7-3 Sample Constructor for an EventGenerator

public EventGenerator()
{
super();
}
protected void doInit(Map map)
throws java.lang.Exception
{
ILogger logger = getLogger();
    m_strUserName = (String)map.get("UserName");
if (m_strUserName == null || m_strUserName.length() == 0
{
String strErrorMsg =
logger.getI18NMessage("event_generator_no_UserName");
logger.error(strErrorMsg);
throw new IllegalStateException(strErrorMsg);
}
m_strPassword = (String)map.get("Password");
if (m_strPassword == null || m_strPassword.length() == 0)
{
String strErrorMsg = logger.getI18NMessage
("event_generator_no_Password");
logger.error(strErrorMsg);
throw new IllegalStateException(strErrorMsg);
}

postEvents() is called from the run method of our parent class, as shown in Listing 7-4. This method polls the EIS to determine when a new event occurs. This method will be invoked at a fixed interval, which is defined in the web.xml file for the event router.

Listing 7-4 Sample Code Implementing postEvents() Method

*/  protected void postEvents(IEventRouter router)
throws java.lang.Exception
{
    ILogger logger = getLogger();
    // TODO: a real adapter would need to call into the EIS to
// determine ifany new events occured since the last time
// this method was invoked. For the sake of example, we'll just
// post a single event every time this method gets invoked...
// event data will be the current time on the
// The system formatted according to the event definition...
// we'll look for several event types...
    Iterator eventTypesIterator = getEventTypes();
if (eventTypesIterator.hasNext())
    {
do
{
       // The event router is still interested in this type of event
       IEventDefinition eventDef = (IEventDefinition)
eventTypesIterator.next();
logger.debug("Generating event for " + eventDef.getName());
       // Create a default event (just blank/default data)
       IEvent event = eventDef.createDefaultEvent();
       // Get the format for the event
      java.util.Map eventPropertyMap = eventDef.
getPropertySet();
String strFormat = (String)eventPropertyMap.get
("Format");
if( logger.isDebugEnabled() )
logger.debug("Format for event type '"+eventDef.
getName()+"' is '"+strFormat+"'");
java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat(strFormat);
IDocument payload = event.getPayload();
payload.setStringInFirst("/SystemTime", sdf.format(new
Date()));
        // let's log an audit message for this...
        try
{
logger.audit(toString() + ": postEvents >>> posting event
["+payload.toXML()+"] to router");
}
          catch (Exception exc)
        {
logger.warn(exc);
}
          // This call actually posts the event to the IEventRouter        
        router.postEvent(event);
} while (eventTypesIterator.hasNext());
}
    }// end of postEvents 

A real adapter would need to call into the EIS to determine if any new events occurred since the last time this method was invoked. You can see a concrete example of this in the DBMS adapter included with the ADK. Refer to the postEvent() method in EventGenerator.java, which is in:

WLI_HOME/adapters/dbms/src/com/bea/adapter/dbms/event/

Adding New Event Types

setupNewTypes() gets called during refresh to handle any new event types. This allows us to perform any setup we need to handle a new type. The parent class has already sanity-checked the listOfNewTypes() and logged it; so you don't need to do that here.

Listing 7-5 Sample Code Showing the Template for setupNewTypes()

protected void setupNewTypes(java.util.List listOfNewTypes)
{
Iterator iter = listOfNewTypes.iterator();
while (iter.hasNext())
{
IEventDefinition eventType = (IEventDefinition)iter.next();
}
}

Removing Event Types for Application Views that are Undeployed

removeDeadTypes() is called during refresh to handle any event types for application views that have been undeployed. You will need to perform a cleanup process to ensure that this event type is no longer handled, such as closing resources needed to handle this specific event type. Listing 7-6 shows how removeDeadTypes() is implemented.

Listing 7-6 Sample Code Showing the Template for removeDeadTypes()

protected void removeDeadTypes(java.util.List listOfDeadTypes)
{
Iterator iter = listOfDeadTypes.iterator();
while (iter.hasNext())
{
IEventDefinition eventType = (IEventDefinition)iter.next();

Removing Resources

Finally, doCleanUpOnQuit() gets called when the event generator is shutting down, This method removes any resources allocated during event processing. The sample adapter stubs in this method. The template for implementing this method is shown in Listing 7-7.

Listing 7-7 Sample Code Showing doCleanUpOnQuit() Method Call

protected void doCleanUpOnQuit()
throws java.lang.Exception
{
ILogger logger = getLogger();
logger.debug(this.toString() + ": doCleanUpOnQuit");
}
}

Step 3b: Implement the Data Transformation Method

Data transformation is the process of taking data from the EIS and transforming it into an XML schema that can be read by the application server. For each event, a schema will define what the XML output looks like. This is accomplished by using the SOM and IDocument class libraries. The following code listings show the data transformation sequence:

SOMSchema schema = new SOMSchema();
SOMElement root = new SOMElement("SENDINPUT");
SOMComplexType mailType = new SOMComplexType();
root.setType(mailType);
SOMSequence sequence = mailType.addSequence();
SOMElement to = new SOMElement("TO");
to.setMinOccurs("1");
to.setMaxOccurs("unbounded");
sequence.add(to);
SOMElement from = new SOMElement("FROM");
from.setMinOccurs("1");
from.setMaxOccurs("1");
sequence.add(from);
SOMElement cc = new SOMElement("CC");
cc.setMinOccurs("1");
cc.setMaxOccurs("unbounded");
sequence.add(cc);
SOMElement bcc = new SOMElement("BCC");
bcc.setMinOccurs("1");
bcc.setMaxOccurs("unbounded");
sequence.add(bcc);
SOMElement subject = new SOMElement("SUBJECT");
subject.setMinOccurs("1");
subject.setMaxOccurs("1");
sequence.add(bcc);
SOMElement body = new SOMElement("BODY");
if (template == null)
{ body.setMinOccurs("1");
body.setMaxOccurs("1");
}else
{ Iterator iter = template.getTags();
if (iter.hasNext())
{ SOMComplexType bodyComplex = new SOMComplexType();
body.setType(bodyComplex);
SOMAll all = new SOMAll();
while (iter.hasNext())
{ SOMElement eNew = new SOMElement((String)iter.next());
all.add(eNew);
}//endwhile
bodyComplex.setGroup(all);
}//endif
}//endif
sequence.add(body);
schema.addElement(root);

Listing 7-9 XML Schema Created by Code in Listing 7-8

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="SENDINPUT">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="TO" maxOccurs="unbounded"
type="xsd: string"/>
<xsd:element name="FROM" type="xsd:string"/>
<xsd:element name="CC" maxOccurs="unbounded"
type="xsd:string"/>
<xsd:element name="BCC" maxOccurs=
"unbounded" type= "xsd:string"/>
<xsd:element name="BCC" maxOccurs="unbounded"
type="xsd:string"/>
<xsd:element name="BODY" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

Listing 7-10 Valid XML Document Created by Schema in Listing 7-9

</xsd:schema>
<?xml version="1.0"?>
<!DOCTYPE SENDINPUT>
<SENDINPUT>
<TO/>
<FROM/>
<CC/>
<BCC/>
<BCC/>
<BODY/>
</SENDINPUT> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

 


Step 4: Testing the Adapter

You can test the adapter by using the adapter test harness provided with WebLogic Integration. See Step 5: Testing the Adapter, in Developing a Service Adapter,for a complete description of this tool and instructions for using it.

 


Step 5. Deploying the Adapter

After rebuilding the new adapter, deploy it into WebLogic Integration. You can deploy an adapter either manually or from the WebLogic Server Console. See Deploying Adapters, for complete information.

 

back to top previous page next page