[Java programming language only]

Building eXtreme Scale dynamic plug-ins

WebSphere® eXtreme Scale includes ObjectGrid and BackingMap plug-ins. These plug-ins are implemented in Java™ and are configured using the ObjectGrid descriptor XML file. To create a dynamic plug-in that can be dynamically upgraded, they need to be aware of ObjectGrid and BackingMap life cycle events because they might need to complete some actions during an update. Enhancing a plug-in bundle with life cycle callback methods, event listeners, or both allows the plug-in to complete those actions at the appropriate times.

Before you begin

This topic assumes that you have built the appropriate plug-in. For more information about developing eXtreme Scale plug-ins, see the System APIs and plug-ins topic.

About this task

All eXtreme Scale plug-ins apply to either a BackingMap or ObjectGrid instance. Many plug-ins also interact with other plug-ins. For example, a Loader and TransactionCallback plug-in work together to properly interact with a database transaction and the various database JDBC calls. Some plug-ins might also need to cache configuration data from other plug-ins to improve performance.

The BackingMapLifecycleListener and ObjectGridLifecycleListener plug-ins provide life cycle operations for the respective BackingMap and ObjectGrid instances. This process allows plug-ins to be notified when the parent BackingMap or ObjectGrid and their respective plug-ins might be changed. BackingMap plug-ins implement the BackingMapLifecyleListener interface, and ObjectGrid plug-ins implement the ObjectGridLifecycleListener interface. These plug-ins are automatically invoked when the life cycle of the parent BackingMap or ObjectGrid changes. For more information about life cycle plug-ins, see the Managing plug-in life cycles topic.

You can expect to enhance bundles using the life cycle methods or event listeners in the following common tasks:
  • Starting and stopping resources, such as threads or messaging subscribers.
  • Specifying that a notification occur when peer plug-ins have been updated, allowing direct access to the plug-in and detecting any changes.

Whenever you access another plug-in directly, access that plug-in through the OSGi container to ensure that all parts of the system reference the correct plug-in. If, for example, some component in the application directly references, or caches, an instance of a plug-in, it will maintain its reference to that version of the plug-in, even after that plug-in has been dynamically updated. This behavior can cause application-related problems as well as memory leaks. Therefore, write code that depends on dynamic plug-ins that obtain its reference using OSGi, getService() semantics. If the application must cache one or more plug-ins, it listens for life cycle events using ObjectGridLifecycleListener and BackingMapLifecycleListener interfaces. The application must also be able to refresh its cache when necessary, in a thread safe manner.

All eXtreme Scale plug-ins used with OSGi must also implement the respective BackingMapPlugin or ObjectGridPlugin interfaces. New plug-ins such as the MapSerializerPlugin interface enforce this practice. These interfaces provide the eXtreme Scale runtime environment and OSGi a consistent interface for injecting state into the plug-in and controlling its life cycle.

Use this task to specify that a notification occurs when peer plug-ins are updated, you might create a listener factory that produces a listener instance.

Procedure

  • Update the ObjectGrid plug-in class to implement the ObjectGridPlugin interface.
    This interface includes methods that allow eXtreme Scale to initialize, set the ObjectGrid instance and destroy the plug-in. See the following code example:
    package com.mycompany;
    import com.ibm.websphere.objectgrid.plugins.ObjectGridPlugin;
    ...
    
    public class MyTranCallback implements TransactionCallback, ObjectGridPlugin {
    
        private ObjectGrid og = null;
    
        private enum State {
            NEW, INITIALIZED, DESTROYED
        }
    
        private State state = State.NEW;
    
        public void setObjectGrid(ObjectGrid grid) {
            this.og = grid;
        }
    
        public ObjectGrid getObjectGrid() {
            return this.og;
        }
        void initialize() {
            // Handle any plug-in initialization here.  This is called by
            // eXtreme Scale, and not the OSGi bean manager.
            state = State.INITIALIZED;
        }
        boolean isInitialized() {
            return state == State.INITIALIZED;
        }
    
        public void destroy() {
            // Destroy the plug-in and release any resources.  This 
            // can be callsed by the OSGi Bean Manager or by eXtreme Scale.
            state = State.DESTROYED;
        }
    
        public boolean isDestroyed() {
            return state == State.DESTROYED;
        }
    }
  • Update the ObjectGrid plug-in class to implement the ObjectGridLifecycleListener interface. See the following code example:
    package com.mycompany;
    import com.ibm.websphere.objectgrid.plugins.ObjectGridLifecycleListener;
          import com.ibm.websphere.objectgrid.plugins.ObjectGridLifecycleListener.LifecycleEvent;
          ...
    
          public class MyTranCallback implements TransactionCallback, ObjectGridPlugin, ObjectGridLifecycleListener{
              public void objectGridStateChanged(LifecycleEvent event) {
                  switch(event.getState()) {
                  case NEW:
                  case DESTROYED:
                  case DESTROYING:
                  case INITIALIZING:
                      break;
                  case INITIALIZED:
                      // Lookup a Loader or MapSerializerPlugin using 
                      // OSGi or directly from the ObjectGrid instance.
                      lookupOtherPlugins()
                      break;
                  case STARTING:
                  case PRELOAD:
                      break;
                  case ONLINE:
                      if (event.isWritable()) {
                          startupProcessingForPrimary();
                      } else {
                          startupProcessingForReplica();
                      }
                      break;
                  case QUIESCE:
                      if (event.isWritable()) {
                          quiesceProcessingForPrimary();
                      } else {
                          quiesceProcessingForReplica();
                      }
                      break;
                  case OFFLINE:
                      shutdownShardComponents();
                      break;
                  }
              }
              ...
          }
  • Update a BackingMap plug-in.
    Update the BackingMap plug-in class to implement the BackingMap plu-in interface. This interface includes methods that allow eXtreme Scale to initialize, set the BackingMap instance, and destroy the plug-in. See the following code example:
    package com.mycompany;
    import com.ibm.websphere.objectgrid.plugins.BackingMapPlugin;
    ...
    
    public class MyLoader implements Loader, BackingMapPlugin {
    
        private BackingMap bmap = null;
    
        private enum State {
            NEW, INITIALIZED, DESTROYED
        }
    
        private State state = State.NEW;
    
        public void setBackingMap(BackingMap map) {
            this.bmap = map;
        }
    
        public BackingMap getBackingMap() {
            return this.bmap;
        }
        void initialize() {
            // Handle any plug-in initialization here.  This is called by
            // eXtreme Scale, and not the OSGi bean manager.
            state = State.INITIALIZED;
        }
        boolean isInitialized() {
            return state == State.INITIALIZED;
        }
    
        public void destroy() {
            // Destroy the plug-in and release any resources.  This 
            // can be callsed by the OSGi Bean Manager or by eXtreme Scale.
            state = State.DESTROYED;
        }
    
        public boolean isDestroyed() {
            return state == State.DESTROYED;
        }
    }
  • Update the BackingMap plug-in class to implement the BackingMapLifecycleListener interface.
    See the following code example:
    package com.mycompany;
    
          import com.ibm.websphere.objectgrid.plugins.BackingMapLifecycleListener;
          import com.ibm.websphere.objectgrid.plugins.BackingMapLifecycleListener.LifecycleEvent;
          ...
    
          public class MyLoader implements Loader, ObjectGridPlugin, ObjectGridLifecycleListener{
              ...
              public void backingMapStateChanged(LifecycleEvent event) {
                  switch(event.getState()) {
                  case NEW:
                  case DESTROYED:
                  case DESTROYING:
                  case INITIALIZING:
                      break;
                  case INITIALIZED:
                      // Lookup a MapSerializerPlugin using 
                      // OSGi or directly from the ObjectGrid instance.
                      lookupOtherPlugins()
                      break;
                  case STARTING:
                  case PRELOAD:
                      break;
                  case ONLINE:
                      if (event.isWritable()) {
                          startupProcessingForPrimary();
                      } else {
                          startupProcessingForReplica();
                      }
                      break;
                  case QUIESCE:
                      if (event.isWritable()) {
                          quiesceProcessingForPrimary();
                      } else {
                          quiesceProcessingForReplica();
                      }
                      break;
                  case OFFLINE:
                      shutdownShardComponents();
                      break;
                  }
              }
              ...
          }

Results

By implementing the ObjectGridPlugin or BackingMapPlugin interface, eXtreme Scale can control the life cycle of your plug-in at the right times.

By implementing the ObjectGridLifecycleListener or BackingMapLifecycleListener interface, the plug-in is automatically registered as a listener of the associated ObjectGrid or BackingMap life cycle events. The INITIALIZING event is used to signal that all of the ObjectGrid and BackingMap plug-ins have been initialized and are available for lookup and use. The ONLINE event is used to signal that the ObjectGrid is online and ready to start processing events.