BEA Logo BEA WebLogic Application Integration 2.0

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

 

   Application Integration Documentation   |   Application Integration Adapter Development Guide   |   Previous Topic   |   Next Topic   |   Contents   |   Index

Developing an Event Adapter

 

Event adapters propagate information from an EIS into the Application Integration environment. These types of adapters can be described as publishers of information. On the Application Integration integration platform, all event adapters perform the following three functions:

The Application 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 Runtime Environment

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


 

Figure 7-1 Event Adapters in the Runtime 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:

 


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

The Application 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, see http://jakarta.apache.org/ant/index.html.

The sample adapter shipped with BEA WebLogic Application Integration (located in <WLAI_HOME>\dev\bin\ sample) contains the file build.xml. 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 runtime, 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 The ADK 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 the /src/ directory for that adapter) by adding the following line:

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

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

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 EventGenerator

The event generation provides 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 BEA WebLogic Application Integration engine is very powerful in that a single EventGenerator 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 designtime. 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 runtime. The Application 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 EventGenerator with identical properties will result in only a single IEventDefinition being created by the Application 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 EventGenerator 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 EventGenerator to route specific events back to their listener. As discussed before, the Application 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

Application 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 EventGenerator 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 EventGenerator.

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 Application Integration engine calls removeDeadTypes when application views with associated events are being un-deployed.

doInit()

doInit() is called while the EventGenerator is being constructed. During the initialization process the EventGenerator 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 EventGenerator 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 Application Integration base classes required to implement an EventGenerator.

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 email sample code.

How the EventGenerator is Implemented

An EventGenerator implementation typically follows this flow of control:

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

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

Note: The AbstractPullEventGenerator implements a "run-able" interface; that is, it's a 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 EventGenerator. 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 EventGenerator at designtime.

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

Listing 7-4 Sample Code Implementation of the 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...The
    // event data will be the current time on 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 DbmsEventGeneratorWorker.java, which is in:

<WLAI_HOME>dev/dbms/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 EventGenerator 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 Document class libraries. The following code listings show the data transformation sequence:

 


Step 4. Deploying the Adapter

To deploy the event adapter, you need to deploy the EventGenerator on a J2EE servlet engine outside of the BEA WebLogic Application Integration engine. To do this, you need to bundle the EventGenerator as a web application, WEB-INF/web.xml. Rather than create this file from scratch, we recommend that you use the GenerateAdapterTemplate utility to clone and customize a development environment for your adapter. Running this utility will modify the web.xml file in the sample adapter for use with the adapter you are developing. For more information on using GenerateAdapterTemplate, see Creating a Custom Development Environment.

Add EventRouterServlet to .war File

The EventRouter is a .war file used to deploy your EventGenerator and is required for any adapter supporting events. It will be the URL that you will use in the design-time interface to deploy the event adapter. Because it is a .war file, it requires an associated web.xml file for deployment.

The EventRouterServlet is responsible for initializing and starting the Application Integration event process. The web.xml file contains initialization parameters for the EventRouterServlet, some of which are shown in Table 7-11.

Listing 7-11 EventRouterServlet Element of web.xml

<servlet>
<servlet-name>EventRouterServlet</servlet-name>
<description>Provides access to event router within WLAI</description>
<servlet-class>com.bea.wlai.event.EventRouterServlet</servlet-class>
<!-- Or jsp-file -->
<init-param>
<param-name>eventGeneratorClassName</param-name>
<param-value>email.event.PullEventGenerator</param-value>
<description>The fully qualified class name of the IEventGenerator implementation class</description>
</init-param>
<init-param>
<param-name>wlsUserID</param-name>
<param-value>system</param-value>
<description>The user id on the WLAI server that this event router will talk to to get schemas, etc.</description>
</init-param>
<init-param>
<param-name>wlsPassword</param-name>
<param-value>weblogic</param-value>
<description>The password for wlsUserID</description>
</init-param>
.
.
.
<load-on-startup>1</load-on-startup>
</servlet>

You need to assign values to several initialization parameters prior to creating the EventRouter. These parameters are described in Table 7-3.

Table 7-3 Event Router Initialization Parameters


 
 

Parameter

Description

Value

EventRouterServlet

Class name for the event router servlet. Do not change this value.

com.bea.wlai.event.EventRouter- Servlet

eventGeneratorClassName

Class name for the EventGenerator. This is the fully qualified class name for your EventGenerator.

email.event.PushEventGenerator

wlsUserID

User ID for Weblogic Server. This user ID will be used to connect to weblogic in order to retrieve the Schema's associated with this event adapter.

system

wlsPassword

Password for Weblogic Server.

weblogic

userName

This is the user name for the EIS the EventGenerator will be connecting to.

username

password

Password for the EIS connection.

password

connectionURL

URL describing the location for the EIS

server.domain.com

RootLogContext

Base log context. If no additional log context is specified this will be the context for the EventGenerator.

adapterLogicName

AdditionalLogContext

Used to further sub-categorize the logging messages. The additional log context can be used to identify logging messages from a specific context. The AdditionalLogContext is used in conjunction with the RootLogContext to identify a new Log Context; that is:

(root.additionalLog- Context)

sub-category

LogConfigFile

The log configuration file for this adapter. The log configuration file contains an XML document with setup parameters for the log utility.

filename.xml

MessageBundleBase

Base name for message bundles. Base name and language code are used to identify a specific instance of a message bundle.

filename

LanguageCode

Preferred language code for log messages

en

CountryCode

Preferred country code for log messages.

US

sleepCount

Count between iterations. This is the time between calls to the postEvents method for the PullEventGenerator. This count is given in milliseconds.

5000


 

The web.xml file also contains servlet directives and security constraints. Refer to the WebLogic documentation for a description of these attributes.

Create the EventRouter .war file

To make the EventRouter .war file you must include the following .jar files in your .war file:

Also add any other .jar file upon which your EventGenerator is dependent. These are specified in the <eventrouter> target in the build.xml file, as shown in Listing 7-12.

Listing 7-12 Adding .jar Files to the eventrouter Target of build.xml

<target name='eventrouter_war' depends='jar,eventrouter_jar'>
   <delete file='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'/>
   <delete dir='${SRC_DIR}/eventrouter/WEB-INF/lib'/>
   <war warfile='${LIB_DIR}/${EVENTROUTER_WAR_FILE} 'webxml='${SRC_DIR}/eventrouter/WEB-INF/web.xml'>
     <fileset dir='${PROJECT_DIR}' includes='version_info.xml'/>
     <fileset dir='${SRC_DIR}/eventrouter' excludes='WEB-INF/ web.xml'/>
       <lib dir='${LIB_DIR}' includes='${JAR_FILE}, ${EVENTROUTER_JAR_FILE}'/>
       <lib dir='${WLAI_LIB_DIR}' includes='adk.jar,adk- eventgenerator.jar,bea.jar,logtoolkit.jar,wlai-common.jar,wlai-ejb-client.jar,wlai-eventrouter.jar,wlai-servlet-client.jar,xmltoolkit.jar'/>
     <lib dir='${RESOURCE_DIR}/log4j' includes='log4j.jar'/>
   </war>
</target>

 


Step 5: Testing the Adapter

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

 

back to top previous page next page