Last Updated: June 27, 2014
STAF Java support must be installed in order to submit requests to STAF via a Java program or to register a STAF Java service such as STAX, Event, Cron, EventManager, Email, etc.
STAF's Java support is provided in the JSTAF.jar file (located in either C:\STAF\bin\JSTAF.jar (by default) on Windows systems or /usr/local/staf/lib/JSTAF.jar (by default) on Unix systems. The STAF install adds the JSTAF.jar file to the CLASSPATH environment variable.
To verify that the version of Java you are using works with STAF Java support, run TestJSTAF as decribed in section 5.0 How to Test STAF Java Support.
STAF externalizes the following primary classes to Java applications. These classes are:
These classes all reside in the com.ibm.staf package. In order to use them in a Java application, you must import the STAF package like so
import com.ibm.staf.*;
STAF externalizes two wrapper classes. These classes are
These classes all reside in the com.ibm.staf.wrapper package. In order to use them in a Java application, you must import the STAF wrapper package like so
import com.ibm.staf.wrapper.*;
The STAFHandle class is the primary class used to communicate with STAF. It is used to register with STAF, submit service requests to STAF, and unregister with STAF. Each Java application should generally create one and only one STAFHandle object. The act of creating this object registers the Java application with STAF.
There are two constructors for the STAFHandle class:
Once you have a valid STAFHandle instance object, you can begin submitting requests to STAF services by one of two methods:
Note that a STAFHandle instance object has a auto-unmarshall result member variable that defaults to true when a STAFHandle instance object is created, but can be set to false via its setDoUnmarshallResult() method. When set to true, this causes STAF results to be automatically unmarshalled when using the submit2() method.
Before the Java application exits, it should unregister with STAF by calling the unRegister() method.
STAFHandle also defines the following constants which can be used as the syncOption parameter for the submit() and submit2() methods:
package com.ibm.staf; public class STAFHandle { public static final int ReqSync = 0; public static final int ReqFireAndForget = 1; public static final int ReqQueue = 2; public static final int ReqRetain = 3; public static final int ReqQueueRetain = 4; public STAFHandle(String handleName) throws STAFException; public STAFHandle(int staticHandleNumber); public String submit(String where, String service, String request) throws STAFException; public String submit(int syncOption, String where, String service, String request) throws STAFException; public STAFResult submit2(String where, String service, String request); public STAFResult submit2(int syncOption, String where, String service, String request); public void unRegister() throws STAFException; public int getHandle(); // Set a flag to indicates whether the result should be auto-unmarshalled // Added in STAF V3.3.1 public void setDoUnmarshallResult(boolean flag); // Retrieve the auto-unmarshall result flag // Added in STAF V3.3.1 public boolean getDoUnmarshallResult(); }
import com.ibm.staf.*; import java.io.*; public class STAFTest { public static void main(String argv[]) { try { // Create a STAFHandle STAFHandle handle = new STAFHandle("MyApplication"); System.out.println("My handle is: " + handle.getHandle()); try { // Submit a synchronous request to the ECHO service on // the local machine STAFResult result = handle.submit2( "local", "ECHO", "ECHO Hello"); if (result.rc != 0) { System.out.println( "ERROR: STAF local ECHO ECHO Hello failed. RC: " + result.rc + ", Result: " + result.result); } else { System.out.println("ECHO Result: " + result.result); } // Or submit an asynchronous request to the ECHO service on // the local machine result = handle.submit2( STAFHandle.ReqRetain, "local", "ECHO", "ECHO Hello"); if (result.rc != 0) { System.out.println( "ERROR: STAF local ECHO ECHO Hello failed. RC: " + result.rc + ", Result: " + result.result); } else { System.out.println( "Asynchronous ECHO Request number: " + result.result); } } finally { handle.unRegister(); } } catch (STAFException e) { System.out.println( "Error (un)registering with STAF, RC:" + e.rc); System.exit(1); } } // End of main() } // End of STAFTest
import com.ibm.staf.*; public class STAFTest { public static void main(String argv[]) { try { // Create a STAFHandle STAFHandle handle = new STAFHandle("MyApplication"); System.out.println("My handle is: " + handle.getHandle()); // Submit some requests to STAF services String machine = "local"; String service = "PING"; String request = "PING"; try { // Submit a synchronous request to the PING service on // the local machine String result = handle.submit(machine, service, request); System.out.println("PING Result: " + result); // Submit an asynchronous STAF request to the PING service // on the local machine result = handle.submit( STAFHandle.ReqQueueRetain, machine, service, request); System.out.println("PING Request number: " + result); } catch (STAFException e) { System.out.println( "Error submitting STAF " + machine + " " + service + " " + request); System.out.println("RC: " + e.rc); System.out.println(e.getMessage()); } finally { handle.unRegister(); } } catch (STAFException e) { System.out.println( "Error (un)registering with STAF, RC:" + e.rc); System.exit(1); } } // End of main() } // End of STAFTest
import com.ibm.staf.*; public class STAFTest { public static void main(String argv[]) { try { // Create a STAFHandle (non-static) STAFHandle handle = new STAFHandle("MyApplication"); System.out.println("My non-static handle is: " + handle.getHandle()); STAFHandle staticHandle = null; int staticHandleNumber = 0; try { // Create a STAF static handle STAFResult result = handle.submit2( "local", "HANDLE", "CREATE HANDLE NAME MyStaticHandleName"); if (result.rc != STAFResult.Ok) { System.exit(1); } staticHandleNumber = new Integer(result.result).intValue(); staticHandle = new STAFHandle(staticHandleNumber); System.out.println("My static handle is: " + staticHandleNumber); // Request a mutex semaphore using the static STAFHandle to // submit the request System.out.println("Request mutex semaphore MyMutex"); result = staticHandle.submit2( "local", "SEM", "REQUEST MUTEX MyMutex"); if (result.rc != STAFResult.Ok) { System.out.println( "ERROR: STAF local SEM REQUEST MUTEX MyMutex failed. RC: " + result.rc + ", Result: " + result.result); System.exit(1); } // Do whatever else you want to do } finally { if (staticHandleNumber != 0) { // Release the mutex semaphore using the static STAFHandle // to submit the request System.out.println("Release mutex semaphore MyMutex"); STAFResult result = staticHandle.submit2( "local", "SEM", "RELEASE MUTEX MyMutex"); // Delete the static handle System.out.println("Delete static handle"); result = handle.submit2( "local", "HANDLE", "DELETE HANDLE " + staticHandleNumber); } handle.unRegister(); } } catch (STAFException e) { System.out.println( "Error (un)registering with STAF, RC:" + e.rc); System.exit(1); } } // End of main() } // End of STAFTest
import com.ibm.staf.*; import java.util.*; public class STAFTest { public static void main(String argv[]) { try { // Create a STAFHandle STAFHandle handle = new STAFHandle("MyApplication"); System.out.println("My handle is: " + handle.getHandle()); try { // Submit a request to the PROCESS service to run a command on // a machine and wait for it to complete and returns its stdout // and stderr. Note that the result from this request returns // a marshalled map so we'll use STAFResult's resultObj variable // to access the map root object String machine = "local"; String command = "dir \\temp"; String service = "PROCESS"; String request = "START SHELL COMMAND " + STAFUtil.wrapData(command) + " WAIT RETURNSTDOUT STDERRTOSTDOUT"; STAFResult result = handle.submit2(machine, service, request); if (result.rc != 0) { System.out.println( "ERROR: STAF " + machine + " " + service + " " + request + " RC: " + result.rc + ", Result: " + result.result); System.exit(1); } // The command was started successfully. Check the process // return code and if non-zero, also print an error message Map resultMap = (Map)result.resultObj; String processRC = (String)resultMap.get("rc"); if (!processRC.equals("0")) { System.out.println( "ERROR: Process RC is not 0.\n" + result.resultContext); System.exit(1); } // Print the stdout/stderr data for the command List returnedFileList = (List)resultMap.get("fileList"); Map stdoutMap = (Map)returnedFileList.get(0); String stdoutData = (String)stdoutMap.get("data"); System.out.println("Process Stdout:\n" + stdoutData); } finally { handle.unRegister(); } } catch (STAFException e) { System.out.println( "Error (un)registering with STAF, RC:" + e.rc); System.exit(1); } } // End of main() } // End of STAFTest
The STAFException class is the exception class thrown by the STAFHandle class. It contains an rc variable which contains the actual return code from STAF. You may use the standard Throwable method getMessage() to retrieve any extra information provided by STAF.
package com.ibm.staf; public class STAFException extends Exception { public STAFException(); public STAFException(int theRC); public STAFException(int theRC, String s); public int rc; }
import com.ibm.staf.*; try { STAFHandle handle = new STAFHandle("MyApplication"); System.out.println("My handle is: " + handle.getHandle()); } catch (STAFException e) { System.out.println("Error registering with STAF, RC: " + e.rc); System.exit(1); }
The STAFResult class is returned by the STAFHandle.submit2() method. It contains both the STAF return code as well as the result string. In addition, if auto-unmarshalling is enabled for the handle (which it is by default), the STAFResult object also contains the marshalling context for the result (e.g. the unmarshalled result) and the result object (e.g. the root object of the marshalling context). Otherwise, if auto-unmarshalling is disabled for the handle that called the submit2() method, the resultContext and resultObj fields will be set to null. It is typically used in places where you wish to avoid catching exceptions when using STAF or where you want the result to be auto-unmarshalled. This class also contains the constant definitions for all the STAF return codes. These return codes are common to STAFResult and STAFException.
package com.ibm.staf; public class STAFResult { STAFResult(); STAFResult(int theRC); STAFResult(int theRC, String theResult); // Added in STAF V3.3.1 STAFResult(int theRC, String theResult, boolean doUnmarshallResult); public int rc; public String result; public Object resultObj = null; // Added in STAF V3.3.1 public STAFMarshallingContext resultContext = null; // Added in STAF V3.3.1 public static final int Ok = 0; public static final int InvalidAPI = 1; public static final int UnknownService = 2; public static final int InvalidHandle = 3; public static final int HandleAlreadyExists = 4; public static final int HandleDoesNotExist = 5; public static final int UnknownError = 6; public static final int InvalidRequestString = 7; public static final int InvalidServiceResult = 8; public static final int REXXError = 9; public static final int BaseOSError = 10; public static final int ProcessAlreadyComplete = 11; public static final int ProcessNotComplete = 12; public static final int VariableDoesNotExist = 13; public static final int UnResolvableString = 14; public static final int InvalidResolveString = 15; public static final int NoPathToMachine = 16; public static final int FileOpenError = 17; public static final int FileReadError = 18; public static final int FileWriteError = 19; public static final int FileDeleteError = 20; public static final int STAFNotRunning = 21; public static final int CommunicationError = 22; public static final int TrusteeDoesNotExist = 23; public static final int InvalidTrustLevel = 24; public static final int AccessDenied = 25; public static final int STAFRegistrationError = 26; public static final int ServiceConfigurationError = 27; public static final int QueueFull = 28; public static final int NoQueueElement = 29; public static final int NotifieeDoesNotExist = 30; public static final int InvalidAPILevel = 31; public static final int ServiceNotUnregisterable = 32; public static final int ServiceNotAvailable = 33; public static final int SemaphoreDoesNotExist = 34; public static final int NotSemaphoreOwner = 35; public static final int SemaphoreHasPendingRequests = 36; public static final int Timeout = 37; public static final int JavaError = 38; public static final int ConverterError = 39; public static final int NotUsed = 40; public static final int InvalidObject = 41; public static final int InvalidParm = 42; public static final int RequestNumberNotFound = 43; public static final int InvalidAsynchOption = 44; public static final int RequestNotComplete = 45; public static final int ProcessAuthenticationDenied = 46; public static final int InvalidValue = 47; public static final int DoesNotExist = 48; public static final int AlreadyExists = 49; public static final int DirectoryNotEmpty = 50; public static final int DirectoryCopyError = 51; public static final int DiagnosticsNotEnabled = 52; public static final int HandleAuthenticationDenied = 53; public static final int HandleAlreadyAuthenticated = 54; public static final int InvalidSTAFVersion = 55; public static final int RequestCancelled = 56; public static final int CreateThreadError = 57; public static final int MaximumSizeExceeded = 58; public static final int MaximumHandlesExceeded = 59; // Added in STAF V3.3.6 public static final int UserDefined = 4000; }
import com.ibm.staf.*; // The variable "handle" is an instance of the STAFHandle class that was // previously instantiated. STAFResult result = handle.submit2("local", "PING", "PING"); if (result.rc == STAFResult.Ok) { System.out.println("Successful PING request. " + "Result=" + result.result); } else { System.out.println("Error submitting PING request. " + "RC: " + result.rc + " Result: " + result.result); }
import com.ibm.staf.*; import java.util.*; // The variable "handle" is an instance of the STAFHandle class that was // previously instantiated. String dirName = "{STAF/Config/STAFRoot}/bin"; String request = "LIST DIRECTORY " + STAFUtil.wrapData(dirName) + " TYPE F LONG"; STAFResult result = handle.submit2("local", "FS", request); if (result.rc == STAFResult.Ok) { // The result buffer from a successful LIST DIRECTORY LONG request // returns a marshalled list of maps containing information about // the entries in the directory System.out.println("Successful FS " + request + "\nResult=" + result.resultContext); // Iterate through the unmarshalled result (which is a List // containing a Map for each entry in the directory) and // check which files have a last modified data > 20140101-00:00:00 List resultList = (List)result.resultObj; Iterator iter = resultList.iterator(); while (iter.hasNext()) { Map entryMap = (Map)iter.next(); String lmTimestamp = (String)entryMap.get("lastModifiedTimestamp"); if (lmTimestamp.compareTo("20140101-00:00:00") == 1) { System.out.println("File " + entryMap.get("name") + " was last modified on " + lmTimestamp); } } } else { System.out.println("Error submitting FS " + request + "\nRC: " + result.rc + " Result: " + result.result); }
These APIs allow you to define, manipulate, and (un)marshall data structures, and print marshalled data in human-readable ("pretty" print) format.
STAF supports the automatic marshalling and unmarshalling of structured data. The act of marshalling takes a data structure and converts it into a string-based representation. The act of unmarshalling reverses this and converts the string-based representation back into a data structure. See Section 6.1, "Marshalling Structured Data" in the STAF User's Guide for more information.
The STAFMapClassDefinition class provides the metadata associated with a map class. In particular, it defines the keys associated with the map class. This class is used to create and/or access a STAF map class definition which can be useful if you want to generate a STAF marshalling context with map classes. The map class definition is used to reduce the size of a marshalling map class in comparison to a map containing the same data. It also contains information about how to display instances of the map class, such as the order in which to display the keys and the display names to use for the keys. You get and set map class definitions using the STAFMarshallingContext class setMapClassDefinition and getMapClassDefinition functions.
When constructing a new STAFMapClassDefinition object, the required argument name specifies the name of the STAF map class definition.
STAFMapClassDefinition defines the following methods:
The required argument keyName specifies the name of a key.
The optional argument displayName specifies a string to use when displaying the key. The default is null which indicates to use the actual key name when displaying the key.
The required argument keyName specifies the name of a key for which this property is being set.
The required argument property specifies the name of the property being set. The only property name currently recognized 'display-short-name' which is used by the STAF executable when displaying a result in a tabular format when the length of the values for the fields is less than the length of the 'display-name'.
The required argument value specifies the value for the property being set.
package com.ibm.staf; public class STAFMapClassDefinition { public STAFMapClassDefinition(String name); public Map createInstance(); public void addKey(String keyName); public void addKey(String keyName, String displayName); public void setKeyProperty(String keyName, String property, String value); public Iterator keyIterator(); public String name(); }
import com.ibm.staf.*; import java.util.*; public class TestMarshalling { public static void main(String [] argv) { // Define a map class for querying information about a test myMapClass = new STAFMapClassDefinition("MyApp/Test/MyMap"); myMapClass.addKey("name", "Name"); myMapClass.addKey("exec", "Executable"); myMapClass.addKey("testType", "Test Type"); myMapClass.setKeyProperty("testType", "display-short-name", "Type"); // Create a marshalling context and assign a map class definition to it STAFMarshallingContext mc = new STAFMarshallingContext(); mc.setMapClassDefinition(myMapClass); // Create an instance of this map class definition and assign data // to the map class instance Map testMap = myMapClass.createInstance(); testMap.put("name", "TestA"); testMap.put("exec", "C:/tests/TestA.exe"); testMap.put("testType", "FVT"); // Set the map as the root object for the marshalling context mc.setRootObject(testMap); // Print the marshalling context in a human-readable format System.out.println("Formatted output:\n" + mc.toString()); // Create a marshalled string String result = mc.marshall(); } private static STAFMapClassDefinition myMapClass; }
Formatted output: { Name : TestA Executable: C:/tests/TestA.exe Test Type : FVT }
The STAFMarshallingContext class is used to create and/or access a STAF marshalling context which is used by STAF to help in marshalling and unmarshalling data. A marshalling context is simply a container for map class definitions and a data structure that uses (or is defined in terms of) them.
In order to use a map class when marshalling data, you must add the map class definition to the marshalling context, set the root object of the marshalling context to the object you want to marshall, and then marshall the marshalling context itself. When you unmarshall a data structure, you will always receive a marshalling context. Any map class definitions referenced by map classes within the data structure will be present in the marshalling context.
The primary use of this class is to represent multi-valued results that consist of a data structure (e.g. results from a QUERY/LIST service request, etc.) as a string that can also be converted back into the data structure. This string can be assigned to the string result buffer returned from the service request.
When constructing a new STAFMarshalling class object, the optional argument obj specifies the root object to be marshalled. The default is null.
STAFMarshallingContext defines the following methods:
The required argument mapClassDef specifies a STAFMapClassDefinition object that can be used when marshalling the object. You may call this method any number of times to set multiple STAFMapClassDefinition objects for the marshalling context.
The required argument mapClassName specifies a String containing the name of the STAFMapClassDefinition object that you want to return.
The required argument mapClassName specifies a String containing the name of the STAFMapClassDefinition object that you want to check if the marshalling context's contains in its list of map class definitions.
Note that the name of a map class definition is a String.
The required argument rootObject can specify any Object.
The STAFMarshallingContex class defines following static methods
More information on these static methods are provided later in this section.
package com.ibm.staf; public class STAFMarshallingContext { public static final int UNMARSHALLING_DEFAULTS = 0; public static final int IGNORE_INDIRECT_OBJECTS = 1; public static boolean isMarshalledData(String someData); public STAFMarshallingContext(); public STAFMarshallingContext(Object obj); public void setMapClassDefinition(STAFMapClassDefinition mapClassDef); public STAFMapClassDefinition getMapClassDefinition(String mapClassName); public boolean hasMapClassDefinition(String mapClassName); public Iterator mapClassDefinitionIterator(); public void setRootObject(Object rootObject); public Object getRootObject(); public Object getPrimaryObject(); public String marshall(); public static String marshall(Object object, STAFMarshallingContext context); public static STAFMarshallingContext unmarshall(String marshalledObject); public static STAFMarshallingContext unmarshall( String marshalledObject, int flags); public static STAFMarshallingContext unmarshall( String data, STAFMarshallingContext context); public static STAFMarshallingContext unmarshall( String data, STAFMarshallingContext context, int flags); public static String formatObject(Object obj); public String toString(); }
import com.ibm.staf.*; import java.util.*; public class TestMarshalling { public static void main(String [] argv) { // Define a map class for querying information about a test myMapClass = new STAFMapClassDefinition("MyApp/Test/MyMap"); myMapClass.addKey("name", "Name"); myMapClass.addKey("exec", "Executable"); myMapClass.addKey("testType", "Test Type"); myMapClass.setKeyProperty("testType", "display-short-name", "Type"); // Create a marshalling context and assign a map class definition to it STAFMarshallingContext mc = new STAFMarshallingContext(); mc.setMapClassDefinition(myMapClass); // Create an instance of this map class definition and assign data // to the map class instance Map testMap = myMapClass.createInstance(); testMap.put("name", "TestA"); testMap.put("exec", "C:/tests/TestA.exe"); testMap.put("testType", "FVT"); // Set the map as the root object for the marshalling context mc.setRootObject(testMap); // Print the marshalling context in a human-readable format System.out.println("Formatted output:\n" + mc.toString()); // Create a marshalled string String result = mc.marshall(); } private static STAFMapClassDefinition myMapClass; }
Formatted output: { Name : TestA Executable: C:/tests/TestA.exe Test Type : FVT }
The required argument someData is a String.
if (STAFMarshallingContext.isMarshalledData(result.result)) { STAFMarshallingContext mc = STAFMarshallingContext.unmarshall( result.result); }
The required argument object can be any Object.
The required argument context specifies the STAFMarshallingContext object that should be used when creating the marshalled string. You can specify null if you don't need to specify a marshalling context.
import com.ibm.staf.*; import java.util.*; public class MarshallTest3 { public static void main(String [] argv) { Map myMap = new HashMap(); myMap.put("name", "TestA"); myMap.put("exec", "C:/tests/TestA.exe"); myMap.put("testType", "FVT"); // Create a marshalled string (without a marshalling context) String result = STAFMarshallingContext.marshall(myMap, null); // Unmarshall the string and print it in a nicely formatted way STAFMarshallingContext mc = STAFMarshallingContext.unmarshall(result); System.out.println(mc); // Note: If you have a marshalling context object, then // just use the non-static marshall() method instead. String result2 = mc.marshall(); } }
{ exec : C:/tests/TestA.exe name : TestA testType: FVT }
The required argument marshalledObject is a string to be unmarshalled.
The required argument marshalledObject is a string to be unmarshalled.
The required argument flags can be used to control how to unmarshall the string. When a string is unmarshalled into a data structure, it is possible that one of the string objects that is unmarshalled is itself the string form of another marshalled data structure. Use STAFMarshallingContext.UNMARSHALLING_DEFAULTS to recursively unmarshall these nested objects. Use STAFMarshallingContext.IGNORE_INDIRECT_OBJECTS to disable this additional processing.
The required argument data is a string to be unmarshalled.
The required argument context specifies the STAFMarshallingContext object that should be used when unmarshalling the string. You can specify null for this argument.
The required argument data is a string to be unmarshalled.
The required argument context specifies the STAFMarshallingContext object that should be used when unmarshalling the string. You can specify null for this argument.
The required argument flags can be used to control how to unmarshall the string. When a string is unmarshalled into a data structure, it is possible that one of the string objects that is unmarshalled is itself the string form of another marshalled data structure. Use STAMarshallingContext.UNMARSHALLING_DEFAULTS to recursively unmarshall these nested objects. Use STAFMarshalingContext.IGNORE_INDIRECT_OBJECTS to disable this additional processing.
Here is the STAF request that this example executes and its result as shown when run using the STAF executable which "pretty prints" the result.
C:\>STAF local FS LIST DIRECTORY {STAF/Config/STAFRoot} Response -------- lib codepage STAFInst samples include bin docs data services STAFReg.inf LICENSE.htm
import com.ibm.staf.*; import java.util.*; public class TestUnmarshallList { public static void main(String [] argv) { // Register with STAF try { handle = new STAFHandle("MyApp/Test"); } catch (STAFException e) { System.out.println( "Error registering with STAF, RC: " + e.rc); System.exit(1); } // Submit a request to the FS service to LIST the contents of // the STAF root directory String machine = "local"; String service = "FS"; String request = "LIST DIRECTORY {STAF/Config/STAFRoot}"; try { String result = handle.submit(machine, service, request); // The result from the request is a marshalled list of strings. // Unmarshall the result. STAFMarshallingContext mc = STAFMarshallingContext.unmarshall( result); // Pretty print the result context System.out.println("Formatted output:\n" + mc); List entryList = (List)mc.getRootObject(); // Check if an entry named "bin" is in the directory list Iterator iter = entryList.iterator(); while (iter.hasNext()) { String entryName = (String)iter.next(); if (entryName.equals("bin")) { System.out.println( "The STAF root directory contains a directory " + "named bin"); } } } catch (STAFException e) { System.out.println( "Error submitting request STAF " + machine + " " + service + " " + request + "\nRC: " + e.rc + " Result: " + e.getMessage()); } } private static STAFHandle handle; }
Formatted output: [ lib codepage STAFInst STAFInst.mfs samples include bin LICENSE.htm docs data services NOTICES.htm install.properties ] The STAF root directory contains a directory named bin
Here is the STAF request that this example executes and its result as shown when run using the STAF executable which "pretty prints" the result.
Response -------- { Return Code: 0 Key : <None> Files : [ { Return Code: 0 Data : Volume in drive C has no label. Volume Serial Number is 88AF-B0AF Directory of C:\STAF 06/23/2014 02:30 PM <DIR> . 06/23/2014 02:30 PM <DIR> .. 06/23/2014 02:31 PM <DIR> bin 06/23/2014 02:30 PM <DIR> codepage 03/05/2010 03:01 PM <DIR> data 06/23/2014 02:30 PM <DIR> docs 06/23/2014 02:30 PM <DIR> include 06/23/2014 02:30 PM 139 install.properties 06/23/2014 02:30 PM <DIR> jre 06/23/2014 02:30 PM <DIR> lib 06/17/2014 07:15 PM 17,029 LICENSE.htm 06/17/2014 07:15 PM 8,516 NOTICES.htm 06/23/2014 02:30 PM <DIR> samples 03/28/2014 10:34 AM <DIR> services 06/23/2014 02:29 PM 275 STAFEnv.bat 06/23/2014 02:30 PM 71,365 STAFInstall.log 12/09/2010 06:49 PM 21 STAFReg.inf 06/23/2014 02:29 PM 147 startSTAFProc.bat 06/23/2014 02:30 PM 2,238 startSTAFProc.ico 06/23/2014 02:30 PM <DIR> Uninstall_STAF 8 File(s) 99,730 bytes 12 Dir(s) 106,599,550,976 bytes free } ] }
import com.ibm.staf.*; import java.util.*; public class TestUnmarshallMap { public static void main(String [] argv) { // Register with STAF try { handle = new STAFHandle("MyApp/Test"); } catch (STAFException e) { System.out.println( "Error registering with STAF, RC: " + e.rc); System.exit(1); } // Submit a request to the PROCESS service to run a command that // lists the contents of the STAF root directory and waits for // the request to complete String machine = "local"; String service = "PROCESS"; String command = "dir {STAF/Config/STAFRoot}"; String request = "START SHELL COMMAND " + STAFUtil.wrapData(command) + " RETURNSTDOUT STDERRTOSTDOUT WAIT"; System.out.println( "STAF " + machine + " " + service + " " + request); try { String result = handle.submit(machine, service, request); // Unmarshall the result buffer whose root object is a map // containing process completion information. The keys for this // map include 'rc' and 'fileList'. The value for 'fileList' // is a list of the returned files. Each entry in the list // consists of a map that contains keys 'rc' and 'data'. // In our PROCESS START request, we returned one file, STDOUT, // (and returned STDERR to the STDOUT file). STAFMarshallingContext mc = STAFMarshallingContext.unmarshall(result); Map processCompletionMap = (Map)mc.getRootObject(); // Verify that the process rc is 0 String processRC = (String)processCompletionMap.get("rc"); if (!processRC.equals("0")) { System.out.println( "ERROR: Process RC is " + processRC + " instead of 0."); System.exit(1); } // Verify that the rc is 0 for returning data to the STDOUT file List returnedFileList = (List)processCompletionMap.get( "fileList"); Map stdoutMap = (Map)returnedFileList.get(0); String stdoutRC = (String)stdoutMap.get("rc"); if (!stdoutRC.equals("0")) { System.out.println( "ERROR retrieving process Stdout data. RC=" + stdoutRC); System.exit(1); } // Get the data from the STDOUT file created by the process // and print it String stdoutData = (String)stdoutMap.get("data"); System.out.println("\nProcess Stdout File Contains:\n"); System.out.println(stdoutData); } catch (STAFException e) { System.out.println( "Error submitting request STAF " + machine + " " + service + " " + request + "\nRC: " + e.rc + " Result: " + e.getMessage()); } } private static STAFHandle handle; }
STAF local PROCESS START SHELL COMMAND :26:dir {STAF/Config/STAFRoot} RETURNSTDOUT STDERRTOSTDOUT WAIT
Process Stdout File Contains: Volume in drive C has no label. Volume Serial Number is 88AF-B0AF Directory of C:\STAF 06/23/2014 02:30 PM <DIR> . 06/23/2014 02:30 PM <DIR> .. 06/23/2014 02:31 PM <DIR> bin 06/23/2014 02:30 PM <DIR> codepage 03/05/2010 03:01 PM <DIR> data 06/23/2014 02:30 PM <DIR> docs 06/23/2014 02:30 PM <DIR> include 06/23/2014 02:30 PM 139 install.properties 06/23/2014 02:30 PM <DIR> jre 06/23/2014 02:30 PM <DIR> lib 06/17/2014 07:15 PM 17,029 LICENSE.htm 06/17/2014 07:15 PM 8,516 NOTICES.htm 06/23/2014 02:30 PM <DIR> samples 03/28/2014 10:34 AM <DIR> services 06/23/2014 02:29 PM 275 STAFEnv.bat 06/23/2014 02:30 PM 71,365 STAFInstall.log 12/09/2010 06:49 PM 21 STAFReg.inf 06/23/2014 02:29 PM 147 startSTAFProc.bat 06/23/2014 02:30 PM 2,238 startSTAFProc.ico 06/23/2014 02:30 PM <DIR> Uninstall_STAF 8 File(s) 99,730 bytes 12 Dir(s) 106,599,550,976 bytes free
The required argument obj specifies any Object to be formatted in a verbose, more readable format.
String request = "QUERY ENTRY {STAF/Config/ConfigFile}"; try { String result = handle("local", "FS", request); STAFMarshallingContext mc = STAFMarshallingContext.unmarshall(result); System.out.println( "Formatted output using formatObject():\n" + STAFMarshallingContext.formatObject(mc)); // Note: Instead of using the static formatObject method, if you // have a STAFMarshallingContext object (e.g. mc), you can simply // print the marshalling context object itself to get the same // output because the toString() function for a STAFMarshallingContext // object calls the formatObject function. System.out.println("\nFormatted output using toString():\n" + mc); } catch (STAFException e) { System.out.println( "Error submitting request STAF local FS " + request + "\nRC: " + e.rc + " Result: " + e.getMessage()); }
Formatted output using formatObject(): { Name : C:\STAF\bin\staf.cfg Type : F Upper 32-bit Size : 0 Lower 32-bit Size : 6612 Modified Date-Time: 20140506-16:08:08 } Formatted output using toString(): { Name : C:\STAF\bin\staf.cfg Type : F Upper 32-bit Size : 0 Lower 32-bit Size : 6612 Modified Date-Time: 20140506-16:08:08 }
These APIs allow you to handle private data. These APIs are all static methods in the STAFUtil class:
See Section 7.3, "Private Data" in the STAF User's Guide for more information about handling private data.
This method should be used by anyone who wants to protect private data specified in a STAF command option that supports handling private data.
Required argument data is a String that contains data you want to protect.
Returns a String object containing the string with opening and closing privacy delimiters added and escapes any privacy delimiters already contained in the string with a caret (^). If the string has length 0 or already has an unescaped opening privacy delimiter at the beginning and an unescaped closing privacy delimiter at the end, privacy delimiters are not added.
Examples:
Since: STAF V3.1.0
public class STAFUtil { public static String addPrivacyDelimiters(String data); }
String password = STAFUtil.addPrivacyDelimiters("passw0rd"); String request = "START COMMAND C:/tests/TestA.exe USERNAME Test1" + " PASSWORD " + password; STAFResult result = handle.submit2("local", "PROCESS", request);
String command = "C:/tests/admin -password " + STAFUtil.addPrivacyDelimiters("secret"); String request = "START SHELL COMMAND " + STAFUtil.wrapData(command); STAFResult result = handle.submit2("local", "PROCESS", request);
This method should be used before calling the addPrivacyDelimiters method for data that needs to be protected but may contain substrings !!@ and/or @!! that should not be mistaken for privacy delimiters .
Required argument data is a String.
Returns a String object containing the updated data.
For example, if the data is "passw@!!d", this method would return "passw^@!!d".
Since: STAF V3.1.0
public class STAFUtil { public static String escapePrivacyDelimiters(String data); }
String password = STAFUtil.addPrivacyDelimiters( STAFUtil.escapePrivacyDelimiters("passw@!!d")); String request = "START COMMAND C:/tests/TestA.exe USERNAME Test1" + " PASSWORD " + password; STAFResult result = handle.submit2("local", "PROCESS", request);
Required argument data is a String that may contain privacy delimiters.
Optional argument numLevels in an int that specifies the number of levels of privacy data to remove. The default is 0 which indicates to remove all levels of privacy data. Note that, generally, you'll want to remove all levels of privacy delimiters.
Returns a String object containing the updated data with privacy delimiters removed.
Examples:
Since: STAF V3.1.0
public class STAFUtil { public static String removePrivacyDelimiters(String data); public static String removePrivacyDelimiters(String data, int numLevels); }
String protectedPassword = "!!@secret@!!"'; String password = STAFUtil.removePrivacyDelimiters(protectedPassword);
Required argument data is a String that may contain privacy delimiters.
Returns a String object containing the string with any private data masked.
Examples:
Since: STAF V3.1.0
public class STAFUtil { public static String maskPrivateData(String data); }
String request = "START COMMAND C:/tests/TestA.exe USERNAME Test1" + " PASSWORD " + STAFUtil.addPrivacyDelimiters("passw0rd"); System.out.println(STAFUtil.maskPrivateData(request);
These are general utility APIs that you may find useful when writing test cases in Java or when writing a Java service.
The general utility APIs that are static functions in the STAFUtil class are:
Other general utility APIs are:
The required argument data is a string.
For example, if the data is Hello world, this method would return a string containing :11:Hello world.
public class STAFUtil { public static String wrapData(String data); }
// Submit a request to the LOG service to log a message String message = "Hello world"; STAFResult result = handle.submit2( "local", "LOG", "LOG GLOBAL LOGNAME MyLog " + "MESSAGE " + STAFUtil.wrapData(message) + " LEVEL Info"); // Submit a request to the PROCESS service to run a command that // lists the contents of the STAF root directory and waits for // the request to complete String machine = "local"; String service = "PROCESS"; String command = "dir {STAF/Config/STAFRoot}"; String request = "START SHELL COMMAND " + STAFUtil.wrapData(command) + " RETURNSTDOUT STDERRTOSTDOUT WAIT"; STAFResult result = handle.submit2(machine, service, request);
The required argument data is a string.
For example, if the data is :8:Hi there, this method would return a string containing Hi there.
public class STAFUtil { public static String unwrapData(String data); }
String wrappedMessage = STAFUtil.wrapData("Hello world"); String unwrappedMessage = STAFUtil.unwrapData(wrappedMessage);
The required argument endpoint is a string.
For example, if the endpoint specified is tcp://client1.company.com@6500, it would return tcp://client1.company.com.
public class STAFUtil { public static String stripPortFromEndpoint(String endpoint); }
String endpoint = STAFUtil.stripPortFromEndpoint( "tcp://client1.company.com@6500");
Required parameter requiredTrustLevel specifies the required trust level for this service request.
Required parameter service specifies the registered name of the service.
Required parameter request specifies the first word (or two) to uniquely identify the request if an error occurs.
Required parameter localMachine specifies the logical identifier for the service machine which will be used in the error message if the requesting machine has insufficient trust.
Required parameter info specified the request information.
This method returns a STAFResult object. If successful, the return code (rc) in the STAFResult object will be STAFResult.Ok and the result buffer (result) in the STAFResult object will be blank. If not successful, a non-zero return code will set and the result buffer will contain a detailed error message.
public class STAFUtil { public static STAFResult validateTrust( int requiredTrustLevel, String service, String request, String localMachine, STAFServiceInterfaceLevel30.RequestInfo info); }
Required parameter durationString specifies the timeout duration in the format <Number>[s|m|h|d|w]. For example: "100", "1s", "5m", "1h".
This method returns a STAFResult object. If successful, the return code (rc) in the STAFResult object will be STAFResult.Ok and the result buffer (result) in the STAFResult object will be the converted duration in milliseconds. If not successful, a non-zero return code will be set and the result buffer will contain a detailed error message.
Since: STAF V3.3.2
public class STAFUtil { public static STAFResult convertDurationString(String durationString); }
STAFResult result = convertDurationString("10h"); if (result.rc != STAFResult.Ok) return result; try { long duration = Long.parseLong(result.result); } catch (NumberFormatException e) { return new STAFResult(STAFResult.InvalidValue, "NumberFormatException: " + e.getMessage()); }
Required parameter size specifies the size in the format <Number>[k|m]. For example: "1000000", "500k", "5m".
This method returns a STAFResult object. If successful, the return code (rc) in the STAFResult object will be STAFResult.Ok and the result buffer (result) in the STAFResult object will be the converted size in bytes. If not successful, a non-zero return code will be set and the result buffer will contain a detailed error message.
Since: STAF V3.3.4
public class STAFUtil { public static STAFResult convertSizeString(String sizeString); }
long maxFileSizeInBytes = 0; STAFResult result = convertSizeString("5m"); if (result.rc != STAFResult.Ok) return result; try { maxFileSizeInBytes = Long.parseLong(result.result); } catch (NumberFormatException e) { // Should never happen because convertSizeString should have // returned an error previously return new STAFResult(STAFResult.InvalidValue, "NumberFormatException: " + e.getMessage()); }
Required argument value is a String that may contain STAF variables to be resolved (e.g. "{STAF/Config/Machine}").
Required argument handle is a STAFHandle object.
Requires argument requestNumber is the request number.
Returns a STAFResult object. If successful, the rc (return code) in the STAFResult object will be set to STAFResult.Ok and the result (result buffer) in the STAFResult object will contain a string with all STAF variables resolved. If unsuccessful, the rc will be set to a non-zero integer and the result string will contain an error message.
public class STAFUtil { public static STAFResult resolveRequestVar( String value, STAFHandle handle, int requestNumber); }
Required argument option is a String that contains the name of an option in a service request whose value is being resolved.
Required argument value is a String that may contain STAF variables to be resolved (e.g. "{STAF/Config/Machine}").
Required argument handle is a STAFHandle object.
Requires argument requestNumber is the request number.
Returns a STAFResult object. If successful, the rc (return code) in the STAFResult object will be set to STAFResult.Ok and the result (result buffer) in the STAFResult object will contain a string with all STAF variables resolved. If unsuccessful, the rc will be set to a non-zero integer and the result string will contain an error message.
public class STAFUtil { public static STAFResult resolveRequestVarAndCheckInt( String option, String value, STAFHandle handle, int requestNumber); }
Required argument option is a String that contains the name of an option in a service request whose value is being resolved.
Required argument value is a String that may contain STAF variables to be resolved (e.g. "{STAF/Config/Machine}"). This value specifies the timeout duration in the format <Number>[s|m|h|d|w]. For example: "100", "1s", "5m", "1h".
Required argument handle is a STAFHandle object.
Requires argument requestNumber is the request number.
Returns a STAFResult object. If successful, the rc (return code) in the STAFResult object will be set to STAFResult.Ok and the result (result buffer) in the STAFResult object will contain a string set to the duration value converted to milliseconds. If unsuccessful, the rc will be set to a non-zero integer and the result string will contain an error message.
Since: STAF V3.3.2
public class STAFUtil { public static STAFResult resolveRequestVarAndConvertDuration( String option, String value, STAFHandle handle, int requestNumber); }
if (parseResult.optionTimes("WAIT") > 0) { String waitString = parseResult.optionValue("WAIT"); String waitTimeout = ""; if (waitString.length() != 0) { // Resolve the WAIT value, verify that it is a valid // duration timeout value, and convert it to milliseconds // if needed resolvedValue = STAFUtil.resolveRequestVarAndConvertDuration( "WAIT", waitString, fHandle, info.requestNumber); if (resolvedValue.rc != STAFResult.Ok) return resolvedValue; waitTimeout = resolvedValue.result; } }
Required argument option is a String that contains the name of an option in a service request whose value is being resolved.
Required argument value is a String that may contain STAF variables to be resolved (e.g. "{STAF/Config/Machine}"). This value specifies the size in the format <Number>[k|m]. For example: "1000000", "500k", "5m".
Required argument handle is a STAFHandle object.
Requires argument requestNumber is the request number.
Returns a STAFResult object. If successful, the rc (return code) in the STAFResult object will be set to STAFResult.Ok and the result (result buffer) in the STAFResult object will contain a string set to the size value converted to bytes. If unsuccessful, the rc will be set to a non-zero integer and the result string will contain an error message.
Since: STAF V3.3.4
public class STAFUtil { public static STAFResult resolveRequestVarAndConvertSize( String option, String value, STAFHandle handle, int requestNumber); }
long maxFileSizeInBytes = 0; if (parseResult.optionTimes("MAXRETURNFILESIZE") > 0) { // Resolve the MAXRETURNFILESIZE value, verify that it is a // valid size value, and convert it to bytes, if needed resolvedValue = STAFUtil.resolveRequestVarAndConvertSize( "MAXRETURNFILESIZE", parseResult.optionValue("MAXRETURNFILESIZE"), fHandle, info.requestNumber); if (resolvedValue.rc != STAFResult.Ok) return resolvedValue; try { maxFileSizeInBytes = Long.parseLong(resolvedValue.result); } catch (NumberFormatException e) { // Should never happen because resolveRequestVarAndConvertSize // should have returned an error previously return new STAFResult( STAFResult.InvalidValue, "Invalid MAXRETURNFILESIZE value: " + resolvedValue.result); } }
Required argument value is a String that may contain STAF variables to be resolved (e.g. "STAF/Config/Machine}").
Required argument handle is a STAFHandle object.
Returns a STAFResult object. If successful, the rc (return code) in the STAFResult object will be set to STAFResult.Ok and the result (result buffer) in the STAFResult object will contain a string with all STAF variables resolved. If unsuccessful, the rc will be set to a non-zero integer and the result string will contain an error message.
public class STAFUtil { public static STAFResult resolveInitVar(String value, STAFHandle handle); }
Required argument option is a String that contains the name of an option in a service request whose value is being resolved.
Required argument value is a String that may contain STAF variables to be resolved (e.g. "STAF/Config/Machine}").
Required argument handle is a STAFHandle object.
Returns a STAFResult object. If successful, the rc (return code) in the STAFResult object will be set to STAFResult.Ok and the result (result buffer) in the STAFResult object will contain a string with all STAF variables resolved. If unsuccessful, the rc will be set to a non-zero integer and the result string will contain an error message.
public class STAFUtil { public static STAFResult resolveInitVarAndCheckInt( String option, String value, STAFHandle handle); }
Required argument machine is a String that contains the endpoint of the machine whose STAF or STAF service version is to be compared.
Required argument handle is a STAFHandle object used to submit the request.
Required argument minRequiredVersion is a String that
contains the minimum version required on the machine.
The version must have the following format unless it's blank or
"
Optional argument service is a String that
contains the name of the service for which you want to compare its
version. Defaults to MISC which means that you want to compare
the version of STAF running. Or, you can specify the name of a
STAF service (such as STAX, Event, Cron, etc.) that implements a
VERSION request.
STAF Versions are compared as follows:
Examples:
Returns a STAFResult object. If successful (the version is at or
above the required version), the rc (return code) in the STAFResult
object will be set to STAFResult.Ok and the result (result buffer) in
the STAFResult object will contain the version of STAF (or of the
specified STAF service) running on the specified machine.
If unsuccessful, the rc will be set to a non-zero integer and the
result string will contain an error message.
If the version is lower than the mininum required version,
STAFResult.InvalidSTAFVersion is returned in the rc with an error
message returned in the result. If another error occurs (e.g. RC 16
if the machine is not currently running STAF, etc.), an error message
will be returned in the result.
Since: STAF V3.1.0
a[.b[.c[.d]]] [text]
where:
"3" = "3.0" = "3.0.0" = 3.0.0.0"
"3.0.0" < "3.1.0"
"3.0.2" < "3.0.3"
"3.0.9" < "3.0.10"
"3.0.0" < "3.1"
"3.1.0 Alpha 1" < "3.1.0 Beta 1"
"3.1.0 Beta 1" < "3.1.0"
public class STAFUtil { public static STAFResult compareSTAFVersion( String machine, STAFHandle handle, String minRequiredVersion); }
public class MyService implements STAFServiceInterfaceLevel30 { // Version of STAF (or later) required for this service private final String kRequiredSTAFVersion = "3.1.0"; private STAFHandle fHandle; public STAFResult init(STAFServiceInterfaceLevel30.InitInfo info) { try { fHandle = new STAFHandle("STAF/SERVICE/" + info.name); } catch (STAFException e) { return new STAFResult(STAFResult.STAFRegistrationError, e.toString()); } // Verify that the required version of STAF is running on the // local service machine. STAFResult res = new STAFResult(); try { res = STAFUtil.compareSTAFVersion( "local", fHandle, kRequiredSTAFVersion); } catch (Error err) { // Note: Method compareSTAFVersion was added in STAF V3.1.0 // so need to catch a NoSuchMethod error return new STAFResult( STAFResult.ServiceConfigurationError, "This service requires STAF Version " + kRequiredSTAFVersion + " or later."); } if (res.rc != STAFResult.Ok) { if (res.rc == STAFResult.InvalidSTAFVersion) { return new STAFResult( STAFResult.ServiceConfigurationError, "Minimum required STAF version for this service " + "is not running. " + res.result); } else { return new STAFResult( STAFResult.ServiceConfigurationError, "Error verifying the STAF version. RC: " + res.rc + ", Additional info: " + res.result); } } ... } ... }
// Assumes a STAF Handle called fHandle has already been created STAFResult res = new STAFResult(); String machine = "server1"; String service = "STAX"; String requiredVersion = "3.1"; try { res = STAFUtil.compareSTAFVersion( machine, fHandle, requiredVersion, service); } catch (Error err) { // The required version of STAF is not running as class STAFVersion // was added in STAF V3.1 so this catches a NoSuchMethod error ... } if (res.rc != STAFResult.Ok) { if (res.rc == STAFResult.InvalidSTAFVersion) { // Service version on the machine is lower than 3.1 ... } else { // Error occurred trying to verify the version of the STAX service // on the machine ... } }
The STAFVersion class allows you to compare STAF versions. This class is useful if you want to verify that a STAF version or a version of a STAF service is at a particular level of STAF.
package com.ibm.staf; public class STAFVersion { public static int NUM_VERSION_LEVELS = 4; public STAFVersion(String version) throws NumberFormatException; public int compareTo(STAFVersion version); public String getVersion(); public int[] getVersionArray(); public String getText(); public String toString(); }
When constructing a new STAFVersion object, the
required argument version is a string containing the STAF version.
A STAF version must be of the following format unless it's blank or
" A NumberFormatException is thrown if a non-numeric value is specified
in a, b, c, or d.
Since: STAF V3.1.0
STAFVersion defines the following methods:
The required argument version is a STAFVersion object
representing the STAF version to compare.
STAFVersion instances are compared as follows:
Examples:
This method returns an integer as follows:
The STAFQueueMessage class provides a wrapper around messages received via
the STAF Queue service. It takes the received string as input and unmarshalls
it and breaks it into its constituent parts.
These APIs are wrappers around the following LOG commands which can make
it simple to submit LOG requests to the LOG and MONITOR services:
The STAFLog class provides a wrapper around the LOG command of the LOG
service. It provides constants for the log type and log levels. It has
instance and static methods for logging. The STAFLog class also interfaces
with the MONITOR service. You may provide the STAFLog class a monitor mask.
For the levels set in the monitor mask, STAFLog will log the message via the
LOG service and then log the message via the MONITOR service. STAFLog will
also log an error message to the MONITOR service, if it should receive an
error while trying to log a message.
The STAFMonitor class provides a wrapper around the LOG command of the
MONITOR service. It has instance and static methods for logging messages to the
MONITOR service.
These APIs are Java GUI classes that allow you to:
Note that the STAX Monitor Java application uses the STAFLogViewer class
to display the STAX job logs and the STAX service log.
Since: STAF V3.1.0
To execute and get help from the STAFLogViewer class from the command line,
specify the following:
The STAFLogViewer class accepts the following command line options:
-machine specifies the name of the machine where the STAF log is located.
This optiontis optional. The default is local.
-serviceName specifies the name of the log service. This option
is optional. The default is LOG.
-levelMask specifies the log levels to be initially displayed. This
option is optional. The default is to display all log levels.
Only level names are supported (for example
"ERROR DEBUG".); use of the 32 byte bit string to represent
the log mask is not supported. These are the log levels that will be displayed
when the initial STAFLogViewer is displayed. The user can then change the
log levels to be displayed via the "Levels" menu.
-fontName specifies the name of the font to use when displaying the
STAF log. This option is optional. The default is Monospaced.
Examples of other fonts are Dialog and TimesRoman.
-saveAsDirectory specifies the initial directory path that will
be used if you select the "File->Save As Text..." or "File->Save As Html..."
menu item to save the log query output in a file.
If not specified, it defaults to user's default directory which is typically
the "My Documents" folder on Windows or the user's home directory on Unix.
-help displays help information for the STAFLogViewer.
This option is optional.
-version displays the version of the STAFLogViewer.
This option is optional.
You may also call the STAFLogViewer class from a Java application. The
following constructors for STAFLogViewer are provided:
Here is an example of the Java GUI that is displayed for the following
command:
The STAFLogViewer's menu bar provides the following menus:
A JVM Log file contains JVM start information such as the date/time when the JVM
was created, the JVM executable, and the J2 options used to start the JVM.
It also any other information logged by the JVM. This includes any
errors that may have occurred while the JVM was running and any debug information
output by a Java service. Also, the JVM Log for the STAX service contains the
output from any print statements that are used within a <script> element
in a STAX xml job file which is useful when debugging Python code contained in
a <script> element. When a problem occurs with a STAF Java service,
you should always check it's JVM Log as it may contain information to help debug
the problem.
STAF stores JVM Log files in the {STAF/DataDir}/lang/java/jvm/<JVMName>
directory. STAF retains a configurable number of JVM Logs (five by default) for each
JVM. The current JVM log file is named JVMLog.1 and older saved JVM log files,
if any, are named JVMLog.2 to JVMLog.<MAXLOGS>. When a JVM is
started, if the size of the JVMLog.1 file exceeds the maximum configurable
size (1M by default), the JVMLog.1 file is copied to JVMLog.2 and
so on for any older JVM Logs, and a new JVMLog.1 file will be created.
When using the STAFJVMLogViewer, you can specify the machine where the STAF
JVM log resides (e.g. where the Java service is registered) and you can
specify/select the name of the STAF service whose JVM Log you want to display.
This Java class submits requests to STAF, so STAF has to be running.
This Java class can be run as an application via the command line or can be
run via another Java program.
Note that the STAX Monitor Java application uses the STAFJVMLogViewer class
to display the JVM log for the STAX service and for other services.
Since: STAF V3.2.1
The STAFJVMLogViewer class accepts the following command line options:
All of the options are optional. If specifying the -help or
-version option, this option must be the first (and only) option
specified.
-serviceName specifies the name of a Java service that is currently
registered whose JVM Log you want to display.
This option is optional. If it is not specified, you'll be prompted
to select a service registered on the specified machine whose JVM Log
you want to display.
-displayAll specifies to display all of the entries in the JVM Log.
This option is optional. The default is to display only the entries
in the JVM Log from the last time the JVM was created.
-fontName specifies the name of the font to use when displaying the
STAF JVM Log. This option is optional. The default is Monospaced.
Examples of other fonts are Dialog and TimesRoman.
-help displays help information for the STAFJVMLogViewer.
This option is optional.
-version displays the version of the STAFJVMLogViewer.
This option is optional.
You may also call the STAFJVMLogViewer class from a Java application. The
following constructors for STAFJVMLogViewer are provided:
Here is an example of the Java dialogs that are displayed for the following
command:
Click on the drop-down list to see all of the Java services registered on
this machine. Select a Java service, and then select the OK button to display
the JVM Log for this Java service.
Here is an example of the dialog that is shown when the JVM Log is displayed.
The STAFJVMLogViewer's menu bar provides the following menus:
This Java class can be run as an application via the command line or can be
run via another Java program. When run as an application, it submits the
specified Log query request to query a STAF log on any machine currently
running STAF and then formats the output as either html or text.
Or, when run via a Java program that has already submitted a LOG QUERY request,
you can use the STAFLogFormatter class to format the log query result
as either html or text. You can specify various options including whether you
want the formatted output written to a file.
Two format types are supported:
Note that the STAFLogViewer class uses the STAFLogFormatter class
when you select File->Save As Text... or File->Save As Html....
Since: STAF V3.3.2
To execute and get help from the STAFLogFormatter class from the command line,
specify the following:
The STAFLogFormatter class accepts the following command line options:
Here's a description of all of the options:
-fileName specifies the fully-qualified name of a file
where the formatted log output will be written. This option is optional.
If not specified, the formatted log output is written to Stdout.
-type specifies the format type. Valid values are: html
or text. This option is optional. If not specified, it
defaults to html.
-fontName specifies the name of the font to use when formatting the
STAF log. It does not have an effect if formatting the log as text.
This option is optional. If not specified, it defaults to courier
(which is a Monospaced font). Examples of other valid font names are
dialog and timesRoman.
-title specifies a title for the log output. This option is
optional. If not specified, it defaults to the actual log query request
submitted if using type html or to no title if using type text.
-machine specifies the name of the machine where the STAF log
is located. This option is optional. If not specified, it defaults to
local.
-serviceName specifies the name of the Log service to which
the query request will be submitted. This option is optional.
If not specified, it defaults to LOG.
-help displays help information for the STAFLogFormatter.
This option is optional, but if specified, it must be the first and
only option specified.
-version displays the version of the STAFLogFormatter.
This option is optional, but if specified, it must be the first and
only option specified.
When constructing a new STAFLogFormatter object, the
required argument context must be a STAFMarshallingContext object
containing a LOG QUERY result's marshalling context.
>A STAFException is thrown if an invalid STAFMarshallingContext object
is specified.
Class STAFLogFormatter defines the following methods:
The required argument fileName is a String
containing the file name.
The required argument fileName is a String containing
the font name.
The required argument title is a String containing
the title for the formatted log output.
The required argument typeString must be a String
containing the format type html or text, case-insensitive.
This method returns a string as follows:
A STAFException is thrown if an invalid STAFMarshallingContext object
was specified when constructing the STAFLogFormatter.
A IOException is thrown if a fileName is set and there is a problem
writting the formatted log output to the specified fileName.
The TestJSTAF class allows you to submit a command-line STAF
request using the STAF Java support. This class is useful if you want to verify
that the STAF Java support is working correctly, without requiring a GUI display
or any modifications to the CLASSPATH.
The syntax of this class is:
a[.b[.c[.d]]] [text]
where:
"3" = "3.0" = "3.0.0" = 3.0.0.0"
"3.0.0" < "3.1.0"
"3.0.2" < "3.0.3"
"3.0.0" < "3.1"
"3.0.9" < "3.0.10"
"3.1.0 Alpha 1" < "3.1.0 Beta 1"
"3.1.0 Beta 1" < "3.1.0"
Examples
Suppose you already had the STAF version that you wanted to compare
in a String variable named versionStr and you wanted to
make sure that it was at version 3.1.0 or higher. You could check
this as follows:
String reqVersionStr = "3.1";
try
{
STAFVersion version = new STAFVersion(versionStr);
STAFVersion requiredVersion = new STAFVersion(reqVersionStr);
if (version.compareTo(requiredVersion) < 0)
{
// Version is lower than the minimum required version
return new STAFResult(
STAFResult.InvalidSTAFVersion,
"Version is " + versionStr + ". Version " +
reqVersionStr + " or later is required.");
}
}
catch (NumberFormatException e)
{
return new STAFResult(
STAFResult.InvalidValue,
"Invalid value specified for version, Exception info: " +
e.toString());
}
catch (Error err)
{
// Note: Class STAFVersion was added in STAF V3.1.0
// so need to catch a NoSuchMethod error
return new STAFResult(
STAFResult.InvalidSTAFVersion,
"Version is " + versionStr + ". Version " +
reqVersionStr + " or later is required.");
}
3.4.15 Class STAFQueueMessage
Definition
package com.ibm.staf;
public class STAFQueueMessage
{
public STAFQueueMessage(String queueMessage);
public int priority;
public String timestamp;
public String machine;
public String handleName;
public int handle;
public String type;
public Object message;
public STAFMarshallingContext mc;
}
Examples
The following example shows how to wait for a message to be queued (by
submitting a GET WAIT request to the QUEUE service) and
to use the STAFQueueMessage class to receive the marshalled queue message
string as input and to unmarshall it and break it into separate fields
including the queued message itself and its priority, timestamp, type, etc.
If the above example is run and the following command is submitted
when requested:
import com.ibm.staf.*;
public class TestQueue
{
// This is the main command line entry point
public static void main(String [] argv)
{
// Verify the command line arguments
if (argv.length != 0)
{
System.out.println();
System.out.println("Usage: java TestQueue");
System.exit(1);
}
// Register with STAF
try
{
handle = new STAFHandle("Queue_Class_Test");
}
catch (STAFException e)
{
System.out.println("Error registering with STAF, RC: " + e.rc);
System.exit(1);
}
System.out.println("Please send a queue message to handle " +
handle.getHandle() + " now");
try
{
String result = handle.submit("local", "QUEUE", "GET WAIT");
STAFQueueMessage message = new STAFQueueMessage(result);
System.out.println("Priority : " + message.priority);
System.out.println("Timestamp : " + message.timestamp);
System.out.println("Machine : " + message.machine);
System.out.println("Handle name: " + message.handleName);
System.out.println("Handle : " + message.handle);
System.out.println("Type : " + message.type);
System.out.println("Message : " + message.message);
}
catch (STAFException e)
{
System.out.println(
"Error getting message from queue, RC: " + e.rc +
", Additional Info: " + e.getMessage());
}
}
private static STAFHandle handle;
}
the result could look like the following:
C:\>staf local queue queue handle 71 message "Hi there" type "MyType"
Response
--------
C:\>java TestQueue
Please send a queue message to handle 71 now
Priority : 5
Timestamp : 20140516-12:31:42
Machine : local://local
Handle name: STAF/Client
Handle : 73
Type : MyType
Message : Hi there
C:>
3.5 Wrapper APIs for Log and Monitor Services' LOG Command
3.5.1 Class STAFLog
Definition
package com.ibm.staf.wrapper;
public class STAFLog
{
// Log type constants
public static final String GLOBAL = "GLOBAL";
public static final String MACHINE = "MACHINE";
public static final String HANDLE = "HANDLE";
// Log level constants (int format)
public static final int Fatal = 0x00000001;
public static final int Error = 0x00000002;
public static final int Warning = 0x00000004;
public static final int Info = 0x00000008;
public static final int Trace = 0x00000010;
public static final int Trace2 = 0x00000020;
public static final int Trace3 = 0x00000040;
public static final int Debug = 0x00000080;
public static final int Debug2 = 0x00000100;
public static final int Debug3 = 0x00000200;
public static final int Start = 0x00000400;
public static final int Stop = 0x00000800;
public static final int Pass = 0x00001000;
public static final int Fail = 0x00002000;
public static final int Status = 0x00004000;
public static final int Reserved1 = 0x00008000;
public static final int Reserved2 = 0x00010000;
public static final int Reserved3 = 0x00020000;
public static final int Reserved4 = 0x00040000;
public static final int Reserved5 = 0x00080000;
public static final int Reserved6 = 0x00100000;
public static final int Reserved7 = 0x00200000;
public static final int Reserved8 = 0x00400000;
public static final int Reserved9 = 0x00800000;
public static final int User1 = 0x01000000;
public static final int User2 = 0x02000000;
public static final int User3 = 0x04000000;
public static final int User4 = 0x08000000;
public static final int User5 = 0x10000000;
public static final int User6 = 0x20000000;
public static final int User7 = 0x40000000;
public static final int User8 = 0x80000000;
// Log level constants (String format)
public static final String FatalStr = "FATAL";
public static final String ErrorStr = "ERROR";
public static final String WarningStr = "WARNING";
public static final String InfoStr = "INFO";
public static final String TraceStr = "TRACE";
public static final String Trace2Str = "TRACE2";
public static final String Trace3Str = "TRACE3";
public static final String DebugStr = "DEBUG";
public static final String Debug2Str = "DEBUG2";
public static final String Debug3Str = "DEBUG3";
public static final String StartStr = "START";
public static final String StopStr = "STOP";
public static final String PassStr = "PASS";
public static final String FailStr = "FAIL";
public static final String StatusStr = "STATUS";
public static final String Reserved1Str = "RESERVED1";
public static final String Reserved2Str = "RESERVED2";
public static final String Reserved3Str = "RESERVED3";
public static final String Reserved4Str = "RESERVED4";
public static final String Reserved5Str = "RESERVED5";
public static final String Reserved6Str = "RESERVED6";
public static final String Reserved7Str = "RESERVED7";
public static final String Reserved8Str = "RESERVED8";
public static final String Reserved9Str = "RESERVED9";
public static final String User1Str = "USER1";
public static final String User2Str = "USER2";
public static final String User3Str = "USER3";
public static final String User4Str = "USER4";
public static final String User5Str = "USER5";
public static final String User6Str = "USER6";
public static final String User7Str = "USER7";
public static final String User8Str = "USER8";
// Constructors - Default monitor mask is 0x00007C07. This causes messages
// with log levels Fatal, Error, Warning, Start, Stop, Pass,
// Fail, and Status to also be logged via the MONITOR
// service
public STAFLog(String logType, String logName, STAFHandle handle);
public STAFLog(String logType, String logName, STAFHandle handle, int mask)
// Methods to actually log a message with a given level
public STAFResult log(int level, String msg)
public STAFResult log(String level, String msg)
public static STAFResult log(STAFHandle theHandle, String logType,
String logName, int level, String msg)
public static STAFResult log(STAFHandle theHandle, String logType,
String logName, String level, String msg)
public static STAFResult log(STAFHandle theHandle, String logType,
String logName, int level, String msg,
int mask)
public static STAFResult log(STAFHandle theHandle, String logType,
String logName, String level, String msg,
int mask)
// Accessor methods
public String getName();
public String getLogType();
public int getMonitorMask();
}
Examples
import com.ibm.staf.*;
import com.ibm.staf.wrapper.*;
...
...
// Create a log object that only logs Fatal and Error messages.
// myHandle is a STAFHandle object that was created earlier.
STAFLog logger = new STAFLog(STAFLog.GLOBAL, "MyLog", myHandle,
STAFLog.Fatal | STAFLog.Error);
STAFResult result;
// Log an error via the instance and static methods
result = logger.log(STAFLog.Error, "Error during test");
result = STAFLog.log(myHandle, STAFLog.GLOBAL, "MyLog", STAFLog.Error,
"Error during test");
// Set a mask to log Fatal, Error, Warning and Info messages.
// Then log a warning via a static method.
int myMask = STAFLog.Fatal | STAFLog.Error | STAFLog.Warning | STAFLog.Info;
result = STAFLog.log(myHandle, STAFLog.GLOBAL, "MyLog", STAFLog.Warning,
"This is just a warning", myMask);
3.5.2 Class STAFMonitor
Definition
package com.ibm.staf.wrapper;
public class STAFMonitor
{
// Constructor
STAFMonitor(STAFHandle stafHandle);
// Methods to log data to the MONITOR service
public STAFResult log(String message);
public static STAFResult log(STAFHandle theHandle, String message);
}
Examples
import com.ibm.staf.*;
import com.ibm.staf.wrapper.*;
...
...
// Create a monitor object. myHandle is a STAFHandle object that was created
// earlier.
STAFMonitor monitor = new STAFMonitor(myHandle);
STAFResult result;
// Log a message to the MONITOR service via the instance and static methods
result = monitor.log("Beginning phase 1");
result = STAFMonitor.log(myHandle, "Beginning phase 2");
3.6 Log Viewer / Formatter APIs
3.6.1 Class STAFLogViewer
Description
The STAFLogViewer class provides a Java GUI that can display any STAF log
on any machine currently running STAF.
A STAF log is a binary log file that has been created by the STAF Log service.
This Java class submits requests to STAF, so STAF has to be running.
This Java class can be run as an application via the command line or can be
run via another Java program.
Definition
java com.ibm.staf.STAFLogViewer -help
-queryRequest <LOG QUERY Request>
-machine <Log Service Machine Name>
-serviceName <Log Service Name>
-levelMask <LEVELMASK option>
-fontName <Font Name>
-saveAsDirectory <Directory Name>
-help
-version
You must specify -queryRequest or -help or -version.
-queryRequest specifies the log query options. This option is
required (unless you are specifying the -help or -version
options). It should begin with
the QUERY option and include any additional query options, including
the options to specify whether the log is a GLOBAL, MACHINE, or HANDLE log. You
may not specify the LEVELMASK option within the queryRequest.
To specify the LEVELMASK option, use the -levelMask
option.
public STAFLogViewer(Component parent,
STAFHandle handle,
String queryRequest)
public STAFLogViewer(Component parent,
STAFHandle handle,
String machine,
String queryRequest
public STAFLogViewer(Component parent,
STAFHandle handle,
String machine,
String serviceName,
String queryRequest)
public STAFLogViewer(Component parent,
STAFHandle handle,
String machine,
String serviceName,
String queryRequest,
String levelMask)
public STAFLogViewer(Component parent,
STAFHandle handle,
String machine,
String serviceName,
String queryRequest,
String levelMask,
String fontName)
public STAFLogViewer(Component parent,
STAFHandle handle,
String machine,
String serviceName,
String queryRequest,
String levelMask,
String fontName,
String saveAsDirectory)
java com.ibm.staf.STAFLogViewer -machine staf1f.austin.ibm.com -queryRequest "QUERY machine {STAF/Config/MachineNickname} logname email all"
Examples
java com.ibm.staf.STAFLogViewer -queryRequest "QUERY machine {STAF/Config/MachineNickname} logname eventmanager last 20"
String queryRequest = " QUERY MACHINE {STAF/Config/MachineNickname}" +
" LOGNAME cron CONTAINS " + STAFUtil.wrapData("ID=5 ");
STAFLogViewer logViewer = new STAFLogViewer(
this, // This is Swing component such as JFrame
myHandle, // This is a STAFHandle object
"local",
"LOG",
queryRequest,
"ERROR DEBUG",
"TimesRoman");
3.6.2 Class STAFJVMLogViewer
Description
The STAFJVMLogViewer class provides a Java GUI that can display a
JVM Log for any STAF Java service that is currently registered.
Each Java service that is registered with STAF runs in a JVM (Java Virtual Machine).
A JVM Log is a text log file that is asociated with each JVM created by STAF.
Note that more than one Java service may use the same JVM (and thus share the same
JVM Log file) depending on the options used when registering the service.
Section
4.4 Service Registration in the STAF User's Guide provides more
information on registering STAF Java services using the JSTAF library.
Definition
To execute and get help for the STAFJVMLogViewer class from the command line,
specify the following:
java com.ibm.staf.STAFJVMLogViewer -help
-machine <Machine where the STAF Java service is registered>
-serviceName <Java Service Name>
-displayAll
-fontName <Font Name>
-help
-version
-machine specifies the endpoint for the machine where the STAF JVM
log is located. This option is optional. The default is local.
public STAFJVMLogViewer(Component parent,
STAFHandle handle,
String serviceName)
public STAFJVMLogViewer(Component parent,
STAFHandle handle,
String machine,
String serviceName)
public STAFJVMLogViewer(Component parent,
STAFHandle handle,
String machine,
String serviceName,
boolean displayAll,
String fontName)
If you don't specify the -service <Java Service Name> option, the following
dialog is displayed which shows a list of Java services currently registered
on machine staf1a.
java com.ibm.staf.STAFJVMLogViewer -machine staf1a
Examples
java com.ibm.staf.STAFJVMLogViewer -serviceName Cron
java com.ibm.staf.STAFJVMLogViewer -serviceName STAX -machine server1.company.com
java com.ibm.staf.STAFJVMLogViewer -machine server1.company.com
import com.ibm.staf.*;
...
STAFJVMLogViewer logViewer = new STAFJVMLogViewer(
this, // This is Swing component such as JFrame
myHandle, // This is a STAFHandle object that you're already created
"local",
"STAX");
import com.ibm.staf.*;
...
boolean displayAll = true;
String cronServiceMachine = "server1.company.com";
String cronServiceName = "CRON";
String fontName = "Dialog";
STAFJVMLogViewer logViewer = new STAFJVMLogViewer(
this, // This is Swing component such as JFrame
fHandle, // This is a STAFHandle object that you're already created
cronServiceMachine,
cronServiceName,
displayAll,
fontName);
3.6.3 Class STAFLogFormatter
Description
The STAFLogFormatter class allows you to format a STAF log (which
is a binary file that has been created by the STAF Log service) as html
or text.
STAF local LOG QUERY GLOBAL LOGNAME test1 LAST 3
20131205-13:54:42 Info Step 1 of ScenarioB completed
20131205-13:54:45 Info Step 2 of ScenarioB completed
20131205-13:54:54 Pass Scenario completed
Definition (when run as an application)
java com.ibm.staf.STAFLogFormatter -help
-queryRequest <LOG QUERY Request>
-fileName <File Name>
-type <html | text>
-fontName <Font Name>
-title <Title>
-machine <Log Service Machine Name>
-serviceName <Log Service Name>
-help
-version
You must specify one of the following options:
-queryRequest or -help or -version.
If specifying the -help or -version option, it must be the first and only
option specified. All of the other options require the -queryRequest option
to be specified.
-queryRequest specifies the QUERY request to submit to the Log
service. This option is required unless you specified -help or -version.
It should begin with the QUERY option and include any additional
query options, including the options to specify whether the log is a
GLOBAL, MACHINE, or HANDLE log. You may not specify the TOTAL
or STATS option within the queryRequest.
Definition (when constructed and used from a Java application)
package com.ibm.staf;
public class STAFLogFormatter
{
public STAFLogFormatter(STAFMarshallingContext context) throws STAFException
public void setFileName(String fileName)
public void setFontName(String fontName)
public void setTitle(String title)
public String format(String typeString) throws IOException, STAFException
}
Examples
C:\>java com.ibm.staf.STAFLogFormatter -type text -machine client1.company.com -queryRequest "QUERY GLOBAL LOGNAME test1 LAST 7"
20131205-13:53:57 Info Step 1 of ScenarioA completed
20131205-13:54:06 Info Step 2 of ScenarioA completed
20131205-13:54:12 Info Step 3 of ScenarioA completed
20131205-13:54:27 Pass ScenarioA completed
20131205-13:54:42 Info Step 1 of ScenarioB completed
20131205-13:54:45 Info Step 2 of ScenarioB completed
20131205-13:54:54 Pass Scenario completed
C:\>java com.ibm.staf.STAFLogFormatter -fileName C:\logs\job1.html -queryRequest "QUERY MACHINE {STAF/Config/MachineNickname} LOGNAME STAX_Job_1 ALL"
String logName = "STAX_Job_1";
String queryRequest = "QUERY MACHINE {STAF/Config/MachineNickname} " +
"LOGNAME " + logName + " ALL";
STAFResult queryResult = fHandle.submit2("local", "LOG", queryRequest);
if ((queryResult.rc != STAFResult.Ok) && (queryResult.rc != 4010))
{
System.out.println(
"Log query request failed with RC=" + queryResult.rc +
", Result=" + queryResult.result);
return;
}
try
{
STAFLogFormatter logFormatter = new STAFLogFormatter(
queryResult.resultContext);
logFormatter.setFileName("/logs/" + logName + ".html");
logFormatter.setTitle(logName + " Log");
logFormatter.setFontName("courier");
logFormatter.format("html");
}
catch (Exception e)
{
System.out.println(
"Formatting/saving the log as html failed.\n" + e.toString());
return;
}
4.0 Java Program Examples
4.1 Example 1
This Java example program is a multi-threaded STAF PING test.
The syntax to run this program is:
C:\>java JPing
Usage: java JPing
For each thread specified by the "# Threads" parameter), this program submits
a PING request to the PING service to ping the machine specified by the
"Where" parameter, repeating the request the number of times
specified by the "# Loops per thread" parameter.
A status message is displayed each time a number of loops
have completed based on the "Display Modulus" parameter.
When complete, an average number of pings per seconds is printed.
/*****************************************************************************/
/* Software Testing Automation Framework (STAF) */
/* (C) Copyright IBM Corp. 2001 */
/* */
/* This software is licensed under the Eclipse Public License (EPL) V1.0. */
/*****************************************************************************/
//===========================================================================
// JPing - A multi-threaded STAF PING test
//===========================================================================
// Accepts: Where to PING
// Optionally, the number of threads to use (default = 5)
// Optionally, the number of loops per thread (default = 10000)
// Optionally, the display modulus (default = 250)
//
// Returns: 0 , on success
// >0, if an error is encountered
//===========================================================================
// Date Who Comment
// ---------- ------------ ------------------------------------------
// 04/25/1998 C. Rankin File Created
//===========================================================================
import com.ibm.staf.*;
import java.util.Date;
import java.util.Calendar;
import java.text.DateFormat;
public class JPing implements Runnable
{
// Constructor
public JPing(int numLoops, int displayModulus, int myThreadNum)
{
loopCount = numLoops;
modulus = displayModulus;
threadNum = myThreadNum;
errors = 0;
}
// This is the main command line entry point
public static void main(String [] argv)
{
// Verify the command line arguments
if ((argv.length < 1) || (argv.length > 4))
{
System.out.println();
System.out.println("Usage: java JPing <Where> [# Threads] " +
"[# Loops per thread] [Display Modulus]");
System.out.println();
System.out.println("Defaults:");
System.out.println();
System.out.println(" # Threads = 5");
System.out.println(" # Loops per thread = 10000");
System.out.println(" Display Modulus = 250");
System.out.println();
System.out.println("Examples:");
System.out.println();
System.out.println("java JPing local");
System.out.println("java JPing SomeServer 3 1000 100");
System.exit(1);
}
// Register with STAF
try
{
handle = new STAFHandle("Java_Ping_Test");
}
catch (STAFException e)
{
System.out.println("Error registering with STAF, RC: " + e.rc);
System.exit(1);
}
// Initialize variables
timeFormatter = DateFormat.getTimeInstance(DateFormat.MEDIUM);
where = argv[0];
int numThreads = 5;
int numLoops = 10000;
int displayModulus = 250;
if (argv.length > 1) numThreads = Integer.parseInt(argv[1]);
if (argv.length > 2) numLoops = Integer.parseInt(argv[2]);
if (argv.length > 3) displayModulus = Integer.parseInt(argv[3]);
JPing [] pingers = new JPing[numThreads];
Thread [] threads = new Thread[numThreads];
System.out.println("(0)" + timeFormatter.format(new Date()) +
" - Started");
long startSecs = (new Date()).getTime();
// Start the threads
for(int i = 0; i < numThreads; ++i)
{
pingers[i] = new JPing(numLoops, displayModulus, i + 1);
threads[i] = new Thread(pingers[i]);
threads[i].start();
}
// Wait for all the threads to finish
for(int i = 0; i < numThreads; ++i)
{
try
{
threads[i].join();
}
catch (Exception e)
{
System.out.println("Exception: " + e);
System.out.println(e.getMessage());
}
}
// Output final pings/sec
long stopSecs = (new Date()).getTime();
System.out.println("(0)" + timeFormatter.format(new Date()) +
" - Ended");
System.out.println("Average: " + ((numLoops * numThreads * 1000) /
(stopSecs - startSecs)) + " pings/sec");
// Unregister with STAF
try
{
handle.unRegister();
}
catch (STAFException e)
{
System.out.println("Error unregistering with STAF, RC: " + e.rc);
System.exit(1);
}
}
// This is the method called when each thread starts
public void run()
{
for(int i = 1; i <= loopCount; ++i)
{
STAFResult result = handle.submit2(where, "PING", "PING");
// If we get a non-zero return code, or a response of something
// other than "PONG", display an error
if (result.rc != 0)
{
System.out.println("(" + threadNum + ")" +
timeFormatter.format(new Date()) +
" - Loop #" + i + ", Error #" +
++errors + ", RC: " + result.rc);
}
else if (result.result.compareTo("PONG") != 0)
{
System.out.println("(" + threadNum + ")" +
timeFormatter.format(new Date()) +
" - Loop #" + i + ", Error #" +
++errors + ", RESULT = " + result.result);
}
// If we are at our display modulus display a status message
if ((i % modulus) == 0)
{
System.out.println("(" + threadNum + ")" +
timeFormatter.format(new Date()) +
" - Ended Loop #" + i + ", Errors = " +
errors);
}
}
}
private static STAFHandle handle;
private static String where;
private static DateFormat timeFormatter;
private int loopCount;
private int modulus;
private int threadNum;
private int errors;
}
Sample results could be:
C:\>java JPing local
(0)4:20:49 PM - Started
(1)4:20:50 PM - Ended Loop #250, Errors = 0
(3)4:20:50 PM - Ended Loop #250, Errors = 0
(2)4:20:50 PM - Ended Loop #250, Errors = 0
(5)4:20:50 PM - Ended Loop #250, Errors = 0
(4)4:20:50 PM - Ended Loop #250, Errors = 0
(3)4:20:51 PM - Ended Loop #500, Errors = 0
(1)4:20:51 PM - Ended Loop #500, Errors = 0
(2)4:20:51 PM - Ended Loop #500, Errors = 0
(5)4:20:51 PM - Ended Loop #500, Errors = 0
(4)4:20:51 PM - Ended Loop #500, Errors = 0
(3)4:20:52 PM - Ended Loop #750, Errors = 0
(1)4:20:52 PM - Ended Loop #750, Errors = 0
(2)4:20:52 PM - Ended Loop #750, Errors = 0
(5)4:20:52 PM - Ended Loop #750, Errors = 0
(4)4:20:52 PM - Ended Loop #750, Errors = 0
...
(2)4:21:19 PM - Ended Loop #9500, Errors = 0
(1)4:21:19 PM - Ended Loop #9500, Errors = 0
(3)4:21:19 PM - Ended Loop #9500, Errors = 0
(4)4:21:20 PM - Ended Loop #9500, Errors = 0
(5)4:21:20 PM - Ended Loop #9500, Errors = 0
(2)4:21:20 PM - Ended Loop #9750, Errors = 0
(1)4:21:20 PM - Ended Loop #9750, Errors = 0
(3)4:21:20 PM - Ended Loop #9750, Errors = 0
(4)4:21:20 PM - Ended Loop #9750, Errors = 0
(5)4:21:20 PM - Ended Loop #9750, Errors = 0
(2)4:21:21 PM - Ended Loop #10000, Errors = 0
(1)4:21:21 PM - Ended Loop #10000, Errors = 0
(3)4:21:21 PM - Ended Loop #10000, Errors = 0
(4)4:21:21 PM - Ended Loop #10000, Errors = 0
(5)4:21:21 PM - Ended Loop #10000, Errors = 0
(0)4:21:21 PM - Ended
Average: 1566 pings/sec
C:\>
4.2 Example 2
This Java example program shows how you can use the MONITOR service to
log a message to update the status of the test.
The syntax to run this program is:
C:\>java com.ibm.staf.service.stax.TestProcess
Usage: java TestProcess loopCount incrementSeconds returnCode
where:
This program submits a LOG request to the MONITOR service stating which loop
it is currently running. It submits a MONITOR LOG request at the beginning
of each loop and then sleeps the specified number of incrementSeconds.
When complete, it returns the specified returnCode.
/*****************************************************************************/
/* Software Testing Automation Framework (STAF) */
/* (C) Copyright IBM Corp. 2002 */
/* */
/* This software is licensed under the Eclipse Public License (EPL) V1.0. */
/*****************************************************************************/
import com.ibm.staf.*;
import java.util.*;
public class TestProcess implements Runnable
{
private STAFHandle handle = null;
private int counter;
private int loopCounter;
private int incrementSeconds;
private int returnCode;
public static void main(String[] args)
{
if (args.length < 3)
{
System.out.println("Usage: java TestProcess loopCount" +
" incrementSeconds returnCode");
System.exit(1);
}
try
{
int loopCounter = (new Integer(args[0])).intValue();
int incrementSeconds = (new Integer(args[1])).intValue();
int returnCode = (new Integer(args[2])).intValue();
TestProcess testProcess = new TestProcess(loopCounter,
incrementSeconds,
returnCode);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public TestProcess(int loopCounter, int incrementSeconds,
int returnCode)
{
this.loopCounter = loopCounter;
this.incrementSeconds = incrementSeconds;
this.returnCode = returnCode;
this.run();
}
public void run()
{
try
{
// register with STAF
handle = new STAFHandle("TestProcess");
System.out.println("STAF handle: " + handle.getHandle());
STAFResult res = handle.submit2(
"local", "VAR",
"RESOLVE STRING {STAF/Config/MachineNickname}");
if (res.rc != 0)
{
System.out.println(
"Error resolving {STAF/Config/MachineNickname}." +
" RC: " + res.rc + " Result: " + res.result);
terminate();
}
System.out.println(
"STAF/Config/MachineNickname: " + res.result);
}
catch(STAFException e)
{
System.out.println("Error registering with STAF");
terminate();
}
for (int i=0; i < loopCounter; i++)
{
STAFResult result = handle.submit2(
"local", "monitor", "log message " +
STAFUtil.wrapData("Loop #" + String.valueOf(i)));
System.out.println("Loop #" + String.valueOf(i));
try
{
Thread.sleep(incrementSeconds * 1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
terminate();
}
public void terminate()
{
try
{
if (handle != null)
{
handle.submit2("local", "monitor", "log message " +
STAFUtil.wrapData("Terminating "));
// unregister
handle.unRegister();
}
}
catch(STAFException e)
{
/* do nothing */
}
finally
{
System.exit(returnCode);
}
}
}
Here's an example of running the sample program:
C:\dev\sf\src\staf\test>java TestProcess 3 2 0
STAF handle: 127
STAF/Config/MachineNickname: sharon
Loop #0
Loop #1
Loop #2
C:\>
While this program is running, you can query the MONITOR
service to see get the latest message that the TestProcess
program logged. For example:
C:\>staf local monitor query machine sharon handle 118
Response
--------
Date-Time: 20140516-17:08:44
Message : Loop #0
C:\>staf local monitor query machine sharon handle 118
Response
--------
Date-Time: 20140516-17:08:49
Message : Loop #1
C:\>staf local monitor query machine sharon handle 118
Response
--------
Date-Time: 20140516-17:08:54
Message : Loop #2
C:\>staf local monitor query machine sharon handle 118
Response
--------
Date-Time: 20140516-17:08:59
Message : Terminating
5.0 How to Test STAF Java Support
5.1 Class TestJSTAF
Definition
Usage: java com.ibm.staf.TestJSTAF <Endpoint | LOCAL> <Service> <Request>
Examples
C:\> java com.ibm.staf.TestJSTAF LOCAL MISC VERSION
TestJSTAF using STAF handle 15
RC=0
Result=3.4.18
C:\> c:\jdk1.7.0\jre\bin\java com.ibm.staf.TestJSTAF LOCAL PING PING
TestJSTAF using STAF handle 19
RC=0
Result=PONG
C:\> java com.ibm.staf.TestJSTAF machineA.company.com VAR RESOLVE STRING {STAF/Config/OS/Name}
TestJSTAF using STAF handle 27
RC=0
Result=Win7
*** End of Document ***