Runtime startup
Consider the following examples showing stack traces from failed startups. In the example below the XML cell configuration files had invalid permissions.
[14/06/07 21:52:56:874 GMT+00:00] 0000000a FileDocument E ADMR0104E: The system is unable to read document cells/spock44pNode01Cell/cell.xml: java.io.IOException: The file access permissions do not allow the specified action. at java.io.UnixFileSystem.createFileExclusively(Native Method) at java.io.File.checkAndCreate(File.java:1380) at java.io.File.createTempFile(File.java:1469) at com.ibm.ws.management.repository.FileDocument.createTempFile(FileDocument.java:562) at com.ibm.ws.management.repository.FileDocument.read(FileDocument.java:498) at com.ibm.ws.management.repository.FileRepository.extractInternal(FileRepository.java:986) at com.ibm.ws.management.repository.FileRepository.extract(FileRepository.java:958) at com.ibm.ws.management.repository.FileRepository.extract(FileRepository.java:916) at com.ibm.ws.management.repository.FileRepository.extract(FileRepository.java:906) at com.ibm.ws.taskmanagement.task.TaskContainer.<init>(TaskContainer.java:200) at com.ibm.ws.taskmanagement.task.TaskManagementMBean.initialize(TaskManagementMBean.java:74) at com.ibm.ws.runtime.component.ContainerImpl.initializeComponent(ContainerImpl.java:1338) at com.ibm.ws.runtime.component.ContainerImpl.initializeComponents(ContainerImpl.java:1136) at com.ibm.ws.runtime.component.ServerImpl.initialize(ServerImpl.java:347) at com.ibm.ws.runtime.WsServerImpl.bootServerContainer(WsServerImpl.java:177) at com.ibm.ws.runtime.WsServerImpl.start(WsServerImpl.java:139) at com.ibm.ws.runtime.WsServerImpl.main(WsServerImpl.java:460) at com.ibm.ws.runtime.WsServer.main(WsServer.java:59) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:615) at com.ibm.wsspi.bootstrap.WSLauncher.launchMain(WSLauncher.java:183) at com.ibm.wsspi.bootstrap.WSLauncher.main(WSLauncher.java:90) at com.ibm.wsspi.bootstrap.WSLauncher.run(WSLauncher.java:72) at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:226) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:376) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:163) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:615) at org.eclipse.core.launcher.Main.invokeFramework(Main.java:334) at org.eclipse.core.launcher.Main.basicRun(Main.java:278) at org.eclipse.core.launcher.Main.run(Main.java:973) at com.ibm.wsspi.bootstrap.WSPreLauncher.launchEclipse(WSPreLauncher.java:245) at com.ibm.wsspi.bootstrap.WSPreLauncher.main(WSPreLauncher.java:73)
In Example 5-44, the WAS Kerberos and LDAP configuration attempted to connect to an Active Directory Server that was inactive.
Example 5-44 Stack trace: Active Directory server failed connection
14/06/07 21:54:31:986 GMT+00:00] 0000000a exception E com.ibm.ws.wim.adapter.ldap.LdapConnection getDirContext com.ibm.websphere.wim.exception.WIMSystemException: CWWIM4520E The 'javax.naming.CommunicationException: 192.168.200.3:389 [Root exception is java.net.ConnectException: A remote host refused an a ttempted connect operation.]' naming exception occurred during processing. at com.ibm.ws.wim.adapter.ldap.LdapConnection.getDirContext(LdapConnection.java:1348) at com.ibm.ws.wim.adapter.ldap.LdapConnection.search(LdapConnection.java:2451) at com.ibm.ws.wim.adapter.ldap.LdapConnection.checkSearchCache(LdapConnection.java:2374) at com.ibm.ws.wim.adapter.ldap.LdapConnection.search(LdapConnection.java:2550) at com.ibm.ws.wim.adapter.ldap.LdapConnection.searchEntities(LdapConnection.java:2694) at com.ibm.ws.wim.adapter.ldap.LdapAdapter.search(LdapAdapter.java:2721) at com.ibm.ws.wim.ProfileManager.searchRepository(ProfileManager.java:4073) at com.ibm.ws.wim.ProfileManager.searchImpl(ProfileManager.java:891) at com.ibm.ws.wim.ProfileManager.genericProfileManagerMethod(ProfileManager.java:245) at com.ibm.ws.wim.ProfileManager.search(ProfileManager.java:333) at com.ibm.websphere.wim.ServiceProvider.search(ServiceProvider.java:447) at com.ibm.ws.wim.registry.util.UniqueIdBridge.getUniqueUserId(UniqueIdBridge.java:151) at com.ibm.ws.wim.registry.WIMUserRegistry$6.run(WIMUserRegistry.java:349) at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:3731) at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:3813) at com.ibm.ws.wim.security.authz.jacc.JACCSecurityManager.runAsSuperUser(JACCSecurityManager.java: 484) at com.ibm.ws.wim.security.authz.ProfileSecurityManager.runAsSuperUser(ProfileSecurityManager.java :961) at com.ibm.ws.wim.registry.WIMUserRegistry.getUniqueUserId(WIMUserRegistry.java:338) at com.ibm.ws.security.registry.UserRegistryImpl.getUniqueUserId(UserRegistryImpl.java:446) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:615) at com.ibm.rmi.util.ProxyUtil$2.run(ProxyUtil.java:654) at java.security.AccessController.doPrivileged(AccessController.java:241) at com.ibm.rmi.util.ProxyUtil.invokeWithPrivilege(ProxyUtil.java:650) at com.ibm.CORBA.iiop.ClientDelegate.invoke(ClientDelegate.java:1118) at $Proxy1.getUniqueUserId(Unknown Source) at com.ibm.websphere.security._UserRegistry_Stub.getUniqueUserId(_UserRegistry_Stub.java:380) at com.ibm.ws.security.role.RoleBasedConfiguratorImpl.fillMissingAccessIds(RoleBasedConfiguratorIm pl.java:706) at com.ibm.ws.security.role.RoleBasedConfiguratorImpl.loadApplication(RoleBasedConfiguratorImpl.ja va:270) at com.ibm.ws.security.core.distSecurityComponentImpl.configureRoleBasedAuthz(distSecurityComponen tImpl.java:1224) at com.ibm.ws.security.core.distSecurityComponentImpl.initialize(distSecurityComponentImpl.java:37 7) at com.ibm.ws.security.core.distSecurityComponentImpl.startSecurity(distSecurityComponentImpl.java :304) at com.ibm.ws.security.core.SecurityComponentImpl.startSecurity(SecurityComponentImpl.java:101) at com.ibm.ws.security.core.ServerSecurityComponentImpl.start(ServerSecurityComponentImpl.java:281 ) at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:977) at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:673) at com.ibm.ws.runtime.component.ApplicationServerImpl.start(ApplicationServerImpl.java:191) at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:977) at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:673) at com.ibm.ws.runtime.component.ServerImpl.start(ServerImpl.java:485) at com.ibm.ws.runtime.WsServerImpl.bootServerContainer(WsServerImpl.java:191) at com.ibm.ws.runtime.WsServerImpl.start(WsServerImpl.java:139) at com.ibm.ws.runtime.WsServerImpl.main(WsServerImpl.java:460) at com.ibm.ws.runtime.WsServer.main(WsServer.java:59) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:615) at com.ibm.wsspi.bootstrap.WSLauncher.launchMain(WSLauncher.java:183) at com.ibm.wsspi.bootstrap.WSLauncher.main(WSLauncher.java:90) at com.ibm.wsspi.bootstrap.WSLauncher.run(WSLauncher.java:72) at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:226) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:376) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:163) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:615) at org.eclipse.core.launcher.Main.invokeFramework(Main.java:334) at org.eclipse.core.launcher.Main.basicRun(Main.java:278) at org.eclipse.core.launcher.Main.run(Main.java:973) at com.ibm.wsspi.bootstrap.WSPreLauncher.launchEclipse(WSPreLauncher.java:245) at com.ibm.wsspi.bootstrap.WSPreLauncher.main(WSPreLauncher.java:73)
For both Example 5-43 and Example 5-44, the bottom of the stack is the same.
It highlights the underlying Eclipse/OSGI runtime startup that launches the WAS runtime; the bottom of the stack is shown in Example 5-45.
Example 5-45 Stack trace: Eclipse/OSGI runtime startup
at com.ibm.wsspi.bootstrap.WSLauncher.launchMain(WSLauncher.java:183) at com.ibm.wsspi.bootstrap.WSLauncher.main(WSLauncher.java:90) at com.ibm.wsspi.bootstrap.WSLauncher.run(WSLauncher.java:72) at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:226) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:376) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:163) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:615) at org.eclipse.core.launcher.Main.invokeFramework(Main.java:334) at org.eclipse.core.launcher.Main.basicRun(Main.java:278) at org.eclipse.core.launcher.Main.run(Main.java:973) at com.ibm.wsspi.bootstrap.WSPreLauncher.launchEclipse(WSPreLauncher.java:245) at com.ibm.wsspi.bootstrap.WSPreLauncher.main(WSPreLauncher.java:73)
This stack traces start with the com.ibm.wsspi.bootstrap.WSPreLauncher class and its main method. All Java processes are started by a class with a main method as its entry point.
This main method calls the launchEclipse method to initiate the Eclipse/OSGI runtime startup. The org.eclipse.core.* classes are used to launch the Eclipse/OSGI runtime.
Finally, the com.ibm.wsspi.bootstrap.WSLauncher class has a launchMain method that starts the WAS runtime. The WAS runtime comes into play from the WsServer classes upwards until the containers themselves have started, as illustrated in Example 5-46.
Example 5-46 Stack trace snippet: WAS runtime startup
at com.ibm.ws.security.core.ServerSecurityComponentImpl.start(ServerSecurityComponentImpl.java:281 ) at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:977) at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:673) at com.ibm.ws.runtime.component.ApplicationServerImpl.start(ApplicationServerImpl.java:191) at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:977) at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:673) at com.ibm.ws.runtime.component.ServerImpl.start(ServerImpl.java:485) at com.ibm.ws.runtime.WsServerImpl.bootServerContainer(WsServerImpl.java:191) at com.ibm.ws.runtime.WsServerImpl.start(WsServerImpl.java:139) at com.ibm.ws.runtime.WsServerImpl.main(WsServerImpl.java:460) at com.ibm.ws.runtime.WsServer.main(WsServer.java:59)
Although this seems relatively straightforward, recognize that these examples sample the stack from a single thread. A real implementation is more complex. The extra complexity comes from the use of the Eclipse/OSGI runtime, but brings with it benefits in extensibility and memory management improvements.
To understand how WAS starts up, examine the startServer.sh file from the /usr/IBM/WebSphere/AppServer/bin directory. Although there are similarly named files for the profiles that start the instances, this file does most of the work as the profile versions reference it.
The setup is complex, particularly the setup of the command line, which is accomplished by a combination of this shell script and the setupCmdLine.sh script that sets up the classpath and other directories, including the lib directory startup.jar and bootstrap.jar files on the classpath.
This startup.jar file is the same startup.jar file that comes with the Eclipse 3.1.2 runtime for AIX/Motif and, as mentioned previously, starts the Eclipse platform runtime. Here is the actual command line that starts up WAS:
"$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" "$WebSphere Application Server _CELL" "$WAS _NODE" "$@" $WORKSPACE_ROOT_PROPBy examining at the ps command output, you can find the expanded version of this command line, with all variables substituted, as shown in Example 5-47.
Example 5-47 Sample full WAS startup command syntax
/usr/IBM/WebSphere/AppServer/java/bin/java -Declipse.security -Dwas.status.socket=34929 -Dosgi.install.area=/usr/IB M/WebSphere/AppServer -Dosgi.configuration.area=/usr/IBM/WebSphere/AppServer/profiles/testwas/configuration -Djava.awt.headless=true -Dosgi.framework.extensions=com .ibm.cds -Xshareclasses:name=webspherev61_%g,groupAccess,nonFatal -Xscmx50M -Xbootclasspath/p:/usr/IBM/WebSphere/AppServer/java/jre/lib/ext/ibmorb.jar:/usr/IBM/WebS phere/AppServer/java/jre/lib/ext/ibmext.jar -classpath /usr/IBM/WebSphere/AppServer/profiles/testwas/properties:/usr/IBM/WebSphere/AppServer/propertie s:/usr/IBM/Web Sphere/AppServer/lib/startup.jar:/usr/IBM/WebSphere/AppServer/lib/bootstrap.jar:/usr/IBM/WebSph ere/AppServer/lib/j2ee.jar:/usr/IBM/WebSphere/AppServer/lib/lmproxy.j ar:/usr/IBM/WebSphere/AppServer/lib/urlprotocols.jar:/usr/IBM/WebSphere/AppServer/deploytool/it p/batchboot.jar:/usr/IBM/WebSphere/AppServer/deploytool/itp/batch2.ja r:/usr/IBM/WebSphere/AppServer/java/lib/tools.jar -Dibm.websphere.internalClassAccessMode=allow -Xms50m -Xmx256m -Dws.ext.dirs=/usr/IBM/WebSphere/AppServer/java/lib :/usr/IBM/WebSphere/AppServer/profiles/testwas/classes:/usr/IBM/WebSphere/AppServer/classes:/us r/IBM/WebSphere/AppServer/lib:/usr/IBM/WebSphere/AppServer/installedC hannels:/usr/IBM/WebSphere/AppServer/lib/ext:/usr/IBM/WebSphere/AppServer/web/help:/usr/IBM/Web Sphere/AppServer/deploytool/itp/plugins/com.ibm.etools.ejbdeploy/runt ime -Dderby.system.home=/usr/IBM/WebSphere/AppServer/derby -Dcom.ibm.itp.location=/usr/IBM/WebSphere/AppServer/bin -Djava.util.logging.configureByServer=true -Duser .install.root=/usr/IBM/WebSphere/AppServer/profiles/testwas -Djavax.management.builder.initial=com.ibm.ws.management.PlatformMBeanServerBuilder -Dwas.install.root=/ usr/IBM/WebSphere/AppServer -Dpython.cachedir=/usr/IBM/WebSphere/AppServer/profiles/testwas/temp/cachedir -Djava.util.logging.manager=com.ibm.ws.bootstrap.WsLogMana ger -Dserver.root=/usr/IBM/WebSphere/AppServer/profiles/testwas -Dcom.ibm.ws.security.spnego.isEnabled=true -Djava.security.auth.login.config=/usr/IBM/WebSphere/App Server/profiles/testwas/properties/wsjaas.conf -Djava.security.policy=/usr/IBM/WebSphere/AppServer/profiles/testwas/properties/server.policy com.ibm.wsspi.bootstrap .WSPreLauncher -nosplash -application com.ibm.ws.bootstrap.WSLauncher com.ibm.ws.runtime.WsServer /usr/IBM/WebSphere/AppServer/profiles/testwas/config spock44pNode0 1Cell spock44pNode02 server1
In Example 5-47, note the -Dosgi.framework.extensions=com.ibm.cds system property entry that tells the OSGI framework to enable the com.ibm.cds classloader to facilitate AIX shared classes and thus, improve memory utilization and performance. This com.ibm.cds jar file is loaded by the startup.jar file during its initialization.
Also notice that the com.ibm.wsspi.bootstrap.WSPreLauncher entry at the start of the bold section matches the bottom of our stack dump, as shown in Example 5-45.
Many of the command line setup defaults for the AIX platform can be found in the aix.systemlaunch.properties file inside the com.ibm.ws.runtime_6.1.0.jar JAR file, as shown in Example 5-48.
Example 5-48 Command line setup defaults from aix.systemlaunch.properties file
# Default system properties
# Default environment settings
com.ibm.websphere.management.launcher.defaultEnvironment=EXTSHM=ON
# Default JVM options
com.ibm.websphere.management.launcher.defaultJvmOptions=-Declipse.security -Dosgi.install.area=${WAS _INSTALL_ROOT} -Dosgi.configuration.area=${USER_INSTALL_ROOT}/configuration -Djava.awt.headless=true -Dosgi.framework.extensions=com.ibm.cds -Xshareclasses:name=webspherev61_%g,groupAccess,nonFatal -Xscmx50MKey elements in the command line are the last few parts that identify the actual Java class that runs the Eclipse/OSGI runtime (com.ibm.wsspi.bootstrap.WSPreLauncher from lib/bootstrap.jar); the Eclipse application plug-in that it starts (com.ibm.ws.bootstrap.WSLauncher from lib/bootstrap.jar); and the core runtime that is then loaded to provide the base environment for the rest of WAS (com.ibm.ws.runtime.WsServer from plugins/com.ibm.ws.runtime_6.1.0.jar). The configuration to apply to this for the cell, node, and instance are then applied.
The WSPreLauncher class and its Main method is what runs as the main Java command. It sets up all of the environment variables and properties it needs to be able to run the Eclipse/OSGI runtime environment.
It then runs the Eclipse/OSGI startup, org.eclipse.core.launcher.Main from startup.jar, as can be derived from the command line shown. This standard Eclipse Java code sets up the security, the remainder of the configuration and environment, and then reads the base Eclipse/OSGI configuration from the configuration/config.ini file.
The config.ini file from the standard Eclipse 3.1.2 environment says to load and start org.eclipse.core.runtime and org.eclipse.update.configurator from the plugins directory as standard, and the WAS configuration is no different. The Eclipse/OSGI runtime run from startup.jar loads further plug-ins from the /plugins directory controlled by the configuration/config.ini file, and further configuration in the plugin.xml files.
One of the command line parameters that the WSPreLauncher code passes to the startup.jar Main class is the -application parameter, which identifies the Eclipse Rich Client Platform application to run, as for any other Eclipse RCP application (in this case, com.ibm.ws.bootstrap.WSLauncher).
The WSLauncher class sets up the configuration of the plug-ins, identifies the WAS runtime environment (in this case, as AIX), checks licenses (using the "TimeBomb" class), and sets up classloaders for the Java environment. It also ensures the profile name passed on the command line after it is available.
This class implements the normal Runnable interface so it can run on a separate thread, but it is not a true Eclipse/OSGI executable. The WSLauncher class simply loads the main runtime environment in the plug-in that it finds in the path that is named on the command line.
Now if we run the WSLauncher class itself as a plain Java application, you would receive the message: usage: WSLauncher <className>. So, you can see that the real work is done by the com.ibm.ws.runtime.WsServer class passed as a parameter to it.
To understand what happens next, open up the com.ibm.ws.runtime_6.1.0.jar JAR file that contains the runtime for WAS and look at the directory structure within it. (Remember, it is essentially a zip file.)
The WsServer class is a singleton that passes the real work on to WsServerImpl class, using the strategy pattern to act as its interface. This is a real Eclipse plug-in class that sets up the rest of the environment, that is composed of Eclipse plug-ins with their extensions and extension points, with significant access to the Eclipse platform extension registry.
Interestingly for this class is the amount of code dedicated to making the z/OSŪ implementation appear to function the same as other versions and to provide z/OS extensions, all referred to using ws390 and z/OS methods and classes. In this class, the components and containers that form the core of a J2EE environment are started. Then, a number of other classes are used to perform tasks, such as create thread pools, set up JMX management, and so on, from the components that are started. The configuration in the server.xml file provides the specific setup of the application server instance and the components it loads using the plugin.xml to identify the components that can be loaded in the container and the order in which they load.
However, the threads of execution do not reveal much about what has been happening in the background to create the runtime environment for WAS. Remember, the Eclipse/OSGI runtime is now running, as started in WSPreLauncher, and it has read its configuration file. It has been reading the plugin.xml and MANIFEST.MF files of the plug-in jar files in the plugins directory to determine what needs to be loaded. This is all happening in the background on a thread within Eclipse, which is why the WSLauncher environment identified by the -application command line argument has its own thread.
The key to knowing where code executes next lies in understanding the Eclipse/OSGI environment. Every OSGI bundle that is a runnable application has an Activator class that supports the start and stop methods to hook the startup and shutdown of the "application" (the com.ibm.ws.runtime.WsServer environment, in this case).
Looking at the MANIFEST.MF file that is part of the com.ibm.ws.runtime_6.1.0.jar file, notice that the startup code is in a class called com.ibm.ws.runtime.component.RuntimeBundleActivator; see Example 5-49.
Example 5-49 MANIFEST.MF: RuntimeBundleActivator
...Bundle-Activator: com.ibm.ws.runtime.component.RuntimeBundleActivatorBundle-Localization: pluginBundle-ManifestVersion: 2Bundle-Name: WS_ServerBundle-SymbolicName: com.ibm.ws.runtime; singleton:=trueBundle-Vendor: IBMBundle-Version: 6.1.0Eclipse-AutoStart: falseJ2EE-DeploymentFactory-Implementation-Class: com.ibm.ws.management.application.j2ee.deploy.spi.factories.DeploymentFactoryImplManifest-Version: 1.0Require-Bundle: com.ibm.ws.bootstrap; visibility:=reexport,org.eclipse.jdt.core...
Also note that the application server runtime is a singleton; that is, only one copy can be loaded, as would be expected for a single application server instance. And the com.ibm.ws.bootstrap bundle code is re-exported for use by components elsewhere. Finally, notice that the Java Developer tools (org.eclipse.jdt.core) are actually used within WAS itself.
IBM uses the strategy pattern to implement most of WAS so the interfaces exposed to the outside world usually are wrappers for other classes and interfaces. In accordance with this, most of the implementation for the RuntimeBundleActivator above can be found in com.ibm.wsspi.bootstrap.osgi.WsBundleActivator in com.ibm.ws.bootstrap_6.1.0.jar, as can be seen in its MANIFEST.MF file; see Example 5-50.
Example 5-50 Implementation of the RuntimeBundleActivator
Bundle-Activator: com.ibm.wsspi.bootstrap.osgi.WsBundleActivatorBundle-Localization: pluginBundle-ManifestVersion: 2Bundle-Name: WebSpherer Bootstrap Plug-inBundle-SymbolicName: com.ibm.ws.bootstrap; singleton:=trueBundle-Vendor: IBMBundle-Version: 6.1.0Eclipse-AutoStart: trueManifest-Version: 1.0Import-Package: org.eclipse.core.runtime,org.osgi.frameworkExport-Package: com.ibm.ws.bootstrap,com.ibm.ws.runtime.service.impl,com.ibm.wsspi.bootstrap,com.ibm.wsspi.bootstrap.osgi,com.ibm.wsspi.extension,com.ibm.wsspi.runtime.service
Remember that the com.ibm.ws.bootstrap_6.1.0.jar file that this MANIFEST.MF file comes from was mentioned in the Require-Bundle entry in the MANIFEST.MF file of the com.ibm.ws.runtime_6.1.0.jar file. This signifies that it is a dependency, so you can be sure that the underlying code for the implementation is already loaded and available.
This simple OSGI activator code implementation simply registers and unregisters the bundle context with the WebSphere services registry. So what actually runs? The Eclipse applications registered in the plugin.xml files run.
When the Eclipse runtime loads, it enumerates all of the jar files and directories under the /plugins directory and examines the plugin.xml or MANIFEST.MF file to set up extension points or extensions that extend other extension points.
In the OSGI world, these plug-ins are bundles that also offer services. The extensions and extension points are handled by the platform extension registry. The services are handled by the OSGI service registry.
During startup of the WAS runtime both are used, but it is not until you get into the com.ibm.ws.runtime_6.1.0.jar code that the service registry gets more heavily used.
Although the plug-ins are being evaluated, those with the Eclipse-AutoStart:true setting (such as those for com.ibm.wsspi.bootstrap.osgi.WsBundleActivator in com.ibm.ws.bootstrap_6.1.0.jar) are actually loaded and their startup code executed. Those without that setting simply have their XML descriptions loaded for later use when referenced.
If we look inside the plugin.xml file for com.ibm.ws.bootstrap_6.1.0.jar, you find that another WSLauncher class is referenced, as shown in Example 5-51, that sets up the Eclipse registry environment for WAS. This was seen in our stack trace earlier, after the EclipseStarter and PlatformActivator classes were brought into play.
Example 5-51 WSLauncher class is referenced to set up registry environment
... <extension id="WSLauncher" point="org.eclipse.core.runtime.applications"> <application> <run class="com.ibm.wsspi.bootstrap.WSLauncher"/> </application> </extension> ...
This extension point tells you that the class com.ibm.wsspi.bootstrap.WSLauncher is designed to be launched as an Eclipse application by the runtime, and it extends the Eclipse IPlatformRunnable interface to allow Eclipse to execute its run method.
Inside this WSLauncher class (which is similar in structure to the earlier WSLauncher class), the run method eventually calls a launchMain method which finds classes that extend the extension point com.ibm.ws.bootstrap.applications and allows them to be run. This time it is the IBM bootstrap environment that executes these mini-applications rather than the native Eclipse runtime, so the dependencies are different. Standard Java reflection code is used to load each of these mini-applications, as you can see in the stack traces.
Eclipse allows individual Eclipse applications, like applets within an application, to run as separate threads of control. These all extend the org.eclipse.core.runtime.applications extension point. If we enumerate all of the extensions found in the internal Eclipse platform registry, you can determine what WAS runs as separate distinct Eclipse applications; see Example 5-52.
Example 5-52 Extensions in Eclipse platform registry
ID: org.eclipse.core.runtime.applicationsExtension:com.ibm.ws.bootstrap.WSLauncherExtension:com.ibm.ws.debug.osgi.StartConsoleExtension:com.ibm.ws.debug.osgi.NoopExtension:com.ibm.ws.runtime.startWsServerExtension:org.eclipse.ant.core.antRunner
The keys to WAS startup itself here are the com.ibm.ws.bootstrap.WSLauncher and com.ibm.ws.runtime.startWsServer classes. Ultimately, the latter of these results, due to the strategy pattern implementation, makes use of code inside the com.ibm.ws.runtime.WsServerImpl class that boots the containers within WAS and makes platform-specific decisions as how the environment should be configured. These applications extend the org.eclipse.core.runtime.applications extension point and so are designed to run on the base Eclipse platform.
Finally, you can distinguish the mini-applications that can run on the base Eclipse platform from those that run on the WAS runtime platform. This can be determined by enumerating the Eclipse registry to examine the extensions for the com.ibm.ws.bootstrap.applications extension point, as shown in Example 5-53.
Example 5-53 Examining extensions for com.ibm.ws.bootstrap.applications extension point
ID: com.ibm.ws.bootstrap.applicationsExtension:com.ibm.ws.migration.WAS PreUpgradeExtension:com.ibm.ws.migration.WAS PostUpgradeExtension:com.ibm.ws.migration.ConvertScriptCompatibilityExtension:com.ibm.ws.migration.ClientUpgradeExtension:com.ibm.ws.runtime.RetrieveSignersExtension:com.ibm.ws.runtime.WsAdminExtension:com.ibm.ws.runtime.CollectManagedObjectMetadataExtension:com.ibm.ws.runtime.WsServerLauncherExtension:com.ibm.ws.runtime.WsServerExtension:com.ibm.ws.runtime.WsServerStopExtension:com.ibm.ws.runtime.ServerStatusExtension:com.ibm.ws.runtime.LaunchBatchCompilerExtension:com.ibm.ws.runtime.LaunchWSAntExtension:com.ibm.ws.runtime.BackupConfigUtilityExtension:com.ibm.ws.runtime.RestoreConfigUtilityExtension:com.ibm.ws.runtime.FindEJBTimersCommandExtension:com.ibm.ws.runtime.CancelEJBTimersCommandExtension:com.ibm.ws.runtime.LaunchClientExtension:com.ibm.ws.runtime.LaunchClientApiExtension:com.ibm.ws.runtime.NodeFederationUtilityExtension:com.ibm.ws.runtime.NodeUninstallPrepExtension:com.ibm.ws.runtime.NodeCleanupUtilityExtension:com.ibm.ws.runtime.NodeRemovalUtilityExtension:com.ibm.ws.runtime.NodeSyncUtilityExtension:com.ibm.ws.runtime.NodeRenameUtilityExtension:com.ibm.ws.runtime.DumpExtensionRegistryExtension:com.ibm.ws.runtime.WsProfileExtension:com.ibm.ws.runtime.WsProfileAdminListenerExtension:com.ibm.uddi.UDDIValueSet
Notice the com.ibm.ws.runtime.WsServer and WsServerLauncher classes that show how the core WAS container environment runs on top of the core WAS runtime, which itself runs on top of the Eclipse/OSGI platform runtime. Many of these extensions can be seen configured in the plugin.xml file for com.ibm.ws.runtime_6.1.0.jar.
In summary, there are two threads of control involved in the WAS startup up to this point:
One thread of control sets up the environment, loads the Eclipse/Equinox/OSGI runtime, and then moves on to do further launching of the environment. After the Eclipse runtime has been started, the second thread of control enumerates the WAS plug-ins to find Eclipse RCP application plug-ins, extensions, and extension points from the enumerated Eclipse plug-ins, and OSGI bundles and services from those plug-ins. For each of these, the MANIFEST.MF or plugin.xml file is read to determine what must be started, what may be started later on request, and what is available to be built on. All of this is used to set up the WAS thin registry or public extension registry in accord with the Eclipse runtime rules, and this can be accessed via JNDI from WAS applications, and the OSGI service registry.
Although the complex layout, duplication, and concurrency leads to confusion regarding how this works and to the impression that this is a work in progress, it is this extensible architecture that allows IBM to extend WAS with new features. And it will form the basis of a future extensible and more efficient WAS runtime.
The WAS runtime start up process is diagrammed in Figure 5-14.
Figure 5-14 WAS runtime startup
At this point you have been shown how the Eclipse registry could be enumerated at runtime, but the process itself has not been explained. To do so, we must generate a plug-in of our own and persuade the WAS Eclipse platform environment to execute it. Note that this activity is not supported for WAS by IBM; we are simply demonstrating how the environment works.
We needed to use an Eclipse plug-in development environment, which is freely available from:
http://www.eclipse.orgFirst we generate a standard plug-in. Then, in the bundle Activator, we change the start method and use the Eclipse registry APIs to do the enumeration, as shown in Example 5-54.
Example 5-54 Custom plug-in
public void start(BundleContext context) throws Exception { super.start(context); System.out.println("Welcome:WAS View called..."); // Get the details of the extension register and enumerate it try { FileWriter outlog = new FileWriter("/tmp/logs/WAS View.log", true); IExtensionRegistry reg = Platform.getExtensionRegistry(); outlog.write("Registry is: " + reg.toString() + "\n"); for (IExtensionPoint point: reg.getExtensionPoints()){ if (!point.getUniqueIdentifier().toLowerCase().equals("null")) { outlog.write("ID: " + point.getUniqueIdentifier() + "\n"); } for (IExtension ext: point.getExtensions()){ if (!ext.getUniqueIdentifier().toLowerCase().equals("null")) { outlog.write("-->Extension:" + ext.getUniqueIdentifier() + "\n"); } } } // Make sure that things get written outlog.flush(); // Finally enumerate the bundles Bundle bundles[] = context.getBundles(); for (Bundle bundle: bundles) { outlog.write("Bundle Name: " + ((bundle.getSymbolicName() != null) ? bundle.getSymbolicName() : "null") + ", ID: " + bundle.getBundleId() + ", State: " + bundle.getState() + "\n"); for (ServiceReference sr: bundle.getRegisteredServices()) { outlog.write("\t-->Service Reference:" + sr.toString() + "\n"); if (sr.getUsingBundles() != null) { for (Bundle b: sr.getUsingBundles()) { outlog.write("\t---->Used By: " + ((b.getSymbolicName() != null) ? b.getSymbolicName() : "null") + "\n"); } } } } outlog.flush(); outlog.close(); } catch (IOException ioe) { ioe.printStackTrace(); } }
When we were ready to deploy, we exported the plug-in and place it in the /plugins directory under WAS. To ensure that our plug-in started when WAS started, we added an entry to the configuration/config.ini file, as shown in Example 5-55.
Example 5-55 Starting the custom plug-in WAS View
... # The startlevel indicates the OSGi start level at which the bundle should run. osgi.bundles=org.eclipse.core.runtime@2:start, org.eclipse.update.configurator@3:start, WAS View@4:start ...
When WAS was now run, output was generated which showed the extension points that allowed the core Web services to be built upon; see Example 5-56. Extensions in feature packs can build on these extension points.
Example 5-56 WAS View plug-in output
ID: com.ibm.wsspi.extension.webservices -->Extension:com.ibm.ws.runtime.wsaddressing_impl-webservices -->Extension:com.ibm.ws.runtime.dynacache-webservices -->Extension:com.ibm.ws.runtime.pmi_rm-webservices -->Extension:com.ibm.ws.runtime.security_wssecurity-webservices -->Extension:com.ibm.ws.runtime.webservices-webservices -->Extension:com.ibm.ws.runtime.i18n-webservices -->Extension:com.ibm.ws.runtime.transaction_impl-webservices
The new WAS 6.1 osgiConsole.sh script loads a command line that allows bundles to be enumerated, started, and stopped. It gives you a view of what WAS has loaded in terms of the OSGI view of bundles and services. It also allows you to see the relationships between the bundles and the services they register, as demonstrated in Example 5-57.
Example 5-57 Using osgiConsole.sh
osgi> status Framework is launched. id Bundle Location State Bundle File Name 0 System Bundle ACTIVE org.eclipse.osgi.framework.internal.core.SystemBundleData@d580d58 1 initial@reference:file:plugins/com.ibm.cds_1.0.0.jar/ RESOLVED BundleData for com.ibm.cds (1) 2 initial@reference:file:plugins/org.eclipse.core.runtime_3.1.2.jar/ ACTIVE BundleData for org.eclipse.core.runtime (2) 3 initial@reference:file:plugins/org.eclipse.update.configurator_3.1.0.jar/ ACTIVE BundleData for org.eclipse.update.configurator (3) 4 update@plugins/com.ibm.ws.bootstrap_6.1.0.jar ACTIVE BundleData for com.ibm.ws.bootstrap (4) 5 update@plugins/com.ibm.ws.debug.osgi_6.1.0.jar ACTIVE BundleData for com.ibm.ws.debug.osgi (5) 6 update@plugins/com.ibm.ws.ejbportable_6.1.0.jar RESOLVED BundleData for com.ibm.ws.ejbportable (6) 7 update@plugins/com.ibm.ws.emf_2.1.0.jar RESOLVED BundleData for com.ibm.ws.emf (7) 8 update@plugins/com.ibm.wsspi.extension_6.1.0.jar RESOLVED BundleData for com.ibm.wsspi.extension (8) 9 update@plugins/com.ibm.ws.runtime.gateway_6.1.0.jar ACTIVE BundleData for com.ibm.ws.runtime.gateway (9) 10 update@plugins/com.ibm.ws.migration_6.1.0.jar RESOLVED BundleData for com.ibm.ws.migration (10) 11 update@plugins/org.eclipse.jdt.core_3.1.2.jar RESOLVED BundleData for org.eclipse.jdt.core (11) 12 update@plugins/com.ibm.ws.security.crypto_6.1.0.jar RESOLVED BundleData for com.ibm.ws.security.crypto (12) 13 update@plugins/com.ibm.ws.runtime_6.1.0.jar ACTIVE BundleData for com.ibm.ws.runtime (13) ... Registered Services {org.osgi.service.packageadmin.PackageAdmin}={service.ranking=2147483647, service.pid=0.org.eclipse.osgi.framework.internal.core.PackageAdminImpl, service.vendor=Eclipse.org, service.id=1} {org.osgi.service.startlevel.StartLevel}={service.ranking=2147483647, service.pid=0.org.eclipse.osgi.framework.internal.core.StartLevelManager, service.vendor=Eclipse.org, service.id=2} {javax.xml.parsers.SAXParserFactory}={service.id=3} {javax.xml.parsers.DocumentBuilderFactory}={service.id=4} {org.eclipse.osgi.service.datalocation.Location}={type=osgi.user.area, service.id=5} {org.eclipse.osgi.service.datalocation.Location}={type=osgi.instance.area, service.id=6} {org.eclipse.osgi.service.datalocation.Location}={type=osgi.configuration.area, service.id=7} {org.eclipse.osgi.service.datalocation.Location}={type=osgi.install.area, service.id=8} {org.eclipse.osgi.service.environment.EnvironmentInfo}={service.ranking=2147483647, service.pid=0.org.eclipse.core.runtime.internal.adaptor.EclipseEnvironmentInfo, service.vendor=Eclipse.org, service.id=9} {org.eclipse.osgi.service.resolver.PlatformAdmin}={service.ranking=2147483647, service.pid=0.org.eclipse.osgi.framework.adaptor.core.StateManager, service.vendor=Eclipse.org, service.id=10} {org.eclipse.osgi.service.pluginconversion.PluginConverter}={service.ranking=21474836 47, service.pid=0.org.eclipse.core.runtime.internal.adaptor.PluginConverterImpl, service.vendor=Eclipse.org, service.id=11} {org.eclipse.osgi.service.urlconversion.URLConverter}={service.ranking=2147483647, service.pid=0.org.eclipse.core.runtime.internal.adaptor.URLConverterImpl, service.vendor=Eclipse.org, service.id=12} {org.eclipse.osgi.framework.console.CommandProvider}={service.ranking=2147483647, service.pid=0.org.eclipse.core.runtime.internal.adaptor.EclipseCommandProvider, service.vendor=Eclipse.org, service.id=13} {org.eclipse.osgi.framework.log.FrameworkLog}={service.ranking=2147483647, service.pid=0.org.eclipse.core.runtime.adaptor.EclipseLog, service.vendor=Eclipse.org, service.id=14} {org.eclipse.osgi.framework.log.FrameworkLog}={service.ranking=-2147483648, performance=true, service.pid=46org.eclipse.core.runtime.adaptor.EclipseLog, service.vendor=Eclipse.org, service.id=15} {org.eclipse.osgi.service.localization.BundleLocalization}={service.ranking=214748364 7, service.pid=0.org.eclipse.core.runtime.internal.adaptor.BundleLocalizationImpl, service.vendor=Eclipse.org, service.id=16} {org.eclipse.osgi.framework.console.CommandProvider}={service.ranking=2147483647, service.id=17} {java.lang.Runnable}={name=splashscreen, service.id=18} {org.eclipse.core.runtime.IExtensionRegistry}={service.id=19} {org.osgi.service.url.URLStreamHandlerService}={url.handler.protocol=[Ljava.lang.Stri ng;@42154215, service.id=20} {org.eclipse.osgi.service.runnable.ParameterizedRunnable}={eclipse.application=defaul t, service.id=21} {org.eclipse.update.configurator.IPlatformConfigurationFactory}={service.id=22}
The output in Example 5-57 shows that most of the OSGI services are registered by the Eclipse/OSGI/Equinox runtime itself, with a particular emphasis on XML (javax.xml.parsers.*) and URL management-related services that provide a general set of infrastructure functions to the rest of the environment.
Note also that the core WAS runtime is bundle 13 in this running WAS environment. From the OSGI Console, a garbage collection can also be manually requested by using the gc command, although the supportability and real use of this in a production setting is yet to be determined.
Although for demonstration purposes in this book, we looked at the unsupported use of Eclipse/OSGI bundles below WAS as a mechanism for seeing how WAS loading works, IBM does support the use of Eclipse/OSGI bundles running in WAS on top of the exported WAS registry. This is covered in the WAS 6.1 documentation:
So, from the WAS startup we obtained a view of the new Eclipse/OSGI architecture and saw how it provides an extensible base. The complexity of the startup path is due to this. Based on statements of direction from IBM as a whole, this is a work in progress as the Eclipse/OSGI (Equinox) architecture is adopted more widely.