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

Reply via email to