Monarch Job and Program Classes

The Monarch Execution Context portion of the framework includes the ASNA.Monarch.Job class that supplements a process (or thread) in the implementation of the concept of a job. The Job class provides an environment for Monarch programs to run under. Its main functions are maintaining program activation and a connection to the database server. The Job class also provides facilities to support certain IBM i concepts, like when overriding file parameters or local data areas.

Programs

When an application is migrated from IBM i; each program is transformed into an AVR class. In Monarch context, these classes are still referred to as "Programs". A Program is a class that conforms to certain conventions allowing it to be the target of a CALLB operation. The class has to implement the *Entry procedure (see topic below for more information). To allow the retaining of state across program calls, the class should derive from the ASNA.Monarch.Program class that works in conjunction with the ASNA.Monarch.Job class.

Besides the *Entry procedure, a Monarch program typically has a constructor and a dispose subroutine. In the constructor, the program opens all the files that were marked as being implicitly opened, that is, those not tagged as user controlled. The constructor is also responsible for initializing any data structure subfields requiring values other than zeros or blanks. The dispose subroutine provides the opportunity to close files and release any unmanaged resources.

The Job maintains an activation manager responsible for handling the activations of programs according to the ActivationGroup custom attribute defined in the BegClass of the program. The ActivationGroup attribute takes a string as a parameter that can be one of the following:

  • Name – A user provided name identifying the activation group to use for the program.
  • *Default – A predefined activation group called *Default. Programs not marked with an ActivationGroup attribute are allocated in this group.
  • *New – This special value indicates that the program is to be run in a new activation group. Monarch will create a new unique name for the group.
  • *Caller – This special value states that the program will be allocated in the same activation group as the program calling this program.

An example of the ActivationGroup attribute for each type (highlighted bold) follows:

BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) + 
			Attributes(ActivationGroup( "myGroupName" ))
BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) +
			Attributes(ActivationGroup( "*Default" ))
BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) + 
			Attributes(ActivationGroup( "*New" ))  
BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) +
			Attributes(ActivationGroup( "*Caller" )) 

Instead of using hard-coded string literals for the special values, the class provides the following three constants:

  • ActivationGroupAttribute.Caller
  • ActivationGroupAttribute.Default
  • ActivationGroupAttribute.New

An example using each of these is shown below:

BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) + 
			Attributes(ActivationGroup( ActivationGroupAttribute.Default ))
BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) + 
			Attributes(ActivationGroup( ActivationGroupAttribute.New ))
BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) +
			Attributes(ActivationGroup( ActivationGroupAttribute.Caller ))

Monarch also defines a couple of attributes to use as a "shorthand" for the cases of *New and *Caller, these are: NewActivationGroupAttribute and CallerActivationGroupAttribute. Using this shorthand, you could code something like this (both shown):

BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) +
			Attributes(NewActivationGroup())
BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public ) +
			Attributes(CallerActivationGroup ())

The "*Entry Procedure" figure in the next section shows a program marked to run inthe activation group "HardWater".

The *Entry Procedure

As part of the migration process of a program, Monarch converts the mainline C-Specs into a procedure called *Entry in the generated class.

BegClass Custcalc Extends(ASNA.Monarch.Program Access( *Public ) +
			Attributes(ActivationGroup("HardWater"))
   . . .
  DclFld Cust#    Type ( *Packed ) Len( 9,0 )   
  DclFld Cust#Ch  Type ( *Char   ) Len( 9   )
  DclFld SalesCh  Type ( *Char   ) Len( 13  )
  DclFld ReturnCh Type ( *Char   ) Len( 13  )

  BegProc *Entry Access ( *Public )
    DclSrParm Cust#Ch  By ( *Reference ) Options( *NoPass )   
    DclSrParm SalesCh  By ( *Reference ) Options( *NoPass )
    DclSrParm ReturnCh By ( *Reference ) Options( *NoPass )
    . . .
  EndProc

The *Entry Figure above shows the generated *Entry. Notice how the Parms in the *ENTRY PLIST become the parameters to the *Entry procedure.

MyJob

Each application has to be associated with a job. This is achieved via the MyJob class that extends ASNA.Monarch.Job. This class is generated by Monarch and is available to be augmented. MyJob is responsible for two main tasks: provide a connection to the databases and invoke the startup program in the application.

MyJob.MyDatabase and optionally MyJob.MyPrinterDB are defined in MyJob. MyDatabase is used for externally described data structures, for data file and data area access, and to call programs back on the server. MyPrinterDB is used to access print files. These database connections are used in two distinct forms; the commands refer to them to obtain their external definitions at compile time, and they are used at runtime to connect to the server.

When a program has to access the database at runtime, or any other of the members of the MyJob class or its base, it is necessary to obtain a reference to the instance associated with this job. This is done using the MonarchJob property provided by the base class ASNA.Monarch.Program. An example follows.

BegClass Custcalc Extends(ASNA.Monarch.Program Access( *Public ))
    . . .
    BegConstructor Access ( *Public )
        . . .
        Open CSMASTERL1  DB (MonarchJob.Database)    
        Open CMMASTERL1  DB (MonarchJob.Database)  
    EndConstructor

As we will see in a later chapter, web applications are run in a multi-threaded environment, the MonarchJob property gets the instance object of the MyJob class associated with the particular thread running the program.

The MonarchJob property has a type of ASNA.Monarch.Job, if you need to refer to members in the class that you added to MyJob, then you should cast the value of MonarchJob using the *AS operator. This example shows how to access a field called MyField.

BegClass Custcalc Extends(ASNA.Monarch.Program) Access( *Public )
. . .
  BegSr exampleSR  Access( *Public )
      DclFld X Type ( *Char  ) Len( 10 )
             X = (MonarchJob *AS MyJob).MyField
    . . .
EndClass

Alternatively, you can use the Job's built-in LDC (local data collection) to provide access to objects and values to ASNA.Monarch.Program classes.

Startup Program

One of the main functions of MyJob is to get the program call sequence going. This is done by invoking the first program in the sequence of calls. This is known as the startup program.

A console program's My Job is typically also responsible for processing the command line. The following figure shows a MyJob sample where the startup program called is CUSTPRTS.

BegClass MyJob Extends(ASNA.Monarch.Job) Access( *Public )
. . .
    BegSr ExecuteStartupProgram Access( *Protected )
        DclSrParm CustNumber Type ( *Char  ) Len( 9 )
        DclFld SendMsg       Type ( *Char  ) Len( 3 )
        Connect MyDatabase    
        Connect MyPrinterDB
        Move 'NO '  SendMsg
        Call CUSTPRTS
        DclParm    CustNumber
        DclParm    SendMsg
        EndPrograms()
     EndSr

     BegSr Main Shared(*Yes) Access(*Public)
         DclSrParm Args Type(*String) Rank(1)
         DclFld job Type(MyJob) New()
         checkParms(Args)
         job.ExecuteStartupProgram(Args[0])
     EndSr

EndClass

The Main subroutine receives the parameters from the command line in the Args array. After being validated, the job's ExecuteStartupProgram is called passing the first argument as a parameter. In this case it represents a customer number. The ExecuteStartupProgram routine connects to the databases and invokes the CUSTPRTS program. When CUSTRPRTS (and all the programs it calls) end, the EndPrograms method of ASNA.Monarch.Job is called to deactivate any program that is still active and then the Dispose method of ASNA.Monarch.Job is called. This method is typically overwritten to close databases and release any other resource kept by the job.

Additional Embedded SQL Code

The following MyJob.vr shows a typical program with the additional code highlighted for the SQL connection established for processing embedded SQL. Notice the /Error statements generated as a reminder to change the code if MS SQL Server is used.

For additional detail and other Monarch Framework classes that support embedded SQL, refer to SQL Migration Overview.

Using System
Using MyCompany.MyApplication
DclNamespace MyCompany.MyApplication.GroupAll_Job
BegClass MyJob Extends(ASNA.Monarch.WebJob) Access(*Public)
  DclDB Name(MyDatabase) DBName("*Public/DG NET Local")Access(*Public)
  DclDB Name(MyPrinterDB) DBName("DG Net Local")Access(*Public)
  // additional declarative
  DclFld ADO_Connection Type(System.Data.Odbc.OdbcConnection) Access(*Public)
/Error When using MS SQL Server, replace System.Data.Odbc.OdbcConnection with +
/System.Data.SqlClient.SqlConnection

BegFunc getDatabase Type(ASNA.isualRPG.Runtime.Database) Access(*Protected) Modifier(*Overrides)
    LeaveSR MyDatabase
EndFunc
BegFunc getPrinterDB Type(ASNA.isualRPG.Runtime.Database) Access(*Protected) Modifier(*Overrides)
    LeaveSR MyPrinterDB
EndFunc

 // additional property
BegFunc getADO_Connection Type(System.Data.Common.DbConnection) Access(*Protected) Modifier(*Overrides)
   LeaveSR ADO_Connection
EndFunc BegSr Dispose Access(*Public) Modifier(*Overrides)
    DclSrParm disposing Type(*Boolean)
    If disposing
        Disconnect MyDatabase
        Disconnect MyPrinterDB
// additional dispose of ADO_Connection
        ADO_Connection.Close()
        ADO_Connection.Dispose()
    EndIf
   *Base.Dispose(Disposing)
EndSr
BegSr ExecuteStartupProgram Access(*Protected) Modifier(*Overrides)
      Connect MyDatabase
      Connect MyPrinterDB

 // additional code for ExecuteStartupProgram for the ADO connection
      DclFld connectStr Type(*String)   
      connectStr=string.Format("Driver={{ClientAccessODBCDriver(32-bit)}}; +
         "++"System={0};DBQ={1},*USRLIBL;Uid={2};Pwd={3}", +
         MyDatabase.Server, +
         MyDatabase.DBName, +
         MyDatabase.User, +
         /* Add your password here */ )
/Error When using MS SQL Server, replace connectStr assignment with "Data Source={0};Initial +
    Catalog={1};Integrated Security=True"

        ADO_Connection = *New System.Data.Odbc.OdbcConnection( connectStr )
/Error When using MS SQL Server, replace *New System.Data.Odbc.OdbcConnection with *New System.Data.SqlClient.SqlConnection

        ADO_Connection.Open()
        CallD 'MyCompany.MyApplication.Db0720'
EndSr
EndClass 

CLProgram

Usage of CL can be divided into two major categories: System Administration and Application Coordination.

The administration of the system involves operations like the creation of user profiles and the save/restore procedures. These activities are not considered part of the application itself and Monarch does not attempt to facilitate such activities. Normal Windows® techniques should be employed to affect these kinds of activities.

CL is used to setup the environment for RPG programs to run. The Monarch Framework, through CL Program class, provides support for CL program procedures in these areas:

  • Sets up the Library List. The Library List is an ordered set of directory names associated with each application's database connection.
  • Overrides database file. File Overrides are commands to replace the database file named in a CL procedure or program or to change certain parameters of the existing database file. These overrides can be applied to DBFile, PrintFile, or a WorkStnFile object. This may be especially useful for files that have been renamed or moved since the procedure or program was created. It can also be used to access a file member other than the first member.
  • Maintain application parameters in data area. This covers several areas.
    A local data area is created for each job in the system. The system creates a local data area, which is initially filled with blanks, with a length of 1024 and type *CHAR. When you submit a job, the value of the submitting job's local data area is copied into the submitted job's local data area. You can use this local data area to pass information to a procedure or program without the use of a parameter list.
    Associated with each job are a set of job properties or attributes. These attributes can be programmatically accessed in CL via the RTVJOBA commands. Another of these attributes is a series of 8 switches that can be "on" or "off." RPG programs also have access to these switches via the *INUx indicators.

Next: Display File Concepts

Previous: Control Execution Context

See Also

SQL Migration Overview
Job Class
Job.Database Property
Job.PrinterDB Property
Program Class
CLProgram Class
ActivationGroupAttribute Class
NewActivationGroupAttribute Class
CallerActivationGroupAttribute Class