# Platform Development Studio - Developer’s Guide

# Container Services

This chapter provides a high-level description of Oracle Communications Services Gatekeeper container services. It also provides an overview of other parts of the API available for the use of extension developers:

- Container service APIs
- Class: InstanceFactory
- Class: ClusterHelper
- Service: EventChannel Service
- Service: Statistics service
- Plug-in
- Management
- EDR
- SLA Enforcement
- Service Correlation
- Parameter Tunneling
- Storage Services

- ConfigurationStore
- StorageService

- Shared libraries

JavaDoc for the container API is available in the `$PDS_Home/doc/javadoc` directory of the Platform Development studio installation and on the Oracle Communications Services Gatekeeper site at `http://www.oracle.com/technology/documentation/bea.html.`

## Container service APIs

The Oracle Communications Services Gatekeeper container service APIs provide the basic infrastructure by which a Communication Service and the container services of Oracle Communications Services Gatekeeper can communicate.

All APIs for inter-working with the container services are found in com.bea.wlcp.wlng.api.*.

In order for a network protocol plug-in of a Communication Service to interact with Oracle Communications Services Gatekeeper it must be deployable in the context of Oracle Communications Services Gatekeeper. Once it is deployable, it can have access to certain utility functions.

.

Table 7-1 Summary of the container services APIs
Package | Summary
--- | ---
com.bea.wlcp.wlng.api.account | Represents an application instance and the related accounts and groups and the states of the accounts.
com.bea.wlcp.wlng.api.corba | Factory to retrieve an ORB.
com.bea.wlcp.wlng.api.edr.* | Annotations, interfaces and classes used when annotating EDRs. Descriptor classes for alarms, EDRs, and CDRs. Helper classes for EDR listeners. See Annotations, EDRs, Alarms, and CDRs.
com.bea.wlcp.wlng.api.event_channel | Classes to publish and listen to events over cluster-wide event channels. See Service: EventChannel Service.
com.bea.wlcp.wlng.api.interceptor | Interfaces and classes for service interceptors. See Service Interceptors.
com.bea.wlcp.wlng.api.management.* | MBean helper classes. See Making Communication Services Manageable.
com.bea.wlcp.wlng.api.plugin.* | Plug-in related classes and interfaces. See Plug-in.
com.bea.wlcp.wlng.api.servicecorrelation | Interface to implement if extending the existing service correlation mechanism. See Service Correlation.
com.bea.wlcp.wlng.api.statistics | Annotation for statistics. See Service: Statistics service.
com.bea.wlcp.wlng.api.storage | Interfaces and classes for the Storage Service. See Storage Services.
com.bea.wlcp.wlng.api.timers | Factory for using commonj.timers API.
com.bea.wlcp.wlng.api.util | Classes and interfaces for commonly used functions, for example ID generator, InstanceFactory, and clustering.
com.bea.wlcp.wlng.api.work | Factory for using commonj.work API.

## Class: InstanceFactory

The Instance Factory is the mechanism used in Oracle Communications Services Gatekeeper to retrieve instances of a given interface, class, or abstract class. You retrieve an instance of the Instance Factory using the public static method `getInstance()`. The factory itself has a single method:

`getImplementation(Class theClass)` - Retrieves a class that implements a given interface or extends a given class

The implementation to be used is located and used based on the following rules:

1. First, check the jar file’s `instancemap`, a standard `java.util.Properties` file. Every jar file can have its own `instancemap`. The `instancemap` provides a list that maps a given interface, class, or abstract class to the preferred implementation of that functionality. See Listing 7-1 for an example.

Note: | The interface name used in the instancemap must be unique across all plug-ins for a given Service Enabler. It is not possible to use the same interface in two `instancemap` files belonging to two different plug-ins and still map them to two different implementations.

2. If a mapping is provided and the target class has a public constructor or static singleton method, instantiate it.
3. If there is no explicit mapping, or if there is no public constructor or static singleton method for a mapped class, instantiate an object named according to the following pattern: `theClass.getClass().getName() +”Impl”` if this exists and has a public constructor or static singleton method.
Listing 7-1 Example instancemap file

    com.bea.wlcp.wlng.MyInterface=com.bea.wlcp.wlng.MyImplementation

    com.bea.wlcp.wlng.MyOtherInterface=com.bea.wlcp.wlng.MyOtherImplementation

For details see Javadoc for Package `com.bea.wlcp.wlng.api.util` Class InstanceFactory.

## Class: ClusterHelper

`com.bea.wlcp.wlng.api.util.cluster.ClusterHelper`

Helper class for getting the JNDI Context for the network and access tier.

For details see Javadoc for Package `com.bea.wlcp.wlng.api.util.cluster` Interface ClusterHelper.

## Service: EventChannel Service

This service is used to broadcast events to other Oracle Communications Services Gatekeeper server instances and to register listeners for events originating in other Oracle Communications Services Gatekeeper server instances.

##### Interface: EventChannel

Use this interface to broadcast events to other instances of Oracle Communications Services Gatekeeper, and to register listeners for events originating in them. It is used, for example, in propagating changes of cached data. It is retrieved using the com.bea.wlcp.wlng.api.event_channel.EventChannelFactory.

An event has a name and a value, where the name is an identifier for the event and the value is any object implementing j`ava.io Serializable`.

The following methods are available:

- `deactivateAllListeners()` - Deactivates all registered listeners.
- `publishEvent` - Publishes an event to all registered listeners.
- `publishEventToOneNode` - Publishes an event to one Oracle Communications Services Gatekeeper instance.
- `registerEventListener` - Registers an `EventListener`.
- `unregisterEventListener` - Unregisters an `EventListener`.

##### Interface: EventChannelListener

This interface is used to receive events published using `EventChannel`.

The following method is available:

- `processEvent(String eventType, Serializable event, String source)` - Receives an event.

## Service: Statistics service

Standard statistics are generated automatically when a plug-in implements `PluginNorth` and `PluginNorthCallBack` interfaces. In addition to this, custom statistics can be generated explicitly.

To explicitly generate statistics, annotate the method where you wish to generate statistics.

The syntax of the annotation is:

`@Statistics(id=<My_Statistics_Type>)`

    @ExceptionStatistics(id=<My_Statistics_Type>)

The annotations are defined in:

    om.bea.wlcp.wlng.api.statistics.Statistics

    com.bea.wlcp.wlng.api.statistics.ExceptionStatistics

The `@Statistics` annotation generates a statistics event when the method returns, while the `@ExceptionStatistics` annotation generates a statistics event if an exception is thrown.

The statistics type must be registered. Use the `addStatisticType` operation in the Management Console. For more information, see “Managing and Configuring Statistics and Transaction Licenses” in the System Administration Guide.

For extensions, the statistics ID shall be in the range 1000 to 2250.

## Plug-in

The `com.bea.wlcp.wlng.api.plugin.*` packages contain a range of interfaces and classes for use by the extension developer.

See Communication Service Description.

## Management

Base classes and annotations for giving the Oracle Communications Services Gatekeeper Management Console or other JMX tools management access to Communication Services. See Making Communication Services Manageable for more information. Also see the JavaDoc for the packages: `com.bea.wlcp.wlng.api.management.*`

## EDR

See Annotations, EDRs, Alarms, and CDRs.. Also see the JavaDoc for the packages `com.bea.wlcp.wlng.api.edr.*`

## SLA Enforcement

SLA enforcement operates on methods identified by the Java representation of the interface, and the operation on the application-facing interface for the Communication Service or the service type of the Communication Service.

The content of the tag <scs> defined in the <serviceContract> tag in the SLA is the plug-in type for the plug-in.

An operation on the application-facing interface is represented in the rules according to the following scheme: <service name> and <operation name>.

Parameters in the operation are represented in the rules according to the following scheme:

arg<n>.<parameter name>

where <n> in arg<n> depends on the WSDL that defines the application-facing interface; normally this is arg0.

If the parameter in <parameter name > is

- a composed parameter, the notation is according to the Java Bean notation for that parameter.
- an enumeration, the notation is according to the Java-representation of that parameter, <parameter name >.<enumeration value>. The <enumeration value> is the String representation.

SLA enforcement can also be done for a certain service type. The service type is defined when generating the Communication Service or network protocol plug-in using the Eclipse Wizard. SLA enforcement for service types relates to quotas and request rates and are defined under the element <serviceTypeContract>.

For enforcement of custom SLAs, see Custom Service Level Agreements.

## Service Correlation

It is often the case that service providers would like to be able to bundle what are to Oracle Communications Services Gatekeeper separate services into a single unit for charging purposes. An end user could send an SMS to the provider requesting the location of the coffee shop closest to her current location. The application would receive the network-initiated SMS (one service), do a user location lookup on the customer (one service), and then send the customer an MMS with a map showing the requested information (one service). So three Oracle Communications Services Gatekeeper services need to be grouped into a single service charging unit. To do this, Oracle Communications Services Gatekeeper provides the framework for a Service Correlation service that uses a Service Correlation ID (SCID) to combine/correlate all the services.

- The Service Correlation ID is optional.
- The Service Correlation ID is captured in the CDRs and EDRs generated from Oracle Communications Services Gatekeeper.
- The Service Correlation ID is propagated as a String.
- The Service Correlation ID is propagated to and from the application in the SOAP header.

The SCID itself is provided either by the application or by an external mechanism that the Communication Service must provide (see Interface: ExternalInvocation). Oracle Communications Services Gatekeeper does not check whether or not it is unique. The SCID is stored in the OLS Work Context, so that it can be accessed by both the Access Tier and the Network Tier. The Service Correlation class registers itself as a `RequestContextListener`. When application-initiated request traffic enters the plug-in, the Service Correlation service takes the SCID from the Work Context and places it in the `RequestContext` object, where it will be available to the EDR service. When network-initiated request traffic is leaving the plug-in, the Service Correlation service takes the SCID from the `RequestContext` object and places it in the Work Context, where it can be retrieved by the SOAP Handler and passed along to the application.

### Interface: ExternalInvocation

Because Service Correlator IDs may need to be stored across several invocations and a `RequestContext` object exists only for the lifetime of a single request, a Communication Service needs to create a way of storing and retrieving the SCIDs. This is done by implementing the `ExternalInvocation` interface. This interface has two methods: one stores the Service Correlation ID and one retrieves it. The implementor is free to modify the ID once it has been stored, or to use the Invocation object to create IDs in the first place.

When the Service Correlation service takes the SCID (should there be one) out of the Work Context of an application-initiated request, it automatically attempts to store it in an object of this type before putting the SCID in the `RequestContext`.

When a network-initiated request is leaving the plug-in, the Service Correlation service automatically attempts to retrieve an SCID from an object of this type, using the SCID (should there be one) it finds in the `RequestContext` object before it sets the Work Context. In this way, if the `ExternalInvocation` object has modified the SCID in any way, it is this modified version that is put in the Work Context and thus sent on to the application. The `ExternalInvocation` implementation class should have an empty public constructor or a static method that returns itself.

### Class: ExternalInvocatorFactory

This class is used by the Service Correlation service to locate and instantiate the correct `ExternalInvocation` object. It does this by using an `instancemap.` The instancemap entry should look like this:

`com.bea.wlcp.wlng.api.servicecorrelation.ExternalInvocation=myPackageStructure.myImplClass`

where `myImplClass` is the `ExternalInvocation` implementation.

### Class: ServiceCorrelation

This class manages the transport and storage of the Service Correlation ID across multiple service invocations.

### Implementing the ExternalInvocation Interface

There are four basic steps in creating a custom service correlation:

1. Create a jar file that includes your code. For example:
Listing 7-2 Sample Custom Service Correlation

    package myPackageStructure;

    import com.bea.wlcp.wlng.api.servicecorrelation.ExternalInvocation;

    import com.bea.wlcp.wlng.api.servicecorrelation.ExternalInvocationException;

    public class MyImplClass implements ExternalInvocation {

     public MyImplClass() {

     }

     public String pushServiceCorrelationID(String scID, String serviceName, String methodName, String spID, String appID, String appInstGrp) throws ExternalInvocationException {

      // your code here

      return scID;

     }

     public String getServiceCorrelationID(String scID, String serviceName, String methodName, String spID, String appID, String appInstGrp) throws ExternalInvocationException {

      // your code here

      return scID;

     }

    }

2. Create the instancemap. See Class: ExternalInvocatorFactory.
3. Put the instancemap file in the JAR. This makes your custom service correlation available to the service interceptor InvokeServiceCorrelation.
4. Put the JAR file in `$DOMAIN_Home/lib`.

## Parameter Tunneling

Parameter tunneling is a feature that allows an application to send additional parameters to Oracle Communications Services Gatekeeper and lets a plug-in use these parameters. This feature makes it possible for an application to tunnel parameters that are not defined in the interface that the application is using and can be seen as an extension to the application-facing interface.

The application sends the tunneled parameters in the SOAP header of a Web Services request.

The tunneled parameter can be retrieved in a plug-in by the key. The parameter is fetched from the RequestContext, using the method `getXParam(String key)`. If a value for the key cannot be found, null is returned.

Listing 7-3 Get the value of the tunneled parameter ‘aParameterName’.

    RequestContext.getCurrent().getXParam("aParameterName");

If the same parameter is defined in the <contextAttribute> SLA tag, it should override the parameter tunneled from the application. This behavior, however, is defined per plug-in.

## Storage Services

The storage services provided in Oracle Communications Services Gatekeeper are of two types, described below:

- ConfigurationStore
- StorageService

### ConfigurationStore

The Oracle Communications Services Gatekeeper container exposes a `ConfigurationStore` Java API that Communication Services can use to store simple configuration parameters instead of using JDBC and caching algorithms in each module.

Note: | This utility is intended for configuration parameters only, not traffic data

All data stored in a `ConfigurationStore` are stored in a database table and cached in memory.

Below are the characteristics of a `ConfigurationStore:`

- It is a named store.
- Parameters stored in it must be initialized before they can be used.
- Stores can be either domain wide (shared) or limited to a single Oracle Communications Services Gatekeeper server (local). The domain wide store type replicates all data changes to all servers in the cluster, while the local store type keeps a different view of the parameters on different servers and data changes affect only the view for that particular server.
- Parameters stored in a `ConfigurationStore` are persisted to database.
- Data in all `ConfigurationStores` are also cached in memory.
- Only one instance of each named `ConfigurationStore` is cached in memory per server.
- Updates to a cluster wide named `ConfigurationStore` is reflected in all cluster nodes.
- The named `ConfigurationStore` only supports parameters of type Boolean, Integer, Long, String, and Serializable.

#### Interfaces

The Java interface APIs are found in the package `com.bea.wlcp.wlng.api.storage`.

The entry point to configuration stores is through the com.bea.wlcp.wlng.api.storage.configuration.ConfigurationStoreFactory using the following method:

    public abstract ConfigurationStore getStore(String moduleName, String name, int storeType) throws ConfigurationException;

The `ConfigurationStore` service exposes an interface with the following features:

- Methods to initialize the store with the following data types:

- Boolean,
- Integer,
- Long,
- String
- Serializable

A ConfigurationStore is initialized using a name in key/value pair. You get and set configuration parameters using the key.

- Methods to set and get the following data types:

- Boolean,
- Integer,
- Long,
- String
- Serializable

- Methods to add and remove listeners for notifications on updates. When a parameter has been updated in one instance of the `ConfigurationStore`, a notification is broadcast to all other instances of the`ConfigurationStore`.

Listing 7-4 is an example of using the Configuration Store.

Listing 7-4 Example of a ConfigurationStoreHelper

    package com.acompany.plugin.example.netex.management;

    import com.bea.wlcp.wlng.api.storage.configuration.*;

    /**

     * Class used for handling the configuration store.

     *

     * @author Copyright (c) 2007 by BEA Systems, Inc. All Rights Reserved.

     */

    public class ConfigurationStoreHandler {

    /**

       * Constants used for the values stored in the store.

       */

      public static final String KEY_NETWORK_HOST = "KEY_NETWORK_HOST";

      public static final String KEY_NETWORK_PORT = "KEY_NETWORK_PORT";

    /**

       * Constant to access either the local store. Note that these are

       * just names for the store.

       */

      private static final String LOCAL_STORE = "local";

    /**

       * Local configuration store instance.

       */

      private ConfigurationStore localConfigStore;

    /**

       * Constructor.

       *

       * @param pluginId The plugin id

       * @throws ConfigurationException An exception thrown if the initialization failed

       */

      public ConfigurationStoreHandler(String pluginId)

        throws ConfigurationException {

        ConfigurationStoreFactory factory = ConfigurationStoreFactory.getInstance();

        localConfigStore = factory.getStore(pluginId, LOCAL_STORE,

                ConfigurationStore.STORE_TYPE_LOCAL);

        // To obtain a shared configuration store, use ConfigurationStore.STORE_TYPE_SHARED

        localConfigStore.initialize(KEY_NETWORK_HOST, "localhost");

        localConfigStore.initialize(KEY_NETWORK_PORT, 5001);

      }

      /**

       * Sets an integer value in the local store.

       *

       * @param key The key associated with the value.

       * @param value The value to store.

       * @throws ConfigurationException An exception thrown if the operation failed

       */

      public void setLocalInteger(String key, Integer value)

        throws ConfigurationException {

        localConfigStore.setInteger(key, value);

      }

    /**

       * Gets an integer value from the local store.

       *

       * @param key The key associated with the value.

       * @return The value associated with the key.

       * @throws InvalidTypeException thrown if type is invalid.

       * @throws NotInitializedException thrown if key value has not been

       * initialized.

       */

      public Integer getLocalInteger(String key)

        throws InvalidTypeException, NotInitializedException {

        return localConfigStore.getInteger(key);

      }

    /**

       * Sets a string value in the local store.

       *

       * @param key The key associated with the value.

       * @param value The value to store.

       * @throws ConfigurationException An exception thrown if the operation failed

       */

      public void setLocalString(String key, String value)

        throws ConfigurationException {

        localConfigStore.setString(key, value);

      }

    /**

       * Gets a string value from the local store.

       *

       * @param key The key associated with the value.

       * @return The value associated with the key.

       * @throws InvalidTypeException thrown if type is invalid.

       * @throws NotInitializedException thrown if key value has not been

       * initialized.

       */

      public String getLocalString(String key)

        throws InvalidTypeException, NotInitializedException {

        return localConfigStore.getString(key);

      }

    }

### StorageService

The Storage Service is used for storing data that is not configuration-related, but related to the traffic flow through a Communication Service, in a cluster-wide store.

It provides mechanisms for:

- Store initialization

A store is created using the `StoreFactory` singleton class, by specifying either a key/value class pair where the value class should be a class that is unique to the Store (recommended), or a Store name.

- Basic Map usage

Since the Store interface extends the `java.util.Map` interface, it can be used as any other Map, and it is extended to be a cluster-wide view of the store.

- Named queries

In addition to the standard `java.util.Map` interface, Stores have support for a `StoreQuery` interface. The behaviors of these named queries are configured as part of the Storage Service configuration files. There is an option to define a cache filter and/or SQL query. If there is an index specified for the Store, this index can be used by implementing the `IndexFilter` interface for the cache filter. The index is automatically used for SQL queries that can make use of these indexes.

- Store listener

The Store API has support for registering `StoreListeners`. These listeners get notified if the Storage Service decides to automatically remove Store entries (based on configuration parameters). It will not be notified if the extension itself removes entries from the Store.

- Cluster locking

Cluster wide locking can be done using the Store interface. This should be used if the same entry in a Store may be modified on multiple servers at the same time, to avoid getting errors due to concurrent modification when a transaction commits.

A Communication Service extension uses the StorageService through an API. The API functionality is implemented by a storage provider. Oracle Communications Services Gatekeeper uses a write-through invalidating storage provider. Invalidating stores are backed by a database table. Other storage providers, supporting additional features, can be integrated but are not supported out-of-the box.

Extensions can use the `com.bea.wlcp.wlng.api.storage.Store` interface. This interface extends a `java.util.Map` interface and adds the following methods:

- `addListener`: Adds a listener for the store.
- `getQuery`: Gets a named query.
- `lock`: Takes a cluster-wide lock.
- `release`: Releases the current store instance.
- `removeListener`: Removes a registered listener.
- `unlock`: Unlocks a previously obtained cluster-wide lock.

The storage service uses configuration files that define the configuration for stores and the relationship between the cluster-wide store and the database table that backs the store. In each configuration file it is possible to define named queries towards the store. There is one configuration file per plug-in. Each configuration store configuration file shall, together its XSD and any complex data types stored, be created and packaged in a JAR file, in the directory `$DOMAIN_HOME/config/store_schema`. The configuration file must be named `wlng-cachestore-config-extensions.xml` and it must be present in the root of the JAR.

For details about the store configuration file, see the corresponding xsd: `com.bea.wlcp.wlng.storage_4.1.0.0.jar/wlng-cachestore-config.xsd` in `$OCSG_HOME/modules`.

A Store is retrieved from `com.bea.wlcp.wlng.api.storage.StoreFactory`, either by the name of the store or by the class names of the key/value names. How to retrieve the Store depends on how the store is configured.

The store interface needs to be released when it is no longer needed. The programming model is to retrieve the Store from the StoreFactory when the Store is used, and to release it once it has finished, using `try { .. } finally { store.release(); }`

Listing 7-5 Example: retrieve a store identified by key/value classes, operate on it, and release it.

    Store<String, NotificationData> store = StoreFactory.getInstance().getStore(String.class, NotificationData.class);

    try {

       notificationData = store.put(address.toString(), notificationData);

    } finally {

       store.release();

    }

If it is a named store, it can also be retrieved by name as illustrated below.

Listing 7-6 Retrieving a store by name

    Store<Serializable,Serializable> store = StoreFactory.getInstance().getStore("A", this.getClass().getClassLoader());

#### Store configuration file

The configuration file `wlng-cachestore-config-extensions.xml` defines attributes of the store and relations between the store, the cache for the store, and the mapping to a database table. This part is used by extension developers.

In addition, the configuration file can contain a section with mapping information between a store, the provider it uses, and the factory for the storage provider. This section should not be used by extension developers.

The XSD for the configuration file is located in `com.bea.wlcp.wlng.storage_4.1.0.0.jar/wlng-cachestore-config.xsd` in `$OCSG_HOME/modules`.

There is one configuration file per plug-in. The file must be embedded in a JAR that contains the file itself and any complex data types used. The JAR must be stored in `$DOMAIN_HOME/config/store_schema`.

Below is an example of a store configuration file for extensions.

Listing 7-7 Example of a store configuration file for extensions

    <store-config>

      <db_table name="example_store_notification">

        <key_column name="address" data_type="VARCHAR(255)"/>

        <!-- bucket_column using default BLOB type -->

        <bucket_column name="notification_data_value"/>

        <value_column name="correlator" data_type="VARCHAR(255)">

          <methods>

            <get_method name="getCorrelator"/>

            <set_method name="setCorrelator"/>

          </methods>

        </value_column>

      </db_table>

      <store type_id="wlng.db.wt.example_store_notification"

             db_table_name="example_store_notification">

        <identifier>

          <classes key-class="java.lang.String"

                   value-class="com.acompany.plugin.example.netex.notification.NotificationData"/>

        </identifier>

        <index>

          <get_method name="getCorrelator"/>

        </index>

      </store>

      <query name="com.bea.wlcp.wlng.plugin.example.netex.Query">

        <sql>

          <![CDATA[

        SELECT * FROM example_store_notification WHERE correlator = ?

       ]]>

        </sql>

        <filter-class>com.acompany.plugin.example.netex.store.FilterImpl</filter-class>

      </query>

    </store-config>

A store is defined between the elements <store-config> and </store-config>

Each Store has three sections:

- store: Defines the store.
- db_table: Defines the database table used to persist data in the store.
- query: Defines queries on the store. This is optional, only required if non-key queries are used with the store.

#### <store>

The store section defines the store itself. The attribute type_id defines the type of the store and a store type identifier. The ID must be mapped to a provider store mapping defined in `wlng-cachestore-config.xml`.

The name should always have the prefix `wlng.db.wt.` when using the storage provider in Oracle Communications Services Gatekeeper. The prefix which indicates that it is a write-through cache, that is, data put in the store is always written to database without any delay.

The attribute db_table_name identifies the database definition to use.

store contains the following elements:

- identifier: Holds one classes element. This element defines the classes for the key and the value that defines the store. The class for the key is defined in the attribute key-class and the class for the value part is defined in the attribute value-class. If a named store is used, the name is given in the element name.
- index: Defines an index on the cache and one or more get methods. The methods maps to an index on the corresponding columns in the table and potentially a cache index if supported by the provider in use.

#### <db_table>

The db_table section defines the database table used to persist data in store. The attribute name defines the table name to use. This name must be the same as the db_table_name specified in the store section. It contains the following elements:

- key_column: Has the attributes name and data_type. The attribute name specifies the column name for the key and the attribute data_type specifies the SQL data type for the key.
- multi_key_column: Has the attributes name and data_type. The attribute name specifies the column name for one part of a multi key column and the attribute data_type specifies the SQL data type for the part of the key. The difference between multi_key_column and key_column is that multi_key_column supports 2 or more columns to be parts of the key, so multi_key_column can occur two or more times in the configuration file.
- bucket_column: Has the attribute name. This attribute specifies the name of the column for the value part of the store. By default this is a BLOB. There is an optional attribute data_type, that can be used if other data types are used. This must be a Java to SQL supported data type mapping and corresponds to the data type in the value part of the store.
- value_column: Is used if attributes in the value part of the store should be stored in a separate column. The attribute name defines the name of the column and the data_type specifies the SQL data type for the column. value_column has the sub-element methods, which encloses the elements get_method and set_method. The sub-element methods defines the names of the set and get methods for the data stored in value_column and the set and get methods for the attribute of the object in the store.
Listing 7-8 Example of single key column configuration

    ...

    <db_table name="single_key_store">

      <key_column name="sample_key_1" data_type="VARCHAR(30)">

        <methods>

          <get_method name="getSampleKey1"/>

          <set_method name="setSampleKey1"/>

        </methods>

      </key_column>

      <value_column name="sample_value" data_type="VARCHAR(30)">

        <methods>

          <get_method name="getSampleValue"/>

          <set_method name="setSampleValue"/>

        </methods>

      </value_column>

    </db_table>

...

Listing 7-9 Example of multi key column configuration

    ...

    <db_table name="combined_key_store">

      <multi_key_column name="sample_key_1" data_type="VARCHAR(30)">

        <methods>

          <get_method name="getSampleKey1"/>

          <set_method name="setSampleKey1"/>

        </methods>

      </multi_key_column>

      <multi_key_column name="sample_key_2" data_type="INT">

        <methods>

          <get_method name="getSampleKey2"/>

          <set_method name="setSampleKey2"/>

        </methods>

      </multi_key_column>

      <value_column name="sample_value" data_type="VARCHAR(30)">

        <methods>

          <get_method name="getSampleValue"/>

          <set_method name="setSampleValue"/>

        </methods>

      </value_column>

    </db_table>

...

#### <query>

In addition to the standard `java.util.Map` interface, Stores have support for a `StoreQuery` interface. The behavior of these named queries are configured as part of the Storage Service configuration files.

The query section specifies a named query and a filter associated with the named query. The attribute name defines the name of the query. When using the storage service, the query is fetched using this name. The SQL query towards the database is defined in the element sql. The actual query is defined in the element <![CDATA[.....]]>.

The filter is a class that implements `com.bea.wlcp.wlng.api.storage.filter.Filter`, and the name of the class is defined in the element filter-class. The filter implements the method `setParameters`, and a `matches(...)` method.

The `setParameters` method maps the parameters to the filter class or a PreparedStatement `setObject` call ordered as the parameter array given. The filter class must implement the `matches` method in such a way that it will yield the same result as the SQL query specified.

Listing 7-10 Example of a named query

    <query name="com.bea.wlcp.wlng.plugin.example.netex.Query">

        <sql>

          <![CDATA[

        SELECT * FROM example_store_notification WHERE correlator = ?

       ]]>

        </sql>

        <filter-class>com.acompany.plugin.example.netex.store.FilterImpl</filter-class>

      </query>

Listing 7-11 Example of using the named query using a filter

    StoreQuery<String, NotificationData> storeQuery = store.getQuery("com.bea.wlcp.wlng.plugin.example.netex.Query");

    storeQuery.setParameters(correlator);

    set = storeQuery.entrySet();

Listing 7-12 Example of a filter implementation

    public class FilterImpl implements Filter {

      /**

       * The query parameters.

       */

      private Serializable[] parameters;

      /**

       * Default constructor.

       */

      public FilterImpl() {

      }

      /**

       * Evaluate if a store entry matches the filter.

       *

       * @param value The store entry value to evaluate.

       */

      public boolean matches(Object value) {

         if (parameters == null || value == null || parameters.length == 0) {

           return false;

        }

        if (value instanceof NotificationData) {

          String compareValue = ((NotificationData) value).getCorrelator();

          if (compareValue != null) {

            return compareValue.equals(parameters[0]);

          }

          return compareValue == parameters[0];

        }

        return false;

      }

      /**

       * Set query parameters. The parameters will be ordered as provided to the

       * StoreQuery and it it the responsibility of the implementation to handle

       * them in this order.

       *

       * @param parameters The query parameters to use.

       */

      public void setParameters(Serializable ... parameters)

        throws StorageException {

        this.parameters = parameters;

      }

    }

#### <provider-mapping>

The provider-mapping section contains definitions of which storage provider a given type-id is mapped to. This section shall not be used unless a custom storage provider is used.

In the type_id attribute for store_mapping type, the same ID shall be used as when the store was defined. A best match (longest matching entry) is performed. A wildcard (*) can be used at the end of type_id to match the prefix.

The <provider-name> entry references the type of store being used, see <providers>.

The type_id for the storage provider mapping in use is wlng.db.wt.*. which references the write-through provider.

There is another set of type_id attributes defined for store_mapping:

- wlng.db.log.*, which is used for internal purposes only.
- wlng.db.wb.*, which is used if the storage provider supports write-behind operations. The invalidating storage provider does not support write-behind operations, write-through will be used.
- wlng.db.wt.*, which is used if the storage provider supports write-through operations.
- wlng.cache.*, which is used if the storage provider supports cache-only operations. The invalidating storage provider does not support cache-only operations, write-through will be used.
- wlng.local.*, which is used for internal purposes only.

These store mapping types are present for internal and future use. All store mapping types (except for the internal wlng.db.log.*) are by default mapped to the keyword `invalidating` which represents the invalidating storage provider. This should not be changed unless a custom storage provider is used.

#### <providers>

The providers section contains mappings between the provider-name defined in the provider-mapping section and the factory class for the storage provider. This section should not be changed used unless a custom storage provider is used.

## Shared libraries

It is possible for multiple plug-ins to share common libraries, for example a third party library or custom code that can be shared.

If there are such parts, these should preferably not be packaged into the plug-in jar but instead be copied into the `APP-INF/lib` directory of the Communication Service network tier EAR. All classes in this directory are available for all of the plug-ins in the EAR.