Saturday 19 May 2007

WAS Startup and Eclipse/OSGI

I couldn't update the blog last night because I was working late - a distinct lack of Java programmers in a building of 1200 people!

To really understand what goes on with the WAS internals and how Eclipse/OSGI fits in we have to examine the startup. So, lets look first at startServer.sh in /usr/IBM/WebSphere/AppServer. In here we will find references to com.ibm.wsspi.bootstrap.wsLauncher, which used to be wsBootstrap in earlier was implementations:

...
"$JAVA_HOME"/bin/java \
"$OSGI_INSTALL" "$OSGI_CFG" \
$X_ARGS \
$WAS_DEBUG \
$CONSOLE_ENCODING \
$D_ARGS \
-classpath "$WAS_CLASSPATH" \
$USER_INSTALL_PROP \
$JVM_EXTRA_CMD_ARGS \
com.ibm.ws.bootstrap.WSLauncher \
$SHELL "$CONFIG_ROOT" "$WAS_CELL" "$WAS_NODE" "$@" $WORKSPACE_ROOT_PROP
...

The $SHELL variable refers to the management tools, (JMX?) that we will look at one another day i.e.

# Bootstrap values ...
SHELL=com.ibm.ws.management.tools.WsServerLauncher

The other environment variables refer to the configuration for the given profiles, i.e. the XML files (server.xml, serverindex.xml, etc).

In the past the bootstrap class used to check for license information, setup platform specific configuration for iSeries and zOS, and then used to load the WAS runtime, but the key change now is the relationship with OSGI/Eclipse.

To explore further just jar the file that contains the plug for com.ibm.ws.bootstrap.WSLauncher, i.e. go to the plugins directory and open up com.ibm.ws.bootstrap_6.1.0.jar. Look at the structure created and open up plugin.xml.

created: META-INF/
extracted: META-INF/MANIFEST.MF
created: com/
created: com/ibm/
created: com/ibm/ws/
created: com/ibm/ws/bootstrap/
created: com/ibm/ws/extension/
created: com/ibm/ws/extension/thinregistry/
created: com/ibm/ws/runtime/
created: com/ibm/ws/runtime/service/
created: com/ibm/ws/runtime/service/impl/
created: com/ibm/wsspi/
created: com/ibm/wsspi/bootstrap/
created: com/ibm/wsspi/bootstrap/osgi/
created: com/ibm/wsspi/extension/
created: com/ibm/wsspi/runtime/
created: com/ibm/wsspi/runtime/service/
created: schema/
inflated: com/ibm/ws/bootstrap/ClassLoaderGateway$1.class
inflated: com/ibm/ws/bootstrap/ClassLoaderGateway$2.class
inflated: com/ibm/ws/bootstrap/ClassLoaderGateway$3.class
inflated: com/ibm/ws/bootstrap/ClassLoaderGateway.class
inflated: com/ibm/ws/bootstrap/ProtectionMetaData.class
inflated: com/ibm/ws/extension/ExtensionRegistryFactoryImpl.class
inflated: com/ibm/ws/extension/thinregistry/ConfigurationElement.class
inflated: com/ibm/ws/extension/thinregistry/ConfigurationProperty.class
inflated: com/ibm/ws/extension/thinregistry/Constants.class
inflated: com/ibm/ws/extension/thinregistry/Extension.class
inflated: com/ibm/ws/extension/thinregistry/ExtensionPoint.class
inflated: com/ibm/ws/extension/thinregistry/ExtensionRegistry.class
inflated: com/ibm/ws/extension/thinregistry/PluginDescriptor.class
inflated: com/ibm/ws/extension/thinregistry/PluginModelObject.class
inflated: com/ibm/ws/extension/thinregistry/PluginParser.class
inflated: com/ibm/ws/extension/thinregistry/RegistryLoader$1.class
inflated: com/ibm/ws/extension/thinregistry/RegistryLoader.class
inflated: com/ibm/ws/extension/thinregistry/RegistryResolver.class
inflated: com/ibm/ws/extension/thinregistry/ResourceHelper.class
inflated: com/ibm/ws/extension/thinregistry/Status.class
inflated: com/ibm/ws/runtime/service/impl/BundleContextMap.class
inflated: com/ibm/wsspi/bootstrap/InvocationHandler.class
inflated: com/ibm/wsspi/bootstrap/WSLauncher.class
inflated: com/ibm/wsspi/bootstrap/osgi/WsBundleActivator.class
inflated: com/ibm/wsspi/extension/ExtensionRegistryFactory$Implementation.class
inflated: com/ibm/wsspi/extension/ExtensionRegistryFactory.class
inflated: com/ibm/wsspi/runtime/service/WsServiceRegistry$1.class
inflated: com/ibm/wsspi/runtime/service/WsServiceRegistry$2.class
inflated: com/ibm/wsspi/runtime/service/WsServiceRegistry.class
inflated: plugin.xml
inflated: schema/applications.exsd
inflated: schema/invocationHandler.exsd

The directory structure shows classnames that relate to a lightweight Eclipse Extension Registry manager and an Eclipse OSGI application, particularly the WsBundleActivator that provides the OSGI start and stop methods as in Eclipse RCP applications, the Service registry for registering services as for OSGI, and the Extension, ExtensionPoint, ExtensionRegistry, and RegistryLoader classes. So, starting with plugin.xml:

...
<extension
id="WSLauncher"
point="org.eclipse.core.runtime.applications">
<application>
<run class="com.ibm.wsspi.bootstrap.WSLauncher"/>
</application>
</extension>

<extension-point id="applications" name="applications" schema="schema/applications.exsd"/>
<extension-point id="invocationHandlers" name="InvocationHandlers" schema="schema/invocationHandler.exsd"/>
<extension-point id="manual-bundle-start" name="Manual Bundle Starter"/>
<extension-point id="resource-file" name="Resource File"/>
...

Yes, WAS is basically like an RCP application in that extends org.eclipse.core.runtime.applications. The class that extends this is com.ibm.wsspi.bootstrap.osgi.WsBundleActivator, and like all "plugins"/RCP applications that extend this and implement the BundleActivator interface the class must provide start() and stop() methods that receive BundleContext objects to interoperate with the Eclipse/OSGI runtime. These methods in the world of OSGI are usually used to initiate the registration and running of services, which is where the WSServiceRegistry classes we unzipped above come in. Ahh, but we've jumped ahead..... This is how it works in the case of an Eclipse RCP or OSGI application as outlined in books like "Eclipse Rich Client Platform", but what loads the Eclipse/OSGI runtime and how do we get to the WsBundleActivator from WSLauncher? Well, the WSLauncher class has a main method, that does all of the argument and license checking functions of earlier releases of WAS, but then checks to see if it is running inside an Eclipse runtime, and if it isn't it creates its own thin, lightweight runtime and runs its extensions and plugins upon it. It then offers up its own extension points as seen in the plugin.xml file.

So, it seems to me that WAS is essentially similar to an Eclipse RCP/OSGI application, but if has both a full Eclipse 3.1.2 runtime and a lightweight one, and applications can use JNDI to provide further plugin services that extend the exposed extesnion points. This new implementaion allows IBM to easily extend WAS and to even support multiple versions. Its a nice architecture...

To get a better understanding read the following books:

  • The Java Developers Guide to Eclipse - D'Anjou et al

  • Eclipse Rich Client Platform - McAffer et al

  • Eclipse: Building Commercial Quality Plugins - Clayberg et al

  • Official Eclipse 3.0 FAQs - Barry etc al


  • They are all good books! However, play with code and write something with it. Just even using the wizards to create a simple osgi plugin is useful, as code can be put into the start() and stop() methods of your BundleActivator class and with a simple change to the config.ini and a start clause and you can have the WAS startup outlined above load your own code as an extension of WAS! This is really powerful and can be used to extend WAS even into the base OS!

    Well, goodnight for now. I'll cover more soon in the next installment!

    No comments: