Triggering WebFOCUS Reporting
By Darin Lee
Problem

Currently, letters are generated out of our legacy production system for our claims department. The system exists on the mainframe and is written in Natural using ADABAS as a data source. These letters include many that go out to claimants.  Being generated from the mainframe environments, they are rather ugly - using standard Courier fonts, no graphics, etc. and must be printed to specific printers that have letterhead paper loaded. The “higher ups” decided that these letters needed to be automatically generated some other way that would allow for a professional look and greater flexibility in distribution. WebFOCUS takes care of delivering the professional letters and forms with graphics, etc., but the question is how to make it respond to events happening in the legacy system.

Solution

The generation of the reports in the production system is generated by a user keystroke (PF9) which submits a batch job at the OS level - in this case JCL is submitted. Using that same trigger, the batch job can be modified to accomplish the necessary steps.

  1. Generate all necessary parameter values for the FEX that will run
  2. Generate the parm strings that will be submitted to the ReportCaster API subroutines, including &vars with calculated variable lengths, distribution method (email, printer, etc) and destination information (Printer IP address, email address)
  3. Generate the command that will start up a WF Server session and execute a server procedure, passing the necessary parameters

 

In our environment, (server is on USS on mainframe) the output of this batch job would look something like

oshell /home/ibi/srv71/wfs/bin/edastart –x “EX runrcjob DEST=10.100.100.10, VAR1=ENGLAND”

From there, the server job “runrcjob” includes the following code to manipulate a distribution list and execute the procedure:
-* File runrcjob.fex
-SET &DLEN=&DEST.LENGTH ;
-SET &STRING1='COUNTRY='|&VAR1 ;
-SET &STRING1L=&STRING1.LENGTH ;
-* replace EXISTING RC SCHEDULE
-SET &SUBERR = DSTBULK(
- 'uname',5,                 (Must be valid MRE and WF Server id, number is                                        calculated length-applicable for all parms in API)
- 'upass',5,                 (for above account)
- 'webserver.wcfgroup.com:80',25, (location of client and web server port)
- 'autoprint',9,                  (name of distribution address list)
- 'R',1,                     (R=Replace)
- ' ',0,                     (place holder for unused parm)
- ' ',0,                     (place holder for unused parm)
- 'admin',5,                 (owner of the above named list)
- ' ',0,                     (placeholder for unused parm)
- 'blankprint',10,           (name of a distribution list which is blank)
- ' ',0,                     (placeholder for webserver credentials(unused))
- 0,                         (optional tcpiplevel parm)  
- 'I4');                     (static)
-RUN
-* add the new record to distribution file
-ADD_NEW
-SET &SUBERR = DSTMEM(
- 'uname',5,
- 'upass',5,
- 'webserver.ibireports.wcfgroup.com:80',25,
- 'autoprint',9,                  (name of distribution list)
- 'A',1,                     (A=Add new record)
- 'admin',5,                 (owner of above named list)
- ' ',0,                     (placeholder for unused parm (burst value))
- &DEST,&DLEN,               (DEST=IP address for printer or queuename@IPAddress,                                  DLEN=length of IP address)
- ' ',0,                     (placeholder for webserver credentials(unused))
- 0,                         (optional tcpiplevel parm)  
- 'I4');                     (static)
-RUN
-*run the scheduled job
-SET &SUBERR = DSTRUN(
- 'uname',5,
- 'upass',5,
- 'webserver.wcfgroup.com:80',25,
- ' ',0,
- 'carinst',7,               (name of FEX located on WF Server)
- 1,                         (priority of job)
- 'admin',5,                 (owner of RC job)
- &STRING1, &STRING1L,            (parameters needed by carinst FEX)        
- ' ',0,                     (placeholder for webserver credentials(unused))
- 0,                         (optional tcpiplevel parm)  
- 'I4');                     (static)

Pre-requisites for the above code include:

  1. Creating an RC job for the procedure (carinst) that will print to a distribution list called autoprint using an output format that will print to a printer such as .PS, .DOC, .WP
  2. Creating an RC distribution list for printing called autoprint (no burst value, doesn’t matter what IP is initially used)
  3. Creating an RC distribution list for printing called blankprint , which is empty.

                  Since RC won’t let you create an empty Distribution List, I created one with IP address 0.0.0.0, then used the                             following code in a server procedure to remove that record:
-SET &SUBERR = DSTMEM(
- 'uname',5,
- 'upass',5,
- 'webserver.wcfgroup.com:80',25,
- 'blankprint',10, (name of Distribution address list)
- 'D',1,           (D=delete record)
- 'admin',5,       (owner of above name address list)
- ' ',0,           (placeholder for burst value (unused))
- '0.0.0.0',8,      (value of destination to be deleted)
- ' ',0,           (placeholder for webserver credentials(unused))
- 0,               (optional tcpiplevel parm)  
- 'I4');           (static)

The rationale for managing the distribution list this way is the following. The API routines allow for Create New List, Add New Records, Replace all Records, and Delete list in bulk (DSTBULK), and Create new list member and Delete list member (DSTMEM).  Since I don’t know what is the exact value of the last IP address used, (which would be required in the DSTMEM routine to delete that record), I found it easier to just replace the whole list using DSTBULK with a blank list, then add the single new member as needed. There is no subroutine to insert a single printer address for RC job output (as opposed to a distribution list or file). (You can do this with Java and the API, but I am avoiding that for now.) You could also manipulate with TABLE and MODIFY on RC tables BOTADDR and BOTDEST, but this way was easier and less steps.

The last step is to execute the RC job immediately using DSTRUN, passing the values for all the &variables. This job always uses the same distribution list, autoprint, but it has been dynamically modified to use the printer destination input (or predetermined) by users.

So the course of action is:

  1. User is in legacy system and presses PF9 to request a report
  2. PF9 trigger submission of JCL to determine parm values and start a WF session execution server procedure runrcjob
  3. Server procedure uses API subroutines DSTBULK and DSTMEM to remove previous value from autoprint list and add new print IP address into list
  4. Server procedure uses API subroutine to execute immediately the server procedure (carinst) and pass needed parms
  5. ReportCaster executes the scheduled job, sending the output to any desired printer

For porting to any platform:
Determine the best method for submitting a batch job (JCL, Unix script, DOS Batch, etc.)
Determine how the legacy system will trigger that job
Create batch job to create/format parm values and startup a WF session executing a procedure with parms
Create runrcjob.fex server procedure. You could even parameterize the schedule that you want to run from the submitted batch job.
Set up scheduled job and distribution lists in ReportCaster
Same procedures could be used for email or FTP by creating RC distribution lists for those distribution methods

Other concerns that need to be addressed:
Security for server procedures
Delays in running RC jobs (crossing up reports with destinations)

If any questions, please contact Darin at dlee@wcfgroup.com.