Running and monitoring offline scripts in a Java EE environment using WebSphere Application Server

Offline processing isn't strictly for mainframes. There are many cases, even in the Java™ world, where it makes sense to strategically schedule scripts to run at certain times or under certain conditions, rather than immediately as a direct result of user interaction. This article explains how to submit scripts from within a Java EE environment, and also looks at how security comes into play when running scripts on remote machines. This content is part of the IBM WebSphere Developer Technical Journal.


Tony Efremenko, Certified Master IT Specialist, IBM

Tony Efremenko photoTony Efremenko is a Certified Master IT Specialist with IBM, with over 24 years of experience in the software industry.

developerWorks Contributing author

Vikram Desai (, Solutions Architect, IBM

Vikram Desai photoVikram Desai is an Architect with IBM Business Partner Technical Enablement. He has worked with several IBM Business Partners to enable them on WebSphere Platform. Previously he has worked as part of development teams for WebSphere Portal, NextWeb, Federated NAS, WebSphere Application Server, Encina++/Encina.

18 June 2008


Java Platform, Enterprise Edition (Java EE) 5 enables you to build sophisticated applications to perform all sorts of valuable functions. Generally, these Java EE applications are Web accessible and perform their functions in near real-time. You might think of these applications as being “online,” and the events that these systems process happen immediately as a direct result of your interaction with them.

But what about things that should happen “offline?” Legacy systems make extensive of batch computing power to efficiently process specific informational needs. UNIX®, Linux®, and Windows® systems often have extensive libraries of useful scripts that provide a wide range of important functions, some of which might need to run only sporadically (for example, to perform cleanup or organizational tasks), and others that might take more time to complete than you would typically want a user to wait.

A scheduling technology, such as cron on UNIX, enables such scripts to be scheduled for execution on a time-of-day or day-of-week sort of schedule. But cron isn’t integrated directly with your Java EE environment. Beyond that, you might want to provide a more sophisticated way to control the execution of your scripts. For example, you might want to:

  • Time the script to prevent it from executing too long (an overlong execution might indicate a problem).
  • Prevent multiple copies of the same script from executing concurrently.
  • Submit scripts to run on other servers or invoke a script on a remote server – but be able to do this securely.
  • Get the return code of your script to handle error processing.

In this article, you will see how to submit scripts from a Java EE environment. Equally important, you will also see how to monitor them, time them, and, if necessary, cancel them using standard classes within the Java EE framework. It’s nice to be able to fire a script, but with just a bit more work, you can also ensure that your scripts don’t execute forever or flood your system with unnecessary or dead scripts that haven’t executed yet -- an important difference that’s key to this solution.

The techniques in this article apply to UNIX, Linux, and Windows. The important concepts of both the script submitter bean and the script timer bean (which times the execution of the script using the EJB timer class) are reviewed, and ways to control script instances to prevent runaway or “dead” scripts (those that are submitted to run that will not or should not execute) are explained. This article also discusses how security comes into play, and some of the capabilities of Secure Socket Shell (SSH) to enable scripts to be run on remote computers in a secure environment.

Specifically, this article describes how to:

  • Submit a script from an EJB component using the Java process API.
  • Invoke the EJB Script Timer class to time the execution of a script.
  • Monitor script return codes.
  • Kill scripts that have been executing too long or that are otherwise deemed unnecessary.
  • Submit scripts to remote systems in a secure manner.
  • In general, do all of the above in a secure environment that prevents unwanted submission or snooping by outside parties.

The environment used for the information in this article consists of:

  • IBM Rational® Application Developer V7
  • IBM WebSphere® Application Server V6.1 test environment
  • openSSH version 3.7 on Windows
  • openSSh version, as bundled on AIX®

The application server is run on Windows, and AIX was used to execute the remote scripts.

Alternative solutions

There are other ways to address this situation. For one, IBM WebSphere Extended Deployment Compute Grid (see Resources) offers a full batch processing environment, with step-wise control of job functions, job flow dependencies, and XML-based control language that provides a solution that’s well suited to handle enterprise-level batch requirements. The solution described in this article isn’t meant to replace the functionality of Compute Grid. Rather, this approach is a useful, time-tested, relatively lightweight way to submit and monitor scripts, scales well to meet a variety of needs, and is handy to have in your toolkit.

Class and API overview

To begin, here is an overview of the important Java classes and operating system facilities that are used in this solution:

Java Runtime and Process objects

The Java Process object is central to how Java interacts with the operating system. You can create a new process by invoking the Java Runtime object, which is single instance class provided with every Java runtime. Using the Runtime object, the process instance is created this way:

Listing 1
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);

In this case, cmd is the batch script that can be submitted on the local (same as WebSphere Application Server) machine, or on the SSH client that handles invocation to a remote machine, if you’re using SSH. The format of cmd is the same as you would submit the script if you had typed it in a command window on your local operating system.

Alternatively, you could use the ProcessBuilder object to manage the process. Using that approach, a ProcessBuilder instance manages a collection of process attributes. The start() method creates a new Process instance with those attributes. The new process instance is created in this way:

Listing 2
ProcessBuilder pb = new ProcessBuilder(cmd);
Process proc = pb.start();

For either approach, when dealing with the spawned process, you want to make sure the output and error streams are flushed to prevent deadlocks caused by limited buffer sizes on certain platforms. The output and error can be handled in separate EJB timers, with the timer being spawned as soon as the process instance is created. The details of this approach will not be discussed here, but it is similar to using the timer to monitor the process. (For more details, see the Process object javdocs for methods getInputStream() and getOutputStream().)

Process hashmap

Another important data structure is the process hashmap. This static (global to the application) object is used to store the process objects (and as you’ll see, the timer information) for any script submitted in the system. The stored process object is kept only while the script is actively running.

Listing 3
static Hashtable processTable = new Hashtable();
                  proc = pb.start();
			procID = proc.hashCode();
			processTable.put(procID, proc);

If the script completes normally, fails, or times out, the process object is removed from the process hashmap by the EJB Timer class described next. Using the hashmap in this way ensures that processes submitted to the system are fully managed by the application. This prevents “runaway” or hanging processes from tying up system resources for an inordinate amount of time.

The hashmap is a singleton instance on the standalone application server instance. If the application is run on an application server cluster, a distributed hashmap/cache will need to be used.

EJB Timer class

You can leverage the EJBTimeout feature of EJB components to time the execution of the scripts. Let’s look at the important parts of the timer code. First, the class declaration:

Listing 4
public class ScriptTimerBean implements javax.ejb.SessionBean, TimedObject {

Notice how the bean implements the TimedObject interface. This interface has the important ejbTimeout callback that you will use to manage the process once its time has expired. The ejbTimeout callback is invoked by the EJB container when the timer is expired. Of course, to have a timer expire, you need to start a timer in the first place:

Listing 5
publicvoid initializeTimer(long timeout, String timerName,
Process p) {
		try {
			// Create Your Timer
			TimerService ts = mySessionCtx.getTimerService();
			Timer timer = ts.createTimer(timeout, timerName);
//			 add the process to be monitored to the process Hashmap
			Integer processKey = new Integer(p.hashCode());
			processMap.put(processKey, p);
		} catch (Exception e) {


To start the timer, use the TimerService interface of the session context to get the timer service and create the timer object. With the timer started, you can now look more closely at the code that handles the timer expiration. As mentioned earlier, when the timer has expired, the container will fire the ejbTimeout interface:

Listing 6
publicvoid ejbTimeout(Timer timer) {
		System.out.println("EJBTimeout in ScriptTimerBean..............");
		Integer key = new Integer(Integer.parseInt((String) timer.getInfo()));

		// use the process hashmap to find the process we want to kill
		Process killp = (Process) processMap.get(key);

		// kill process if it is still running
		try {

			if (killp != null) {
				if (killp.exitValue() != 0) {


Since the timer and process objects were correlated with hash keys, you can use the timer expiration to find the process object in the hashmap (Process killp = (Process) processMap.get(key);) and kill it with the destroy method: (killp.destroy();). With the process destroyed, you can now remove it from the process hashmap (processMap.remove(key);).

Secure Socket Shell

This secure command environment is available on UNIX, Linux, and Windows, and provides a secure way to submit scripts that execute on other systems that are remote from your Java EE application server. Using SSH can establish a secure communication channel to a remote server.

If you’re only planning on running scripts on the same machine as your application server, you might not absolutely need SSH, but if you’re trying to submit over a network, SSH provides transport level encryption to protect your traffic, similar to how https does this for your http traffic.

One assumption made here is that you have enabled SSH to invoke remote scripts in such a way that a password is not required to login to a remote machine. Otherwise, your script will fail execution because SSH will be expecting a password prompt. A simple way to do this is to use public key-based authentication under RSA to allow login to a remote machine without specifying a password. (Appendix A includes instructions for doing this in openSSH with RSA encryption to allow secure communications without a password prompt.)

As for obtaining SSH, it is bundled on many AIX and Linux systems, and is available for download on Windows as part of Putty or MKS (see Resources).

Finally, a key part of this solution is that remote scripts executed by SSH can be killed by terminating the process object with a Process.destroy() method (details on this below). This is never a problem for scripts submitted on the same machine as the application server, but we found that on certain releases of openSSH, the kill signals did not propagate correctly to scripts submitted to a *remote* server. The effect was that killing the parent object always killed the SSH client on the localhost, but did not always kill the remote script. We worked around this by associating a tty session with our scripts (“-t”). As for the main pages for SSH, we found that adding multiple “-t” switches forced the tty associate best and ensured that everything worked well. Our scripts ended up looking something like this:

ssh –t –t –l <user> <machine>

The -t switch forces pseudo-tty allocation, and multiple -t options force tty allocation, even if SSH has no local tty.

Java 2 security concerns

When running a script on your local machine, you might be concerned about Java 2 security. To run the scripts locally, the machine where the Java EE application is running must be allowed to execute a script on the local machine, and if your Java 2 security rules prevent this, you will need to update them accordingly. It is often the case that Java 2 security is not enabled if other security measures are in place, such as a firewall or other isolation of the application server in a secure zone. If that is true in your case, there shouldn’t be a problem. The creation of Java 2 security rules is beyond the scope of this paper, so for the sake of simplicity, we will assume that the WebSphere Application Server that houses your script application is behind a firewall in a secure zone, as defined by best practices for server deployment. Of course, security is always a concern, and so you should take the time to review the capabilities of Java 2 security, which WebSphere Application supports.

End-to-end overview

Figure 1 shows an overview of the flow of the script submitter sample application.

Figure 1. ScriptSubmitter application
Figure 1. ScriptSubmitter application

Figure 1. ScriptSubmitter application

Here is an overview of the important components of the sample application (the code for the entire sample application is included in the download file).

Web application: JSPs

JavaServer Pages (JSPs) are used as the view to the application. These JSPs submit the user interaction (clicks and command text) to the controller servlet. Three JSPs are provided in the sample code:

  • SubmitScript.jsp submits the script to the controller servlet, as shown in Listing 7.
    Listing 7
    <form method="post" 
    	type="text" name="CommandName" size="30"><br>
    	type="submit" name="SubmitCommand" value="SubmitCommand">
    	<input type="reset" value="Clear"></form>

    The commandName parameter is the script to be submitted to the ScriptSubmitterController. The path can be either a Windows path to the script:


    or an SSH remote script:

    ssh –t –t –l <user> <remotemachine> /tmp/

    There are also status JSPs (ScriptResult.jsp, ScriptStatus.jsp) that dig out the process object from the Process HashHap and check its exit value. The sample script is written to return zero when it exits successfully, so you can use that to check how things are proceeding.

  • ScriptStatus.jsp invokes the controller servlet to check the exit value for the process. If the process hasn’t completed yet, you receive a status that indicates it is still running. You can then check again or kill the script. It does this by checking the EXITVAL attribute used in theScriptSubmitterController servlet.
    Listing 8
      int exitVal = ((Integer)request.getAttribute("EXITVAL")).intValue();
      System.out.println("exitVal in JSP = " + exitVal);
      if (exitVal == 3) {	
  • ScriptResult.jsp simply indicates that a script has been submitted. This is the response page to the SubmitScript.jsp.

Web Application: ScriptSubmitterController servlet

The ScriptSubmitterController servlet is the Web tier controller for the application. It evaluates the parameters passed in from the JSP and determines which method to call. For example, here’s how the ScriptSubmitterContoller servlet determines how to hand off execution:

Listing 9
Protectedvoid doPost(HttpServletRequest request, HttpServletResponse 
		response) throws 
	ServletException, IOException {
	String command = null;
		if (request.getParameter("SubmitCommand") != null) {
			command = request.getParameter("CommandName");
			if ((command != null ) && !command.equals("")) {
				//execute the script
				int procID = executeScript(command);
           	         // some code was omitted 
		} else {
			if (request.getParameter("GetStatus") != null) {
				int procID = Integer.parseInt((String)
				int exitVal = getStatus(procID);
				System.out.println("The process exitVal is " + exitVal);
				request.setAttribute("EXITVAL", new Integer(exitVal));
				request.setAttribute("ProcessID", new Integer(procID));
                         // some code was omitted
			} else {
				if (request.getParameter("Kill") != null) {
					int procID = Integer.parseInt((String)
					System.out.println("in kill procID = " + procID);
					int exitVal = killProcess(procID);
                    //  some code was omitted

If the request is a SubmitCommand request, the executeScript method of the controller is invoked. Listing 10 shows the executeScript method. Here, the ScriptSubmitterBean is the EJB component invoked from within the Web application:

Listing 10
Int executeScript(String cmd) {
	int procID = 0;
	try {
		InitialContext ic = new InitialContext();
		ScriptSubmitterLocalHome scriptSubmitterHome = 

		ScriptSubmitterLocal scripSubmitter = scriptSubmitterHome.create();
		procID = scripSubmitter.runScript(cmd);
	} catch (Exception e) {
	return procID;

The method does an EJB lookup on the ScriptSubmitter bean’s home interface, and passes the command string (obtained in the JSP) to that bean in the runscript method.

The getStatus(procID) and killProcess(procID) methods similarly invoke EJB methods; the getStatus(procID) method invokes the scriptSubmitter method that checks the exit value of the process, and the killProcess(procID) invokes the method that destroys the process object.

EJB container: ScriptSubmitter bean

The ScriptSubmitterBean is an EJB invoked from within the Web application. The function is encapsulated in a stateless session bean to implement the logic. The ScriptSubmitterBean accepts the script path as a parameter. It uses the parameter to create the process object, stores the process object in the process hashmap, and then invokes the ScriptTimer bean to time the process. It then invokes the timer bean with the callTimer(proc) method.

Listing 11
publicint runScript(String cmd) {
	Runtime rt = Runtime.getRuntime();
		int exitVal = 0;
		int procID = 0;
		try {
			proc = rt.exec(cmd);
			procID = proc.hashCode();
			processTable.put(procID, proc);
			System.out.println("runScript procID1 = " + procID);
		} catch (Exception e) {
			exitVal = -1;

		return procID;


The callTimer method of the ScriptSubmitterBean looks up the TimerBean home interface and starts its initializeTimer method:

Listing 12
publicvoid callTimer(Process myproc) {

		try {
			InitialContext ic = new InitialContext();
			ScriptTimerLocalHome scriptTimerHome = (ScriptTimerLocalHome) ic

			// get a hashcode of the process to use as the timer name
			Integer processKey = new Integer(myproc.hashCode());
			ScriptTimerLocal st = scriptTimerHome.create();

			st.initializeTimer(60000, processKey.toString(), myproc);
		} catch (Exception e) {


Finally, the kill and status methods are used by the ScriptSubmitterController servlet to report on status or kill the process with a process.destroy(). The getStatus method digs out the process object from the process hashmap and checks its exit value:

Listing 13
publicint getStatus(int procID) {
		Process procRef = (Process) processTable.get(procID);

		System.out.println("id = " + procRef.hashCode());
		int exitVal = -1;
		if (procRef != null) {
			try {
				exitVal = procRef.exitValue();
			} catch (IllegalThreadStateException e) {
				System.out.println("Process Still in execution");
				exitVal = 3;
		System.out.println("Process exitVal = " + exitVal);
		if (exitVal == 0) {
			Integer processKey = new Integer(procID);
			callCancelTimer(processKey.toString(), procRef);

		return exitVal;

The killProcess method does the same, but issues a destroy against the object:

Listing 14
publicint killProcess(int procID) {
		System.out.println("EJB kill process" + procID);
		Process procRef = (Process) processTable.get(procID);
		System.out.println("id = " + procRef.hashCode());
		int exitVal = -1;
		try {
			if (procRef != null) {

				Integer processKey = new Integer(procID);
				callCancelTimer(processKey.toString(), procRef);

EJB container: ScriptTimer bean

The ScriptTimer bean is the EJB component that determines how long a script should run before the execution is considered to be “timed out.” As the script is submitted by the Script Submitter class, a call to this EJB starts the execution timer. Listing 15 shows the code that creates the timer in the ScriptSubmitter bean:

Listing 15
publicvoid initializeTimer(long timeout, String timerName,
Process p) {
		try {
			// Create Your Timer
			TimerService ts = mySessionCtx.getTimerService();
			Timer timer = ts.createTimer(timeout, timerName);
//			 add the process to be monitored to the process Hashmap
			Integer processKey = new Integer(p.hashCode());
			processMap.put(processKey, p);
		} catch (Exception e) {


Upon reaching the time out value that is configured in timeout parameter (in this example, 60000, or 1 minute) the ejbTimeout method is fired to:

  • Obtain the process object from the global process hashmap.
  • Kill the process associated with the process object.
  • Remove the process object from the global process hashmap.

The ejbTimeout method was discussed above, but another piece has been added here to cancel the timer if the script is either killed or completes successfully (there’s no reason to let the timer keep running if the script is dead). The cancelTimer method is called from a number of places in the code if you determine that the script should be halted. The cancelTimer method cancels the timer and removes the process object from the global process hashmap.

Listing 16
publicvoid cancelTimer(String timerName, Process proc) {
	try {
		TimerService ts = mySessionCtx.getTimerService();

		Collection timers = ts.getTimers();
		Iterator it = timers.iterator();
		while (it.hasNext()) {
			Timer myTimer = (Timer);
			if ((myTimer.getInfo().equals(timerName))) {
				System.out.println("ScriptTimerBean: Timer cancelled");
	} catch (Exception e) {


	// Now remove the process from the hashmap
		Integer processKey = new Integer(proc.hashCode());

Scripts executing on local or remote system

The scripts can be anything you wish, using SSH for remote invocation with password verification bypassed instead of RSA. Remember, you can run the scripts locally or remotely, but SSH provides the secure way to execute remote.

Rules for writing the scripts

Here are some tips to help you get the most function from your scripts. To illustrate these ideas, try putting up the following script in your submission window:

Ssh –t –t –l <user> <machine> /tmp/

where <user> is the userid of the run-as user, and <machine> is the host name of the target remote machine. As before, the assumption is that you have followed the Password setup procedures in the appendix to eliminate the need for the password, and that the script exists on the remote machine in path /tmp and has been made executable (chmod +x

This script couldn’t be simpler; it just sleeps for five minutes.

Sleep 600

Of course, the sleep command won’t work in Windows, so you can use this as your test script.

Listing 17
@ping -n 2 -w 1000 > nul
@ping -n 600 -w 1000> nul

Other rules include:

  • Scripts should return a return code of 0 if successful, a non-zero value if unsuccessful.
  • The initial script must be 1 line in length in order to accommodate rules for the Java process object. If additional, multi-line script logic is required, the first script can invoke the second script. Script parameter substitution occurs on the first script only.
  • Multiple commands separated by the command separator, typically a semi-colon (;), are not permitted on the initial script’s one line.
  • To avoid password prompts in SSH scripts, security pairs should be set up according to the information found in Appendix A.
  • For JMX-style scripts (those scripts which use wsadmin and jacl), it is essential that the SOAP port for JMX be available to On a single server environment, stopping the server will also stop this SOAP port. So it is recommended that “Test” scripts for single-server WebSphere environments use the “Test Port” style test scripts, which simply look for the availability of port 9080.


In this article, you’ve seen how command line batch scripts can be invoked from Java EE applications using the Java Process object to submit a script to either a local machine or to a remote machine over the network. In addition, you’ve seen how you can monitor the scripts with timers and, if necessary, kill the scripts that were submitted to avoid orphaned processes. This article offers a basic approach that has been tested and used a number of times. If you require a more sophisticated approach, WebSphere Extended Deployment Compute Grid offers a full featured set of batch processing options.


Special thanks to Randall Hollman, Emilio Zegarra, and Cathy Rivi for their help with this article.

Appendix A: Set up SSH key pairs to prevent entering password each time

If you have installed openSSH on your system (see Resources), you can perform the steps below to create an RSA keypair that bypasses the password authentication that SSH requires while still providing a secure environment. The procedure involves setting up RSA keypairs, and passing the public key to the remote system:

  1. Generate they public/private key pair:

    C:\temp\myssh>ssh-keygen -t rsa

    Doing this will generate a dialog similar to this:

    Listing 18
    Generating public/private rsa key pair.
    Enter file in which to save the key (/.ssh/id_rsa):   /* I took this default */
    /.ssh/id_rsa already exists.
    Overwrite (y/n)? y
    Enter passphrase (empty for no passphrase):  /* just hit enter –no passphrase ! */
    Enter same passphrase again:                             /* hit enter again */
    Your identification has been saved in /.ssh/id_rsa.
    Your public key has been saved in /.ssh/
    The key fingerprint is:
    c6:06:be:99:9f:d6:8e:20:03:10:d9:4b:11:a9:8f:ac WCC\efremenk

    This set the keys in c:/.ssh folder.

  2. Copy the public key to the target machine. This example uses scp (secure copy), but any copy command will do. The important thing is the directory on the target machine ~/.ssh (which is basically /.ssh for user “root”, since directory “/” is the “root” home directory. Because everything is not enabled, you are prompted for a password:
    Listing 19
    C:\temp\myssh>scp /.ssh/'s password:           100% |*****************************|   222       00:00
  3. Log into the host machine. SSH is used here to log into the remote machine. Note that you are prompted me for a password, since everything is not yet set up:
    Listing 20
    C:\temp\myssh>ssh's password:
  4. Change to the host’s .ssh directory. For some machines, you might have to create a .ssh directory from “/”.
    Listing 21
    Cd /
    Mkdir .ssh
    Cd .ssh
  5. Stash the public key:
    [root@wccaix11 .ssh]# cat >> authorized_keys
  6. Test that now, when you run the ssh command, no password is required:

    C:\temp\myssh>ssh –l root

    * *
    * Welcome to AIX Version 5.2! *
    * *
    * *
    * *
    * *

Appendix B: Running the samples

  1. Import the Project Interchange file included in the download file into your Rational Application Developer workspace:
    1. Select File => Import Project Interchange.
    2. Navigate to the location where you downloaded the file, then click Select All.
    3. Click Finish when done.
  2. Add the ScriptSubmitter EAR file to your WebSphere Application Server V6.1 test server:
    1. In the server window, right-click WebSphere Application Server 6.1, then select Add and remove projects.
    2. Select ScriptSubmitter.ear, then click Complete.
  3. Start the server by right-clicking WebSphere Application Server 6.1, then select Start.
  4. Create a test script, in either UNIX or Windows:

    For UNIX: in location /tmp, create script that contains this:

    sleep 500

    Don’t forget to make the script executable:

    chmod +x /tmp/

    For Windows: in location C:\temp, create a testSleep.bat script that contains this:

    		@ping -n 2 -w 1000 > nul
    		@ping -n 600 -w 1000> nul
  5. Run the test JSP either by:
    • Selecting ScriptSubmitterArticleWeb => Web Content => SubmitScript, and right click Run As => Run on Server, or
    • Include your script in the command window:

      For UNIX: ssh –t –t –l root <your_machine> /tmp/

      For Windows: C:\temp\testSleep.bat

      In a separate command window watch the script execute:

      For UNIX: ps –ef|grep testsleep

      For Windows: Taskmgr

  6. Search for testSleep.bat. Manage the process using the JSP windows.


Code samplescriptsubmitter_200806.zip22 KB



developerWorks: Sign in

Required fields are indicated with an asterisk (*).

Need an IBM ID?
Forgot your IBM ID?

Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.


All information submitted is secure.

Dig deeper into WebSphere on developerWorks

ArticleTitle=Running and monitoring offline scripts in a Java EE environment using WebSphere Application Server