Writing a WebLogic Startup Class
October 4, 2001
Copyright © 2001
Stephen Davies
Introduction
This paper presents a tutorial on writing a startup class for WebLogic 6.x. It is targeted at developers who would like to use this WebLogic proprietary feature. It covers code creation and deployment into the WebLogic runtime system.
The topic of application specific data is frequently discussed in the J2EE and WebLogic newsgroups. All applications have a requirement to place frequently accessed, read-mostly global data somewhere that it can be easily used. The usual answer to these kinds of questions is to place the global data into JNDI. Why? because the powers that be, the ones who write the specs, have decided that this is the accepted way of doing it.
So? If the accepted way of of making global application data available is to place it into the naming service (JNDI) then how can this be done? Easy, implement a startup class and have WebLogic invoke it as part of its runtime initialization. This can be summarized as:
Create and compile the startup class
Place the startup class on the servers classpath
Register the startup class via the console
Start the server
Creating the Startup Class
It all begins with the creation of the startup class. BEA have made this quite straight forward, simply create a class that implements the interface weblogic.common.T3StartupDef. If you're wondering about the 'T3', the unofficial word is that it stands for Tengah 3, which I believe was the old name for the product before the WebLogic company was purchased by BEA. It used to be Tengah by WebLogic, now its WebLogic by BEA.
Create the class and implement the two callback methods. The first of these is the setServices method. The T3ServicesDef parameter is an object that gives you access to WebLogic proprietary internals, things such as the connection pools, workspaces, time and logging services. Much of this has now become obsolete under J2EE. For example, you use DataSources instead of directly accessing the connection pools. For this example the method can be left as a no-op. If you wanted to access the T3Services as part of your startup logic then you could store the services object in an instance variable.
The bulk of the startup logic is placed into the startup method. The startup method takes two parameters, the registered name and a hashtable. The name is set during deployment and can be used to differentiate between two registered instances of the same startup class. The hashtable contains the arguments, key/value pairs which are specified during configuration. These can be any String values. The String returned by the startup method is placed into the log. The class skeleton looks like this:
public class StartupSample implements T3StartupDef {
public void setServices(T3ServicesDef services) {}
public String startup(String name, Hashtable args) throws Exception {
// do startup actions here
return "message to appear in log";
}
}
The coding of the startup method is quite simple, in this example a context is created within the JNDI tree and any arguments are bound into the new context. It was done this way to prevent name clashes, having a separate context prevents this from happening. Binding the arguments into the JNDI tree demonstrates what is possible and makes it easy to change. You can use the console to modify the actual data being registered into the tree. The full startup method is shown below. The complete startup class source code can be found here.
public String startup(String name, Hashtable args) throws Exception {
System.out.println("Startup class invoked - " + name);
InitialContext ic = new InitialContext();
Context startupContext = ic.createSubcontext("startup");
// bind each argument using its name
Enumeration keys = args.keys();
while(keys.hasMoreElements()) {
String key = (String)keys.nextElement();
String value = (String)args.get(key);
startupContext.bind(key, value);
}
return "ok";
}
Deploying the Startup Class
Setting the Classpath
There is a small trick to getting the startup class to run. It must be placed on the servers classpath. That means that you need to modify the WebLogic startup script. You will need to create a directory to store your classes and place this into the CLASSPATH environment variable. For example you could create the directory path x:\bea\wlserver6.1\custom_classes and modify the startWeblogic.bat file to include it on the classpath. You must be careful which classes you place into this directory, classes loaded from the servers CLASSPATH cannot be hot deployed. If a class changes then the server must be restarted. A startup class cannot be part of a JAR, EAR or WAR file; startup classes are invoked before component classloaders are created.
Registering the Startup Class
Registering the startup class involves starting the WebLogic Server and opening the administration console in a browser. In the Deployments folder you will find the Startup & Shutdown option. From here you can elect to Configure a new Startup class. The configuration values are fairly self explanatory, the name is the String that is passed as the first parameter to the startup method. It can be set to whatever you like. The classname is the fully qualified name of the startup class. The deployment order is a number used to determine startup order when there is more than one startup class. Lowest number goes first.
Arguments allows you specify a comma separated list of key/value pairs. For example, 'abc=1,def=2' is a valid argument string. It identifies the argument 'abc' as having the value '1' and a second key of 'def' having the value '2'. Note that both the key and value are Java Strings. These arguments are passed to the startup method as the hashtable. If for some reason you need to specify a String that contains embedded blanks you must use the double quote character around the space delimited text. The abort startup on failure option will abort the server startup if an exception is thrown by the startup method. Best not to turn this on until you have the class working, if you can't start the server you can't run the console which makes it difficult to modify a poorly configured server.
When you've created the registration don't forget to target it to the server(s) that you want the startup class to run on. When you've finished you will need to restart the WebLogic server.
Summary
Now you know how easy it is to implement a WebLogic startup class. All it takes is 4 easy steps:
Create and compile the startup class
Place the startup class on the servers classpath
Start the server
Register the startup class via the console
Restart the server
Enjoy!
Appendix - Code Samplepackage sjdavies.wls61.startup;
import javax.naming.*;
import weblogic.common.*;
import java.util.Hashtable;
import java.util.Enumeration;
/**
* An example of a WebLogic startup class.
* Binds some sample values into the Naming Service.
*
* The top level context "startup" is created and then the startup
* classes arguments are bound as key/value pairs into this context.
*
* Copyright (c) 2001, Davies Consulting Pty. Ltd.
*
* @author Stephen Davies
*/
public class StartupSample implements T3StartupDef {
public void setServices(T3ServicesDef services) {}
/**
* Bind selected values into the Naming Service.
*/
public String startup(String name, Hashtable args) throws Exception {
System.out.println("Startup class invoked - " + name);
InitialContext ic = new InitialContext();
Context startupContext = ic.createSubcontext("startup");
// bind each argument using its name
Enumeration keys = args.keys();
while(keys.hasMoreElements()) {
String key = (String)keys.nextElement();
String value = (String)args.get(key);
startupContext.bind(key, value);
}
return "ok";
}
}