Listeners and Listener Notifications
Overview
Listeners and listener notifications work together to create a much more powerful model than polling notifications in detecting and processing events in the adapter resource.
- Integration Server instantiates and initializes a polling notification object with settings from the node.
- Integration Server then invokes the polling notification object by calling its runNotification method on a periodic basis.
- The polling notification object must retrieve a connection and use it to determine if publishable events have occurred in the adapter resource.
- If an event has occurred, the polling notification object must generate a WmRecord object conforming to the output signature of the polling notification node, and publish it by calling the doNotify method.
- The polling notification object then goes to sleep until the next time it is invoked.
- If the overlap option is enabled in the notification schedule, a second object may be instantiated while the previous instance is still processing events detected in a previous invocation. The second instance retrieves another connection, and interrogates the resource again. This model can make state management significantly more difficult.
- A listener object is instantiated and is given a connection when the user of the adapter enables the associated node.
- The listener object remains active with the same connection to monitor the resource activity until it is disabled either explicitly or by disabling the containing package, the adapter, the connection, or Integration Server.
- When the listener detects a publishable event in the resource, it passes an object back to Integration Server.
-
Integration Server interrogates a configured list of listener notifications
associated with the listener node until it finds a listener notification node
that can process the event.
Integration Server accomplishes this by calling the listener notification's
supports method. The first notification to return
truefrom this call is invoked using its runNotification method. This behavior is similar to the polling notification where any data about the event that was provided by the listener is passed as an argument to the runNotification method.
Synchronous and Asynchronous Listener Notifications
The ADK includes both, synchronous and asynchronous processing model.
- An asynchronous listener notification publishes a document.
- The notification object's runNotification method calls doNotify method.
- The users of the adapter may process the document's data as needed. For example, the users of the adapter can create an Integration Server trigger that receives the document and executes an Integration Server flow service or a Java service.
- Asynchronous listener notifications do not support session handling. When a synchronous listener notification calls an Integration Server service that needs that needs information contained in the session data, it may appear to work because asynchronous listener notifications themselves do not execute a service. Instead, an Integration Server trigger, which supports session handling, is used to receive the document and execute an Integration Server flow service or a Java service.
- A synchronous listener notification does not publish a document.
- The notification object's runNotification method calls invokeService.
- The users of the adapter cannot process the document's data as the processing is done in the invokeService method.
- Synchronous listener notifications do not support session handling. When a synchronous listener notification calls an Integration Server service that needs information contained in the session data, that service can fail.
Implementing Listeners and Listener Notifications
The implementation of a listener and listener notification is similar to the implementation of an adapter connection. Each implementation includes a Java class extending an ADK base class, and a namespace node in which design-time configuration data is stored. In the Java class, the metadata model for listeners and listener notification is nearly identical to that of adapter connections. The configuration pages are built from the listeners metadata. For more information, see Metadata Model for Connection
Listener Classes
The following figure shows the classes provided by the ADK to support listener notifications. It also shows the com.wm.adk.notification.WmConnectedListener implementation class SimpleListener.
Create a listener class by extending com.wm.adk.notification.WmConnectedListener base class. You must override the following base class methods in your WmConnectedListener implementation class:
| Method | Description |
|---|---|
| fillWmDescriptor | Controls how metadata parameters are displayed, and defines rules for data entry for the listener's metadata parameters. From the standpoint of the adapter implementation, the model is identical to the connection model. |
| listenerStartup | Initializes the listener. This method is called during the listener startup sequence as well as during the recovery procedure after an AdapterConnectionException is encountered. |
| waitForData | Monitors the adapter resource. This method returns data that is analyzed by the support method of associated listener notifications. For more details, see Listener and Listener Notification Interactions. |
| listenerShutdown | Cleans up listener resources. This method
is called during the listener shutdown sequence.
Note: You may optionally override the
processNotificationResults method to allow
the listener implementation class to post-process listener notification
results. For an example of using both methods, see
Implementing Listener Methods.
|
In addition, the implementation class may override the following optional methods:
| Method | Description |
|---|---|
| restrictNotificationTypes | Allows the listener implementation class to restrict the notification classes it supports by explicitly identifying them. For more information, see Restricting Listeners to Register Specified Notification Templates. |
| shutdownCallBack | Invoked on a thread separate from the listener's thread, this method allows the listener's waitForData loop to be gracefully interrupted prior to a normal shutdown. |
Asynchronous Listener Notification Classes
The following figure shows the classes provided by the ADK to support asynchronous listener notifications.
Create an asynchronous listener notification class by extending the base class com.wm.adk.notification.WmAsyncListenerNotification, as shown by the SessionLogListenerNotification class in the figure. As previously mentioned, the implementation of an asynchronous listener notification is similar to a polling notification. The key differences occur in the following methods:
| Method | Description |
|---|---|
| supports | Determines whether the notification can
process the object returned by the listener's
waitForData method.
|
| runNotification | If the
supports method returns
true, the
Integration Server calls the following
runNotification method to process the data.
The implementation of this method must
Note: The
NotificationEvent simply wraps the data
object returned from the listener's
waitForData method.
|
For more information about alternative method of managing resource domains, see to-appx_alt_approaches_metadata.html#A52135.
Synchronous Listener Notification Classes
The following figure shows the classes provided by the ADK to support synchronous listener notifications.
Create a synchronous listener notification class by extending com.wm.adk.notification.WmSyncListenerNotification base class. The examples in this section do not implement a synchronous notification, so the figure in this section only shows a placeholder class. A synchronous notification calls the WmSynchronousNotification.invokeService method, passing it a WmRecord object containing data consistent with the output signature of the notification node.
Synchronous listener notifications are expected to define both an input and output signature. The terms input and output are relative to the notification. The output signature specifies the format of the data that the notification places on the pipeline prior to invoking the service associated with the synchronous notification. The input signature describes the data that the notification expects to find on the pipeline after the invoked service has completed processing.
The service invoked by WmSynchronousNotification.invokeService method is specified at design time in the notification node data. When this service is invoked, it executes on a separate thread (and therefore in a different transactional context) from the listener. When the invoked service completes, Integration Server extracts the data on the pipeline that is identified in the notification node's input signature and delivers that data as a WmRecord wrapped in the SyncNotificationResults object returned by invokeService method.
Listener and Listener Notification Interactions
The design time interactions for listeners and listener notifications are essentially the same as the interactions for connections and polling notifications, as described in Connection Class Interactions and Polling Notification Interactions, respectively. This section describes the runtime behavior of listeners and their associated notifications.
The figures that illustrate listener runtime interactions with synchronous and asynchronous notifications in this section show the runtime lifecycle of a listener from the time it is started until the time it is shut down. The difference between the two diagrams begins at step 3.3, when the server calls the runNotification method of the notification. Do not interpret the separation of these diagrams to imply that a given listener can use only synchronous or asynchronous notifications. On the contrary, step 3 represents a loop that repeats continuously while the listener is running, and any iteration of the loop may follow either course depending on the class type of the notification that indicates support for the notification event.
- Retrieves a connection from the associated connection node.
- Calls the listener's
listenerStartup method. This
listenerStartup method performs the following:
- Access the connection using the retrieveConnection method from the base class.
- Initialization required prior to the first waitForData call.
- Disables the listener if an exception is thrown by the listenerStartup method, or if retrieving connection by Integration Server fails.
After initialization of the listener is complete, Integration Server initiates the notification event-processing loop represented by step 3 of the interaction diagrams. This loop continues until one of the following events occurs:
- The user of the adapter disables the listener in the adapter's administrative interface.
- Package containing the listener is
disabled (or reloaded).
Note: Disable the listener package before you disable the adapter package.
- Integration Server is shut down.
- Listener or a listener notification throws an AdapterConnectionException. This causes the listener to shut down and to attempt to restart with a new connection.
- Listener throws an AdapterException or a RunTimeException.
The following figure shows the listener runtime interactions with synchronous notification
- Interrogates the adapter resource to determine whether an event has occurred that the listener should report.
- If the event has not occurred, the listener should return a
nullobject.The model assumes that the listener implements some form of blocking read operation with a time component that allows it to return periodically, even if no notification event has occurred. The adapter developer must provide appropriate means of configuring the timing characteristics of this blocked read, such as through a metadata parameter on either the listener or the connection.
- If the event has occurred, the listener's
waitForData method returns a non-null object,
Integration Server
iterates through the listener notifications that are currently registered with
the listener, which must be enabled and registered.
- The data object received from waitForData method is passed to the supports method (step 3.2) for each notification.
- For the first notification that returns
truefrom its supports method:- Integration Server calls the runNotification method passing the data object wrapped as a NotificationEvent (step 3.3).
- Integration Server calls the listener's processNotificationResults method with a NotificationResults as input object returned from runNotification (step 3.4).
- If no notification returned
true from the
supports method, or if
runNotification threw an exception other than
an
AdapterConnectionException, then
processNotificationResults is called with a
nullargument.
- Interpreting the NotificationEvent object.
- Building a
WmRecord object consistent with its output
signature.
This may or may not require additional interaction with the resource. If it does, a connection is made available for that purpose through the retrieveConnection method, which is the same connection used by the listener.
- An asynchronous notification passes this WmRecord object to the doNotify method (step 3.3.1).
- The doNotify method publishes the document in the same way it does for polling notifications.
- An asynchronous notification must instantiate a new AsynchNotificationResults object (step 3.3.3), including the notification name, which can be retrieved from the base class nodeName method (step 3.3.2).
- A synchronous notification's implementation of runNotification method passes its output, WmRecord object to invokeService method instead of doNotify method (step 3.3.1).
- The service called by invokeService method is specified in the configuration of the synchronous listener notification node. The service is invoked on a separate thread and transaction context.
- The results of the service invocation are returned to invokeService method as a SynchronousNotificationResults object.
- The results are then available to be interrogated by the notification and/or the listener, using the methods provided by that class.
Listener Implementation
The example listener implementation provided in this section shows the basic mechanics of a simple listener that can be used to monitor activity on an Integration Server log file. The example listener notification parses a session log entry and produces asynchronous notifications.
The tasks for implementing a listener are as follows:
- Defining a WmConnectedListener Implementation Class
- Specifying Configuration Metadata for Listeners
- Implementing Listener Methods
- Creating getReader Method in the WmManagedConnection Implementation Class
- Updating the Resource Bundle
- Registering Listeners in the WmAdapter Implementation Class
- Compiling the Adapter
- Reloading Adapter
- Refreshing the Designer cache
- Configuring a Listener
Example Listener Class
package com.wm.MyAdapter.listeners;
import com.wm.adk.error.AdapterException;
import com.wm.adk.metadata.WmDescriptor;
import com.wm.adk.notification.WmConnectedListener;
import com.wm.adk.notification.NotificationResults;
import java.io.FileReader;
import java.util.Locale;
import javax.resource.ResourceException;
import com.wm.MyAdapter.MyAdapter;
import com.wm.MyAdapter.connections.SimpleConnection;
public class SimpleListener extends WmConnectedListener
{
public static final String FILE_NAME_PARM = "fileName";
private String _fileName = null;
public void setFileName(String val){_fileName = val;}
private FileReader _reader = null;
private StringBuffer workingBuffer = new StringBuffer();
private String _lastDataObject = null;
public void fillWmDescriptor(WmDescriptor descriptor, Locale locale)
throws ResourceException
{
descriptor.setRequired(FILE_NAME_PARM);
descriptor.setDescriptions(
MyAdapter.getInstance().getAdapterResourceBundleManager(), locale);
}
public void listenerStartup() throws ResourceException
{
try
{
//_reader = ((SimpleConnection)retrieveConnection()).getReader();
_reader = ((SimpleConnection)retrieveConnection()).getReader(_fileName);
while(_reader.ready())
{
_reader.read(); // move to the end of the stream
}
}
catch (Throwable t)
{
throw MyAdapter.getInstance().createAdapterException(100,t);
}
}
public Object waitForData() throws ResourceException
{
try
{
if(_reader.ready())
{
do
{
int i = _reader.read();
if (i != -1)
{
char c = (char)i;
workingBuffer.append(c);
if(c == '\n')
{
_lastDataObject = new String(workingBuffer);
workingBuffer = new StringBuffer();
break;
}
}
else
{
break;
}
} while (_reader.ready());
}
}
catch (Throwable t)
{
throw MyAdapter.getInstance().createAdapterException(100,t);
}
return _lastDataObject;
}
public void listenerShutdown()
{
try
{
_reader.close();
}
catch(Throwable t){}
}
public void processNotificationResults(NotificationResults results)
throws ResourceException
{
if(results != null)
{
if(results.hadError())
{
MyAdapter.getLogger().logError(9999,
"Error processing: " + this._lastDataObject +
" errorInfo = " + (results.getErrorInfo() == null ? "" : results.getErrorInfo().toString()));
}
}
else
{
MyAdapter.getLogger().logError( 9999,
"No notification available to process:" +
this._lastDataObject);
}
}
}
Defining a WmConnectedListener Implementation Class
Procedure
Specifying Configuration Metadata for Listener Notifications
The next step for implementing a listener is to create the metadata constructs that the users of the adapter use for entering data when they create listener notification nodes. To do this, perform the following:
- Create metadata parameters appropriate for the function of the
listener notification nodes. Each parameter has:
- A variable to hold the configured values.
- A String constant containing the name of the parameter.
- An accessor method.
- A set of resource bundle entries with a localizable parameter name and description as shown in Updating the Resource Bundle.
For more information on metadata parameters, see Metadata Model for Connection.
- Describe presentation for those metadata parameters.
- Set the data entry rules for those metadata parameters.
The example implementation includes one metadata parameter, that the users of the adapter use to create listener notification nodes. The following table describes the purpose of each of these parameters for data entry:
| Parameter | Description |
|---|---|
| fileName | File to monitor. |
| Parameter | Accessor Method | Variable | Resource Bundle Entries |
|---|---|---|---|
| fileName | setFileName | FILE_NAME_PARM | None |
Specifying the Display and Data Entry Attributes of the Data Entry Parameters
- After creating the parameters, specify the display and data entry attributes by calling various methods of the WmDescriptor interface from the service's fillWmDescriptor method.
- The example code places each data entry parameter into a single group (in display order) referenced by the constant NOTIFICATION_SETUP_GROUP. A constant instead of a string is used to name the group, because the same value is used in the resource bundle to specify a localizable group name.
Restricting Listeners to Register Specified Notification Templates
By default a listener supports all listener
notification templates of the adapter. When the users of the adapter configure
a new listener notification (either synchronous or asynchronous) using
Designer, they may select from the complete list of all enabled
listeners in the adapter. You may want to override this default behavior so
that the listener implementation specifies exactly which notification templates
it supports. To do this, implement the
restrictNotificationTypes method in your
listener implementation class. This method returns a
String array containing the fully qualified path
names of one or more notification template classes that the listener supports.
When the users of the adapter attempt to configure a new listener notification
in
Designer, only those template classes in the returned array will
appear in the Adapter Notification Editor. The following example shows how to
use this method.
public class SimpleListener extends WmConnectedListener
{
...
public String[] restrictNotificationTypes()
{
return new String[]{"com.wm.myadapter.notifications.FooNotification",
"com.wm.myadapter.notifications.BarNotification"};
}
...
}
Implementing Listener Methods
- listenerStartup
- waitForData
- listenerShutdown
- processNotificationResults
The example also includes an implementation of processNotificationResults.
Creating getReader Method in WmManagedConnection Implementation Class
package com.wm.MyAdapter.connections;
..
..
import java.io.FileReader;
import java.io.FileNotFoundException;
..
..
public class SimpleConnection extends WmManagedConnection {
..
..
public FileReader getReader(String fileName) throws AdapterException
{
FileReader _reader = null;
try {
_reader = new FileReader(fileName);
}
catch(Exception e) {
throw MyAdapter.getInstance().createAdapterException(100,e);
}
return _reader;
}
}
Updating the Resource Bundle
Update the resource bundle with a display name, and description to make the listener more usable. For example:
package com.wm.MyAdapter;
..
..
import com.wm.MyAdapter.listeners.SimpleListener;
..
..
public class MyAdapterResource extends ListResourceBundle implements MyAdapterConstants{
..
..
static final Object[][] _contents = {
..
..
//Listener
,{SimpleListener.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME,
"Simple Listener"}
,{SimpleListener.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION,
"Use to monitor log files"}
,{SimpleListener.FILE_NAME_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME,
"Log File Name"}
}
protected Object[][] getContents() {
// TODO Auto-generated method stub
return _contents;
}
}
Registering Listeners in the WmAdapter Implementation Class
You must register each listener class in the WmAdapter implementation class. You do this by passing the class name to the AdapterTypeInfo.addListenerType method in the WmAdapter.fillAdapterTypeInfo method in the WmAdapter implementation class. In the example, the listener class SimpleListener is registered in the adapter implementation class MyAdapter:
package com.wm.MyAdapter;
..
..
import com.wm.MyAdapter.listeners.SimpleListener;
..
..
public class MyAdapter extends WmAdapter implements MyAdapterConstants {
..
..
public void fillAdapterTypeInfo(AdapterTypeInfo info, Locale locale)
{
..
..
info.addListenerType(SimpleListener.class.getName());
}
}
Compiling Adapter
About this task
Compile your adapter as described in Compiling the Adapter.
Reloading Adapter
About this task
Reload your adapter as described in Loading, Reloading, and Unloading Packages.
Refreshing the Designer cache
About this task
Refresh the Designer cache.
Configuring a Listener
About this task
Perform the following procedure to configure a listener node. You can use Designer to configure adapter service nodes.
To configure a listener node
Procedure
What to do next
Listener Notification Implementation
The following example implements an asynchronous
listener notification that recognizes session log entries and generates
notifications from them. To distinguish a session log entry from another type
of log entry, the listener parses the entry data in the notification's
supports method. The
supports method model is flexible enough to permit
this approach because the same listener notification object instance that
returns
true from the
supports call is guaranteed to receive the
runNotification call.
The example listener notification uses an alternative approach to implementing resource domains that redirects resource domain activities back to the notification (or adapter service) that uses it. This model does a better job of encapsulating the notification functionality into a single class. The model is described in detail in to-appx_alt_approaches_metadata.html#A52135. If you do not want to use this model, you may implement the resource domain code following the model described in Specifying Adapter Service Signature Resource Domains.
Another new concept used in this example is the "uses" metadata mechanism. This is a shortcut mechanism commonly used to manipulate a metadata signature. You use it to add a column of check boxes to the adapter's interface so that the users of the adapter can select the fields to use for the notification. When they select the check boxes, values will appear in the Signature column. This metadata mechanism is described in The useParam Argument of setResourceDomain, but you do not need to fully understand the constraint of that feature to implement this example.
The tasks for implementing an asynchronous listener notification are as follows:
- Defining a WmAsyncListenerNotification Implementation Class
- Specifying Configuration Metadata for Listener Notifications
- Implementing Configuration Resource Domains for Listener Notifications
- Implementing the supports and runNotification Method
- Updating the Resource Bundle
- Registering Listener Notifications in the Adapter
- Compiling the Adapter
- Reloading Adapter
- Refreshing the Designer cache
- Configuring and Testing Listener Notification Nodes
Example Listener Notification Class
package com.wm.MyAdapter.listeners;
import com.wm.adk.error.AdapterException;
import com.wm.adk.metadata.WmDescriptor;
import com.wm.adk.notification.WmAsyncListenerNotification;
import com.wm.adk.notification.NotificationResults;
import com.wm.adk.notification.AsyncNotificationResults;
import com.wm.adk.notification.NotificationEvent;
import com.wm.adk.connection.WmManagedConnection;
import com.wm.adk.metadata.*;
import com.wm.adk.cci.record.WmRecord;
import com.wm.adk.cci.record.WmRecordFactory;
import javax.resource.ResourceException;
import java.util.Locale;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;
import com.wm.MyAdapter.MyAdapter;
import com.wm.MyAdapter.MyAdapterConstants;
import com.wm.MyAdapter.connections.SimpleConnection;
public class SessionLogListenerNotification extends WmAsyncListenerNotification
implements MyAdapterConstants
{
private String[] _fieldNames = null;
private String[] _fieldTypes = null;
private boolean[] _uses = null;
public void setFieldNames(String[] val){_fieldNames = val;}
public void setFieldTypes(String[] val){_fieldTypes = val;}
public void setUses (boolean[] val){_uses = val;}
public void setSignature(String[] val){}
public static final String NOTIFICATION_SETUP_GROUP =
"SessionLogListenerNotification.setup";
public static final String FIELD_NAMES_PARM = "fieldNames";
public static final String FIELD_TYPES_PARM = "fieldTypes";
public static final String USES_PARM = "uses";
public static final String SIG_PARM = "signature";
public static final String FIELD_NAMES_RD =
"SessionLogListenerNotification.fieldNames.rd";
public static final String FIELD_TYPES_RD =
"SessionLogListenerNotification.fieldTypes.rd";
public static final String[] _sigFieldNames = {
"timeStamp",
"component",
"rootContext",
"parentContext",
"currentContext",
"server",
"eventCode",
"user",
"sessionName",
"RPCs",
"age"};
private Object[] _parsedValues = new Object[_sigFieldNames.length];
public void fillWmTemplateDescriptor(WmTemplateDescriptor descriptor,Locale l)
throws ResourceException
{
String[] parms = new String[] {FIELD_NAMES_PARM,
FIELD_TYPES_PARM,
USES_PARM,
SIG_PARM};
descriptor.createGroup(NOTIFICATION_SETUP_GROUP, parms);
descriptor.createFieldMap(parms, false);
descriptor.createTuple(new String[]{FIELD_NAMES_PARM, FIELD_TYPES_PARM});
descriptor.setResourceDomain(FIELD_NAMES_PARM, FIELD_NAMES_RD, null);
descriptor.setResourceDomain(FIELD_TYPES_PARM, FIELD_TYPES_RD, null);
descriptor.setResourceDomain(SIG_PARM,
WmTemplateDescriptor.OUTPUT_FIELD_NAMES,new String[]{
FIELD_NAMES_PARM,FIELD_TYPES_PARM}, USES_PARM);
descriptor.setDescriptions( MyAdapter.getInstance().
getAdapterResourceBundleManager(), l);
}
public Boolean adapterCheckValue(WmManagedConnection connection,
String resourceDomainName, String[][] values,
String testValue) throws AdapterException
{
return true;
}
public ResourceDomainValues[] adapterResourceDomainLookup(
WmManagedConnection connection, String resourceDomainName,
String[][] values) throws AdapterException
{
ResourceDomainValues[] results = null;
if (resourceDomainName.equals(FIELD_NAMES_RD)
|| resourceDomainName.equals(FIELD_TYPES_RD))
{
ResourceDomainValues names = new ResourceDomainValues(
FIELD_NAMES_RD, _sigFieldNames);
ResourceDomainValues types = new ResourceDomainValues(
FIELD_TYPES_RD,new String[] {
Date.class.getName(), //timestamp
String.class.getName(), // component
String.class.getName(), // rootContext
String.class.getName(), // parentContext
String.class.getName(), // currentContext
String.class.getName(), // server
Integer.class.getName(), // eventCode
String.class.getName(), // user
String.class.getName(), // sessionName
Integer.class.getName(), // RPCs
Long.class.getName() // age
});
results = new ResourceDomainValues[] {names,types};
}
return results;
}
public void registerResourceDomain(WmManagedConnection connection,
WmAdapterAccess access) throws AdapterException
{
access.addResourceDomainLookup(this.getClass().getName(),
FIELD_NAMES_RD, connection);
access.addResourceDomainLookup(this.getClass().getName(),
FIELD_TYPES_RD, connection);
}
public boolean supports(Object data) throws ResourceException
{
boolean result = false;
try
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:mm:ss zzz");
String sData = (String)data;
this._parsedValues[0] = sdf.parse(sData.substring(0,48));
StringTokenizer st = new StringTokenizer(sData.substring(49)," ",false);
this._parsedValues[1] = st.nextToken();
this._parsedValues[2] = st.nextToken();
this._parsedValues[3] = st.nextToken();
this._parsedValues[4] = st.nextToken();
/*
st.nextToken(); // skip the session ID
this._parsedValues[5] = st.nextToken();
this._parsedValues[6] = new Integer(st.nextToken());
this._parsedValues[7] = st.nextToken();
this._parsedValues[8] = st.nextToken();
this._parsedValues[9] = new Integer(st.nextToken());
this._parsedValues[10] = new Long(st.nextToken());
*/
result = true;
}
catch(Throwable t){}
return result;
}
public NotificationResults runNotification(NotificationEvent event)
throws ResourceException
{
NotificationResults result = null;
WmRecord notice = WmRecordFactory.getFactory().createWmRecord("notUsed");
for(int i = 0; i< _sigFieldNames.length;i++)
{
if (_uses[i])
{
notice.put(_sigFieldNames[i],_parsedValues[i]);
}
}
this.doNotify(notice);
result = new AsyncNotificationResults(this.nodeName(),true,null);
return result;
}
}
Defining a WmAsyncListenerNotification Implementation Class
- fillWmTemplateDescriptor
- supports
- runNotification
- adapterCheckValue
- adapterResourceDomainLookup
- registerResourceDomain
Specifying Configuration Metadata for Listener Notifications
The example listener notification in this section includes only those configuration parameters that are directly related to the signature. The only new concept in this section is the use of the useParam argument of theWmTemplateDescriptor.setResourceDomain method.
The useParam Argument of setResourceDomain
The WmTemplateDescriptor interface provides two signatures for the setResourceDomain method, one of which includes the argument useParam:
public void setResourceDomain(java.lang.String name,
java.lang.String resourceDomainName,
java.lang.String[] dependencies,
java.lang.String useParam)
- Use this argument as a filter to determine which of the available fields will be included in the signature. The example implements the useParam argument as USES_PARM constant, in the setResourceDomain method near the end of the example.
- The
USES_PARM parameter is only meaningful when
the parameter identified in the name argument and the parameter names in
useParam parameter are in the same fieldMap,
and the data type of the
useParam parameter is
boolean[]. When these conditions are satisfied, the adapter service editor treats the useParam setting as a filter on the resource domain association. When this occurs, the resource domain values are only applied to the name parameter row in the fieldMap if the corresponding value in the useParam is true which occurs when the user of the adapter selects the check box. - When the user of the adapter selects the fields to use for the notification by selecting the check boxes in the Uses column, values appear in the Signature column. When you save changes to the notification node, the signature changes are reflected in the associated document type.
Implementing Configuration Resource Domains for Listener Notifications
class.getName method
when specifying data types. Using this technique enables you to catch spelling
errors at compile time.
Implementing the supports and runNotification Method
This example implementation of the
supports method parses the contents of the data
object that is originally returned from the listener's
waitForData method, into the
_parsedValues object variable. Any error in the
parsing process indicates that the data object was not a session log entry, and
the supports method returns a
false value.
The runNotification method implementation assumes that the supports method was successful in parsing the data object, so it does not need the NotificationEvent argument. It merely populates a WmRecord object by inserting the parsed names, using the same key names array that populate the resource domain.
Updating the Resource Bundle
Update the resource bundle with a display name, and description to make the listener notification more usable.
package com.wm.MyAdapter;
..
..
import com.wm.MyAdapter.listeners.SessionLogListenerNotification;
..
..
public class MyAdapterResource extends ListResourceBundle implements MyAdapterConstants{
..
..
static final Object[][] _contents = {
..
..
//SessionLog Listener Notification
,{SessionLogListenerNotification.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME,
"SessionLog Listener Notification"}
,{SessionLogListenerNotification.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION,
"Use SessionLog Listener Notification to monitor log files"}
,{SessionLogListenerNotification.FIELD_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME,
"Field Name"}
,{SessionLogListenerNotification.FIELD_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION,
"Field Name To Check"}
,{SessionLogListenerNotification.FIELD_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME,
"Field Types"}
,{SessionLogListenerNotification.FIELD_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION,
"Field Types To Check"}
}
protected Object[][] getContents() {
// TODO Auto-generated method stub
return _contents;
}
}
Registering Listener Notifications in the Adapter
You must register each listener notification class in the WmAdapter implementation class. You do this by passing the class name to the AdapterTypeInfo.addNotificationType method in the WmAdapter.fillAdapterTypeInfo method in the WmAdapter implementation class. In the example, the listener notification class SessionLogListenerNotification is registered in the adapter implementation class MyAdapter:
For example:
package com.wm.MyAdapter;
..
..
import com.wm.MyAdapter.listeners.SessionLogListenerNotification;
..
..
public class MyAdapter extends WmAdapter implements MyAdapterConstants {
..
..
public void fillAdapterTypeInfo(AdapterTypeInfo info, Locale locale)
{
..
..
info.addNotificationType(SessionLogListenerNotification.class.getName());
}
}
Compiling Adapter
About this task
Compile your adapter as described in Compiling the Adapter.
Reloading Adapter
About this task
Reload your adapter as described in Loading, Reloading, and Unloading Packages.
Refreshing the Designer cache
About this task
Refresh the Designer cache.
Configuring and Testing Listener Nodes and Listener Notification Nodes
Now you are ready to configure a listener notification node as follows:
- Configuring Listener Notification Nodes
- Testing Listener Nodes and Listener Notification Nodes
Configuring Listener Notification Nodes
About this task
A listener notification node can be either synchronous or asynchronous. When an event occurs, an asynchronous listener notification publishes a document. You must create a trigger that receives the document and executes a service to process the document's data. With a synchronous listener notification, you can designate a flow service to process the data produced by the notification. A synchronous notification does not use a trigger.
To configure a listener notification node
Procedure
Testing Listener and Listener Notification Nodes
Creating the Flow Service for the Listener Notification Node
About this task
Perform the following procedure to create the flow service for the listener notification node.
To create the flow service for the listener notification node
Procedure
Creating the Trigger for the Listener Notification Node
About this task
Perform the following procedure to create the trigger for the Polling notification node.
To create the trigger for the Polling notification node
Procedure
- Start Designer.
- In the Package Navigator, select the folder where you want to create the trigger.
- Select File > New.
- Select webMethods Messaging Trigger from the list of elements.
- On the webMethods Messaging Trigger screen, type TestMyAdapterMsgTrigger in the Element name field and click Finish.
- In the trigger editor, in the Conditions section, accept the default Condition1.
- In the Condition detail section, in the Service field, select or type the flow service name TestMyAdapterFlowService.
-
Click
to insert document types. Select
TestMyListenerNotificationPublishDocument
and click
OK.
-
Click
to save your trigger.
Enabling Listener Notification Nodes and Listener Nodes
About this task
Enabling the listener before you configure and enable its corresponding listener notification node produces a warning.
To enable a listener node and a listener notification node
Procedure
- Start Integration Server Administrator.
- In Adapters screen, select the name of your adapter.
- Select Listener Notifications.
- In the Listener Notification screen, enable the listener notification node by clicking No in the Enabled column. The Enabled column now shows Yes (enabled).
- Select Listeners.
- In the Listeners screen, enable the listener by clicking No in the Enabled column. The Enabled column now shows Yes (enabled).
Testing Listener
About this task
<?xml version="1.0" encoding="UTF-8"?>
<IDataXMLCoder version="1.0">
<record javaclass="com.wm.data.ISMemDataImpl">
<value name="fileName">MonitorListenerNotificationPipeline.log</value>
<record name="TestMyAdapterListener:TestMyAdapterListenerNotificationPublishDocument"
javaclass="com.wm.data.ISMemDataImpl">
<Date name="timeStamp" type="java.util.Date">Thu Oct 21 12:34:45 IST 2021</Date>
<value name="component">)</value>
<value name="rootContext">Unable</value>
<record name="_env" javaclass="com.wm.data.ISMemDataImpl">
<value name="locale"></value>
<value name="activation">wm624455fb0-b66d-4344-b92f-cee92639b14c</value>
<value name="businessContext">wm6:2281c61b-a0dd-4dc2-bb31-6eaea2052a1c\snull\snull:
wm624455fb0-b66d-4344-b92f-cee92639b14c:null:IS_61:null</value>
<value name="uuid">wm:14c48f70-323e-11ec-b7fd-000000000152</value>
<value name="trackId">wm:14c48f70-323e-11ec-b7fd-000000000152</value>
<value name="pubId">islocalpubid</value>
<Date name="enqueueTime" type="java.util.Date">Thu Oct 21 12:41:15 IST 2021</Date>
<Date name="recvTime" type="java.util.Date">Thu Oct 21 12:41:15 IST 2021</Date>
<number name="age" type="java.lang.Integer">0</number>
</record>
</record>
</record>
</IDataXMLCoder>