XmlBlaster Logo

REQUIREMENT

engine.runlevel.howto

XmlBlaster Logo


Type NEW
Priority HIGH
Status CLOSED
Topic How to write a native client plugin for xmlBlaster
Des
cription

XmlBlaster has a sophisticated runlevel manager to control startup and shutdown of the server. It is possible to write xmlBlaster clients and instead of starting them separately add them to be managed by the runlevel manager. Here follows an example how to write such a native plugin for xmlBlaster. It is started with xmlBlaster, and stopped with xmlBlaster automatically be the runlevel manager.

A plugin needs to implement the I_Plugin interface and you need to register it in the xmlBlasterPlugins.xml configuration file, that's it.

Example
Java

Write your first plugin

Step 1: Write a client plugin


 1 // xmlBlaster/demo/javaclients/ClientPlugin.java
 2 package javaclients;
 3 import org.xmlBlaster.client.I_XmlBlasterAccess;
 4 import org.xmlBlaster.client.XmlBlasterAccess;
 5 import org.xmlBlaster.util.XmlBlasterException;
 6 import org.xmlBlaster.util.MsgUnit;
 7 import org.xmlBlaster.util.plugin.I_Plugin;
 8 import org.xmlBlaster.util.plugin.PluginInfo;
 9 
10 
11 /**
12  * This client is loaded by xmlBlaster as a plugin on startup, it then connects
13  * to xmlBlaster and gets synchronous a message and disconnects. 
14  * <p />
15  * You need to add this plugin to xmlBlasterPlugins.xml.
16  */
17 public class ClientPlugin implements I_Plugin
18 {
19    public void init(org.xmlBlaster.util.Global glob, PluginInfo pluginInfo)
20                                                throws XmlBlasterException {
21       doSomething();
22    }
23 
24    public String getType() {
25       return "ClientPlugin";
26    }
27 
28    public String getVersion() {
29       return "1.0";
30    }
31 
32    public void shutdown() throws XmlBlasterException {
33    }
34 
35    /**
36     * We login to xmlBlaster and check the free memory
37     */
38    private final void doSomething() {
39       try {
40          I_XmlBlasterAccess con = new XmlBlasterAccess(new String[0]);
41 
42          con.connect(null, null);    // Login to xmlBlaster
43 
44          MsgUnit[] msgs = con.get("<key oid='__cmd:?freeMem'/>", null);
45 
46          System.out.println("\n###ClientPlugin###: xmlBlaster has currently " +
47                 new String(msgs[0].getContent()) + " bytes of free memory\n");
48 
49          con.disconnect(null);
50       }
51       catch (Exception e) {
52          System.err.println("ClientPlugin: We have a problem: " + e.toString());
53       }
54    }
55 }
   

This is a very simple plugin, it implements the I_Plugin interface and is therefor forced to implement the methods getType() which returns the unique name of the plugin which is later used to register, getVersion() which returns an arbitrary version number, init() which is called after creating the plugin and shutdown() which is called before unloading the plugin.

On line 38 we do some client specific code, here we login to xmlBlaster and check the used memory, then the plugin logs out and does nothing any more. Note that this plugin communicates over the default protocol CORBA with the server which is a bit of overkill. See requirement protocol.local how to connect natively as we are in the same JVM.

Step 2: Register our plugin in xmlBlasterPlugins.xml

First copy the xmlBlasterPlugins.xml file to your home directory, the following example is for UNIX, on Windows it is similar:

cp xmlBlaster/config/xmlBlasterPlugins.xml.template  $HOME/xmlBlasterPlugins.xml
     
<xmlBlaster>
   ...
   <plugin id='ClientPlugin' className='javaclients.ClientPlugin'>
      <action do='LOAD' onStartupRunlevel='9'/>
      <action do='STOP' onShutdownRunlevel='6'/>
   </plugin>
   ...
</xmlBlaster>
     

In this configuration we tell the runlevel manager to load our plugin at the end of the startup sequence (9) and unload it in runlevel 6 again on shutdown of the server

Example
Java

Deploying to a running server

This example shows how to deploy a plugin without restarting xmlBlaster

Note: This feature has a high security risc as any authorized client can inject any code into the xmlBlaster server. This code is executed with the rights of the user running the xmlBlaster server. Therefore this features is switched off as a default setting with xmlBlaster/allowDynamicPlugins=false.

You can send a xmlBlaster message containing the plugin jar file (with your coded plugin) and the xml markup to register the plugin. XmlBlaster than automatically extends its classpath with your jar file and loads the plugin according to your xml configuration.

Here is an example using our HelloWorldPublish demo client to send such a plugin. First create a jar file with

jar cvf dynamic.jar javaclients/ClientPlugin.class

and we will use this xml configuration for registration

   <plugin id='ClientPlugin' className='javaclients.ClientPlugin'>
      <action do='LOAD' onStartupRunlevel='9'/>
      <action do='STOP' onShutdownRunlevel='6'/>
   </plugin>

The LOAD directive is not important in this case as xmlBlaster is already up and running, there for we leave it away in the following command line example.

Start the xmlBlaster server with dynamic plugins enabled:

  java org.xmlBlaster.Main -xmlBlaster/allowDynamicPlugins true                 

Now we are ready to send the plugin to a already running xmlBlaster server (all in one line):

  java javaclients.HelloWorldPublish \
     -oid __sys__RunlevelManager \
     -contentFile dynamic.jar \
     -clientProperty[__plugin.jarName] dynamic.jar \
     -clientProperty[__plugin.xml] \
         "<plugin create='true' id='ClientPlugin' className='javaclients.ClientPlugin'> \
            <action do='STOP' onShutdownRunlevel='6'/> \
          </plugin>"

To register a plugin you need to send it to the topic __sys__RunlevelManager, the message content contains the jar file.
We use a client property __plugin.jarName to pass a nice name for the jar file, this is optional. The jar file will be dumped by the xmlBlaster server to the root directory of its CLASSPATH.

Finally, the client property __plugin.xml contains the configuration for registering the plugin.

After sending the above message, you should see some server output telling you about the successful registration.

Note that the registration is not persistent, on server restart the plugin is lost. If you wish to use the plugin permanently you need to register it in xmlBlasterPlugins.xml as well.

Please use JMX (for example the jconsole GUI, see the admin.jmx requirement) to control the plugin when running in xmlBlaster.

Configure
Property Default Description Implemented
xmlBlaster/allowDynamicPlugins false Switching this feature on has a very high security risk, as any code can be injected. This settings needs to be set on startup and can't be changed during a running server. yes

NOTE: Configuration parameters are specified on command line (-someValue 17) or in the xmlBlaster.properties file (someValue=17). See requirement "util.property" for details.
Columns named Impl tells you if the feature is implemented.
Columns named Hot tells you if the configuration is changeable in hot operation.

See REQ engine.runlevel
See REQ protocol.local
See REQ admin.jmx
See API javaclients.HelloWorldNative
See http://www.xmlBlaster.org/xmlBlaster/demo/javaclients/HelloWorldNative.java.html
See API javaclients.HelloWorldNative2
See http://www.xmlBlaster.org/xmlBlaster/demo/javaclients/HelloWorldNative2.java.html
See API org.xmlBlaster.engine.runlevel.RunlevelManager
See API org.xmlBlaster.engine.runlevel.I_RunlevelListener

This page is generated from the requirement XML file xmlBlaster/doc/requirements/engine.runlevel.howto.xml

Back to overview