Hi Andrew,
thank you for this Java program. I took the liberty to transform it to ooRexx (untested) which
should do the same as your Java program:
/* load the Java class into ooRexx, it will understand ooRexx messages */
MvsConsole = bsf.loadClass("com.ibm.jzos.MvsConsole")
if MvsConsole~isListening<>1 then /* same as .true in ooRexx */
MvsConsle~startMvsCommandListener
rexxCallBack = .CommandCallback~new /* create a Rexx value of type
"CommandCallback" */
/* wrap/box the Rexx value/object as a Java value/object */
boxedCallBack = BsfCreateRexxProxy(rexxCallBack, ,
"com.ibm.jzos.MvsCommandCallback")
MvsConsole~registerMvsCommandCallback(boxedCallBack)
/* ... do whatever you need to do, if anything ... */
/* now wait until the stop event gets received in rexxCallBack */
rexxCallBack~waitForStop /* invocation will block */
::requires "BSF.CLS" /* get ooRexx-Java bridge */
/* ooRexx class defines the Java methods it will serve. Invoking these
Java methods will cause a message of the same name and same arguments
to be sent to the ooRexx value/object which will search and invoke
the appropriate ooRexx method here. */
::class CommandCallback /* implements MvsCommandCallback methods */
::method init /* runs when a value of this type gets created */
expose startTime /* access object variable (attribute) */
startTime=.DateTime~new /* remember current date and time */
::method handleModify
expose startTime /* access object variable (attribute) */
parse arg arg0
if arg0="REPORT" then
say "Runtime:" startTime - .dateTime~new /* deduct current date and
time */
else
say arg0 "not recognized. Valid commands: REPORT"
::method handleStart /* do nothing */
::method handleStop
expose lock /* access object variable (attribute) */
lock = .false /* set lock to 0 */
return .false /* return 0 */
::method waitForStop /* method to block caller until stop occurs */
expose lock /* access object variable (attribute) */
guard on when lock=.false/* wait until control variable is set to .false
*/
A few notes:
- it is not necessary to know Java, one just needs to be able to understand the documentation of the
Java classes that you wish to use from ooRexx, in this case e.g.
<https://www.ibm.com/docs/en/sdk-java-technology/7.1?topic=jzos-mvsconsole> and
<https://www.ibm.com/docs/en/sdk-java-technology/7.1?topic=jzos-mvscommandcallback>. Anyone on this
list will be able to read the Java documentation of these Java classes and understand what is
documented there, I am sure;
- the statements that start with two colons (::) are directives to ooRexx; ooRexx will read a
program, syntax check it, then carry out each directive one by one and at the end will start to
execute the program with the statement starting at line 1
- the "::requires BSF.CLS" directive will cause ooRexx to call the ooRexx program BSF.CLS which will
load the Java bridge and camouflage the strictly typed, case sensitive Java as the dynamically typed
and caseless ooRexx
- the "::class" directive will cause ooRexx to create a class (synonyms: type, structure) and
remember its name
- the "::method" directives will cause ooRexx to create methods, remember their names and the Rexx
code going with them and assign those methods to the previously created class
- any Rexx value (synonyms: object, instance) created from this class will understand all messages
that are named as the methods therein: conceptually, every Rexx value/object/instance is like a
living thing and understands messages it receives by searching a method by the name of the received
message, invoke it (and supply arguments if any) and return any return value, if any
Should there be any questions please do not hesitate and ask them.
---rony
On 22.06.2022 07:31, Andrew Rowley wrote:
On 22/06/2022 9:03 am, Charles Mills wrote:
Can one write a Started Task in Java? What would the JCL look like (neglecting
application-specific items)?
This is a basic Java program that runs and responds to MODIFY and STOP commands:
import java.time.*;
import com.ibm.jzos.MvsCommandCallback;
import com.ibm.jzos.MvsConsole;
public class JavaStc
{
static volatile boolean stopped = false;
static final Instant startTime = Instant.now();
public static void main(String[] args) throws InterruptedException
{
if (!MvsConsole.isListening())
{
MvsConsole.startMvsCommandListener();
}
MvsConsole.registerMvsCommandCallback(new CommandCallback());
while (!stopped)
{
Thread.sleep(1000);
}
}
static class CommandCallback implements MvsCommandCallback
{
public void handleModify(String arg0)
{
if (arg0.equals("REPORT"))
{
Duration runtime = Duration.between(JavaStc.startTime,
Instant.now());
System.out.println("Runtime: " + runtime.toString());
}
else
{
System.out.println(arg0 + " not recognized. Valid commands:
REPORT");
}
}
public void handleStart(String arg0)
{
// do nothing
}
public boolean handleStop()
{
JavaStc.stopped = true;
return false;
}
}
}
JCL to run it under the JZOS batch launcher (which allows you to access JCL DDs from the Java
program):
//G EXEC PGM=JVMLDM80,REGION=256M,
// PARM='/ JavaStc'
//*
//STEPLIB DD DISP=SHR,DSN=VENDOR.LINKLIBE
//*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//STDOUT DD SYSOUT=*
//STDERR DD SYSOUT=*
//CEEDUMP DD SYSOUT=*
//ABNLIGNR DD DUMMY
//*
//STDENV DD *
export JAVA_HOME=/usr/lpp/java/J8.0
LIBPATH=/lib:/usr/lib:"${JAVA_HOME}"/bin
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390/j9vm
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/classic
export LIBPATH="$LIBPATH":
export CLASSPATH="/home/andrewr/java"
IJO="-Xms16m -Xmx128m"
export IBM_JAVA_OPTIONS="$IJO "
This JCL is adapted from the samples provided with JZOS.
One quirk is that the modify commands need to specify APPL=, i.e.
MODIFY JOBNAME,APPL=REPORT
The command callbacks happen on a different thread I think so you need to consider
synchronization. Other than that it is quite simple.
Andrew Rowley
----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN