- 1 Introduction
- 2 Overview of the RPG Mail Engine framework
- 3 Installation
- 4 The components of RPG Mail Engine and how they work
I have built the RPG Mail Engine based on the concept by Aaron Bartell's RPG Chart Engine . I have reused and/or amended much of the code and presentation.
- Please email me in order for me to email the source code to you, as the file formats are not allowed to be uploaded to the wiki server.
Java 1.4 and upwards can be used
Startup of Java applications can be very time-consuming due to the JVM (Java Virtual Machine) initialisation. Using the RPG Mail Engine technique, this problem is addressed by adding a data queue messaging layer between the RPG and Java. This creates an environment where the JVM startup occurs only once per machine allowing your Java to run entirely in batch, with no performance penalty.
Overview of the RPG Mail Engine framework
- Make call to the RME_newMail sub procedure, which in turn does a WRITE to RMEMAILPF containing all the information needed to send an email.
- Execute RME_run, which writes a record with a with a unique key to data queue DQRME.
- The RPG program immediately goes to wait for a response on the same data queue for the same unique key.
- The Java program RPGMailEngine.java is listening for new entries on data queue DQRME.
- The Java uses the unique key from data queue entry to do an SQL select. The SQL select extracts the data out of table/ file RMEMAILPF to obtain the information necessary to send mail.
- If debugging is turned on, the Java program will also trickle statements into a file in the IFS during processing.
- The Java program completes sending of the mail, and writes the result of the mail sending process back to the data queue.
- The RPG program, which has been waiting for a response in step 3, receives the response from the Java program in step 7, and continues processing based on the result.
- Issue the AS/400 command: CRTSAVF FILE(QGPL/RME)
- FTP the file RME from your PC to the AS/400 in BINARY mode into the save file RME in library QGPL.
- Issue the AS/400 command: CRTLIB RME
- Issue the AS/400 command: RSTOBJ OBJ(*ALL) SAVLIB(RME) DEV(*SAVF) SAVF(QGPL/RME) MBROPT(*ALL) ALWOBJDIF(*ALL) RSTLIB(RME)
- Issue the AS/400 commands:
- MKDIR '/java'
- MKDIR '/java/rme'
- FTP the following files to the AS/400 in binary mode to folder /java/rme/
- If not already created, create a file /QIBM/UserData/Java400/SystemDefault.properties, then edit it and add the two lines below.
- QSH CMD('touch /qibm/userdata/java400/SystemDefault.properties')
- EDTF '/qibm/userdata/java400/SystemDefault.properties'
- Issue the AS/400 command to start the Java portion that runs in QBATCH:
- RMESTR DTALIB(RME) DQLIB(RME) DQNAM(DQRME) DQWAIT(-1) DBG(TRUE) DBGFLR('/java/rme/')
- Add library RME to the library list.
- Add a record to the configuration file with the following data : data queue library, data queue name, waiting period, ip address of SMTP server,
- Add a file to the '/java/rme/' directory, and ensure that it is the same name as found in the RMEMAILR program.
- CALL RMEMAILR to see the program in action.
The components of RPG Mail Engine and how they work
Starting the Java process
Calling the command below will in turn call CL program STRRMEC which submits a RUNJVA command in batch.
RME/RMESTR DTALIB(RME) DQLIB(RME) DQNAM(DQRME) DQWAIT(-1) DBG(TRUE) DBGFLR('/java/rme/')
With DBG(TRUE) specified, text will be trickled into /java/rme/rme_debug_2007-Apr-09.log
If you do a WRKACTJOB, you will see two jobs running :
Job User Type -----Status----- Function RMERUNJVA GUREN001 BATCH ACTIVE CMD-RUNJVA QJVACMDSRV GUREN001 BATCHI ACTIVE JVM-RPGMailEng
The Java program is now waiting for entries on the data queue. You will have noticed that we start the process with a wait of -1. This means we are going to wait indefinitely for entries on the data queue.
Data Queue DQRME
The following command creates the data queue :
CRTDTAQ DTAQ(RME/DQRME) MAXLEN(32766) SEQ(*KEYED) KEYLEN(32) AUTORCL(*YES)
- Data queue DQRME is used to “connect” the RPG and Java programs.
- Two data queues could have been created, one for requests and one for responses, but it is stated in IBM documentation that having a single *KEYED data queue is a better practice if the situation can facilitate it.
- A keyed data queue is neat because you can tell your RPG program to listen for ANY entry or only entries with a specific key.
- In RPG Mail Engine, the Java program is listening for ALL entries, and the RPG program that made the request is waiting for specific uniquely keyed response.
A R MAILR A UID 32 COLHDG('UNIQUE ID') A CRTDT Z COLHDG('CREATION DATE') A FROM 50 COLHDG('FROM') A TO 100 COLHDG('RECIPIENT') A SUBJECT 50 COLHDG('SUBJECT') A MSGTEXT 200 COLHDG('MESSAGE TEXT') A ATTACHMENT 200 COLHDG('ATTACHMENT')
RMEMAILPF is used to hold data that will be needed to send the mail.
RPGMAILR - Sending Mail
uid = RME_newMail('email@example.com':'firstname.lastname@example.org': 'Testing with attachment':'Attachment!': '/java/rme/test.prop'); RME_run(uid: gError);
First execute RME_newMail and pass in parameters to initialise values specific to your business needs ie. email to be sent. A unique number will be passed back that will be used in RME_run. RME_run will add the unique number to the data queue in order for the Java program to pick up the entry.
Java - RPGMailEngine
- When STRRME is executed it instantiates the RPGChartEngine Java object and attaches to the DQRCE data queue waiting for entries. “Instantiates” simply means the Java program goes through it’s initial execution much akin to *INZSR in RPG. As you can see in the code there is a debug statement. This will write out to a file in the IFS if debugging was turned on during startup of this Java process ie. RME/RMESTR DTALIB(RME) DQLIB(RME) DQNAM(DQRME) DQWAIT(-1) DBG(TRUE) DBGFLR('/java/rme/').As soon as an entry is received the processEntry() method is called.
Java - processEntry
- Method processEntry’s purpose is to obtain the unique key value and start a new Java thread. Starting a thread is similar to submitting a job in OS/400; you pass some priming input parms and disconnect from the process so it can do it’s own processing apart from the main process. This enables better throughput as multiple emails can be created at the same time. If any errors occur during this process then a text message will be placed in the debug file residing in the IFS.
Java - MailEngineTransaction
- To create the email at hand the program obviously needs to gain access to the physical file data in RMEMAILPF on the System i. A connection is created to the System i and the data in file RMEMAILPF is read and placed into a “result set”. A result set is exactly similar to a result set in RPG when using embedded SQL.
Java - sendMail
- The data residing in the result set is extracted and used to as input to the sendMail function which will send the email.
- The last step from the Java side is to write a response entry to data queue DQRME. If an error occurs then the RPG program waiting for the response will simply have to time out and appropriately generate a notification so somebody knows the process failed.