Package com.opencloud.slee.resources.cgin.persist

Common API for CGIN's "fast persist" infrastructure.


This package provides infrastructure that allows per-protocol generated CGIN datatypes to be efficiently persisted to a bytearray representation, then later restored. It is intended to be used when SLEE services need to persist a CGIN datatype - for example, an InitialDPArg - in a SBB CMP field, as a replacement for the standard Java serialization that would normally be used.

Typically, using the "fast persist" model is on the order of 100 times faster to persist or restore an object compared to using standard Java serialization, and the stored representation is 10-100 times smaller.


However, there are a number of limitations:

  • a particular protocol must be chosen to do the persistence; only fields defined by that protocol are stored and restored;
  • the concrete type of the restored object is always the exact type used by the protocol, even if a different type (subclass, superclass, or sibling) was originally stored;
  • the protocol used to restore an object must exactly match the protocol used to store the object originally (notably, this system should not be used for long-term persistence, as the internal representation may change due to resource adaptor or protocol updates)
  • only the encoded form of an extension type is stored; the decoded representation is not restored when the object is rebuilt

Using the codecs

All persistence operations are done via the PersistCodec interface. This interface provides methods to encode and decode a particular CGIN type to and from a bytearray. Generic type parameters describe the bounds of the types a particular codec can handle; in general, a codec always decodes to a particular concrete type, but may be able to encode superclasses of this type. For example, the CAP v3 protocol provides a codec that will encode any subclass of CCInitialDPArg (encoding only those fields defined in CAP v3), and always produces an instance of CAP3InitialDPArg when decoded.

There are two ways to obtain a suitable PersistCodec.

For a fixed type and protocol

For cases where the exact type you wish to encode or decode is known at compile time, each protocol defines a class containing static singleton instances of PersistCodec for each type defined by the protocol. This class is named com.opencloud.slee.resources.cgin.[protocol].persist.[prefix]Codecs.

For example, CAP3Codecs provides the codecs for types defined by the CAP v3 protocol, and the static field CAP3Codecs.CAP_gsmSSF_gsmSCF_ops_args_InitialDPArg is an instance of a codec that will encode and decode CAP3InitialDPArg, as described above.

A service would use these codecs in a way similar to the following code:

  // CMP abstract methods
  public abstract byte[] getEncodedInitialDPArg();
  public abstract void setEncodedInitialDPArg(byte[] value);

  // Wrapper methods that perform encoding/decoding
  private CAP3InitialDPArg getInitialDPArg() {
    return CAP3Codecs.CAP_gsmSSF_gsmSCF_ops_args_InitialDPArg.fromByteArray(getEncodedInitialDPArg());

  private void setInitialDPArg(CAP3InitialDPArg arg) {

For a fixed type but many protocols

For cases where the exact type is not known at compile type - for example, for a service that may deal with many different protocols - a codec can be located at runtime by using the PersistRegistry interface. Each protocol-specific [prefix]Codecs class defines a static field named REGISTRY that is a PersistRegistry instance populated with codecs for that particular protocol.

Services can then perform three steps to encode or decode a value:

  1. Locate the registry for the protocol in use;
  2. Ask the registry for a suitable codec for a given argument type;
  3. Use the returned codec to encode or decode the value.

For example:

  // CMP abstract methods
  public abstract byte[] getEncodedInitialDPArg();
  public abstract void setEncodedInitialDPArg(byte[] value);

  // Map of protocol names to registries.
  // If the service only needs to persist a small number of types, it
  // may be more efficient to store resolved PersistCodec instances directly
  // in a map, rather than asking the PersistRegistry for a codec each time.

  private static final Map<String,PersistRegistry> registryByProtocolMap =
    new HashMap<String,PersistRegistry>();
  static {
    registryByProtocolMap.put("etsi_inap_cs1", CS1Codecs.REGISTRY);
    registryByProtocolMap.put("cap_v1", CAP1Codecs.REGISTRY);
    registryByProtocolMap.put("cap_v2", CAP2Codecs.REGISTRY);
    registryByProtocolMap.put("cap_v3", CAP3Codecs.REGISTRY);

  // Locate a suitable registry for the protocol in use on a given dialog.
  private static PersistRegistry getPersistRegistry(Dialog dialog) {
    return registryByProtocolMap.get(dialog.getApplicationContext().getProtocol());

  // Wrapper methods that perform encoding/decoding
  private CCInitialDPArg getInitialDPArg(Dialog dialog) {
    PersistRegistry registry = getPersistRegistry(dialog);
    return registry.getCodec(CCInitialDPArg.class).fromByteArray(getEncodedInitialDPArg());

  private void setInitialDPArg(Dialog dialog, CCInitialDPArg arg) {
    PersistRegistry registry = getPersistRegistry(dialog);


The persist API is packaged as a number of SLEE library jars. These libraries are not deployed by default, as they are quite large. Services that wish to use the persist API should:

  • Declare a dependency on the appropriate library in their deployment descriptor. For example, when using the CAP v3 persist API, add a dependency on:
      <library-name>CAP v3 Persist API</library-name>
  • Ensure that all required DUs are deployed before deploying the service:
    • protobuf-library-*.du.jar - the GPB support library
    • cgin-persist-*.du.jar - the CGIN persist API support library
    • [protocol].persist.*.du.jar - the protocol-specific persist libraries

These DUs are not deployed by default, as they are quite large. Services that wish to use these APIs should declare a dependency on the persist libraries they use, and ensure that the corresponding DUs are deployed before the service is deployed.

Representation as a Google Protocol Buffers message

Internally, the encoding and decoding of objects is implemented by mapping each CGIN object to an intermediate form that is a Google Protocol Buffers message, and then using the standard GPB encoding to encode and decode the messages. As a convenience for services that wish to embed the messages in a larger GPB message, PersistCodec also offers additional methods that translate between CGIN objects and the intermediate message form.

Each PersistCodec has a type parameter identifying the intermediate GPB message type. The definitions of the GPB messages are included as .proto files within the protocol- specific library jars, for use within larger message definitions. The protocol-specific library jars also include a compiled version of the message definitions.