Difference between revisions of "Mail Engine"

From MidrangeWiki
Jump to: navigation, search
(Installation: make SMTP a link)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
I have built the RPG Mail Engine based on the concept by Aaron Bartell's RPG Chart Engine (http://www.mowyourlawn.com/index.html). I have reused and /or amended much of the code and presentation.  
+
[[Image:Rceframework.png|500px|right]]
<br>
+
==Introduction==
'''Please email me at gareth.uren@hyphen.co.za in order for me to email the source code to you, as the file format are not allowed to be uploaded to the wiki server.'''
+
I have built the RPG Mail Engine based on the concept by Aaron Bartell's RPG Chart Engine [http://www.mowyourlawn.com/index.html]. I have reused and/or amended much of the code and presentation.  
<br>
+
 
 +
;Please [http://wiki.midrange.com/index.php/Special:Emailuser/Garethu 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
 
Java 1.4 and upwards can be used
<br>
+
 
 
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.   
 
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.   
  
[[Image:Rceframework.png | 600px]]
 
  
<br>
 
'''Overview of the RPG Mail Engine framework'''
 
1. 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.
 
2. Execute RME_run, which writes a record with a with a unique key to data queue DQRME.
 
3. The RPG program immediately goes to wait for a response on the same data queue for the same unique key.
 
4. The Java program RPGMailEngine.java is listening for new entries on data queue DQRME.
 
5. 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.
 
6. The Java program completes sending of the mail, and writes the result of the mail sending process back to the data queue.
 
7. 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.
 
  
'''Installation'''
+
==Overview of the RPG Mail Engine framework==
  1. Issue the AS/400 command: CRTSAVF FILE(QGPL/RME)
+
# 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.
  2. FTP the file RME from your PC to the AS/400 in BINARY mode into the save file RME in library QGPL.
+
# Execute RME_run, which writes a record with a with a unique key to data queue DQRME.
  3. Issue the AS/400 command: CRTLIB RME
+
# The RPG program immediately goes to wait for a response on the same data queue for the same unique key.
  4. Issue the AS/400 command: RSTOBJ OBJ(*ALL) SAVLIB(RME) DEV(*SAVF) SAVF(QGPL/RME) MBROPT(*ALL) ALWOBJDIF(*ALL) RSTLIB(RME)       
+
# The Java program RPGMailEngine.java is listening for new entries on data queue DQRME.
  5. Issue the AS/400 commands:
+
# 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.
      MKDIR '/java'
+
#:  If debugging is turned on, the Java program will also trickle statements into a file in the IFS during processing.
      MKDIR '/java/rme'
+
# The Java program completes sending of the mail, and writes the result of the mail sending process back to the data queue.
  6. FTP the following files to the AS/400 in binary mode to folder /java/rme/
+
# 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.
      activation-1.1.jar  
+
 
      mail-1.4.jar
+
==Installation==
      jt400.jar
+
# Issue the AS/400 command: CRTSAVF FILE(QGPL/RME)
      RPGMailEngine.jar  
+
# FTP the file RME from your PC to the AS/400 in BINARY mode into the save file RME in library QGPL.
  7. If not already created, create a file /QIBM/UserData/Java400/SystemDefault.properties, then edit it and add the two lines below.
+
# Issue the AS/400 command: CRTLIB RME
      7.1. QSH CMD('touch /qibm/userdata/java400/SystemDefault.properties')
+
# Issue the AS/400 command: RSTOBJ OBJ(*ALL) SAVLIB(RME) DEV(*SAVF) SAVF(QGPL/RME) MBROPT(*ALL) ALWOBJDIF(*ALL) RSTLIB(RME)       
      7.2. EDTF '/qibm/userdata/java400/SystemDefault.properties'
+
# Issue the AS/400 commands:
            java.version=1.4
+
#: MKDIR '/java'
            java.awt.headless=true
+
#: MKDIR '/java/rme'
  8. Issue the AS/400 command to start the Java portion that runs in QBATCH:
+
# FTP the following files to the AS/400 in binary mode to folder /java/rme/
      RMESTR DTALIB(RME) DQLIB(RME) DQNAM(DQRME) DQWAIT(-1) DBG(TRUE) DBGFLR('/java/rme/')
+
#* activation-1.1.jar  
  9. Add library RME to the library list.
+
#* mail-1.4.jar
10. Add a record to the configuration file with the following data : data queue library, data queue name, waiting period, ip address of SMTP server,
+
#* jt400.jar
11. Add a file to the '/java/rme/' directory, and ensure that it is the same name as found in the RMEMAILR program.
+
#* RPGMailEngine.jar  
12. CALL RMEMAILR to see the program in action.
+
# 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'
 +
##: java.version=1.4
 +
##: java.awt.headless=true
 +
# 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:''
+
==The components of RPG Mail Engine and how they work==
<br>
+
===Starting the Java process===
<br>
 
'''Starting the Java process'''
 
<br>
 
 
Calling the command below will in turn call CL program STRRMEC which submits a RUNJVA command in batch.
 
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/')
 
   RME/RMESTR DTALIB(RME) DQLIB(RME) DQNAM(DQRME) DQWAIT(-1) DBG(TRUE) DBGFLR('/java/rme/')
Line 62: Line 60:
 
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.
 
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'''
+
===Data Queue DQRME===
<br>
 
 
The following command creates the data queue :
 
The following command creates the data queue :
 
   CRTDTAQ    DTAQ(RME/DQRME) MAXLEN(32766) SEQ(*KEYED) KEYLEN(32) AUTORCL(*YES)
 
   CRTDTAQ    DTAQ(RME/DQRME) MAXLEN(32766) SEQ(*KEYED) KEYLEN(32) AUTORCL(*YES)
Line 72: Line 69:
 
*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.   
 
*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.   
  
'''PF RMEMAILPF'''
+
===PF RMEMAILPF===
 
  A          R MAILR                                               
 
  A          R MAILR                                               
 
                                                                  
 
                                                                  
Line 85: Line 82:
 
RMEMAILPF is used to hold data that will be needed to send the mail.
 
RMEMAILPF is used to hold data that will be needed to send the mail.
  
'''RPGMAILR - Sending Mail'''
+
===RPGMAILR - Sending Mail===
  
 
  uid = RME_newMail('admin@rme.hyphen.co.za':'gareth.uren@hyphen.co.za':
 
  uid = RME_newMail('admin@rme.hyphen.co.za':'gareth.uren@hyphen.co.za':
Line 95: Line 92:
 
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.
 
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'''
+
===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.
 
*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'''
+
====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.
 
* 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'''
+
====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.
 
*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'''
+
====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 data residing in the result set is extracted and used to as input to the sendMail function which will send the email.
  

Latest revision as of 17:53, 29 February 2008

right

Introduction

I have built the RPG Mail Engine based on the concept by Aaron Bartell's RPG Chart Engine [1]. 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

  1. 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.
  2. Execute RME_run, which writes a record with a with a unique key to data queue DQRME.
  3. The RPG program immediately goes to wait for a response on the same data queue for the same unique key.
  4. The Java program RPGMailEngine.java is listening for new entries on data queue DQRME.
  5. 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.
  6. The Java program completes sending of the mail, and writes the result of the mail sending process back to the data queue.
  7. 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.

Installation

  1. Issue the AS/400 command: CRTSAVF FILE(QGPL/RME)
  2. FTP the file RME from your PC to the AS/400 in BINARY mode into the save file RME in library QGPL.
  3. Issue the AS/400 command: CRTLIB RME
  4. Issue the AS/400 command: RSTOBJ OBJ(*ALL) SAVLIB(RME) DEV(*SAVF) SAVF(QGPL/RME) MBROPT(*ALL) ALWOBJDIF(*ALL) RSTLIB(RME)
  5. Issue the AS/400 commands:
    MKDIR '/java'
    MKDIR '/java/rme'
  6. FTP the following files to the AS/400 in binary mode to folder /java/rme/
    • activation-1.1.jar
    • mail-1.4.jar
    • jt400.jar
    • RPGMailEngine.jar
  7. If not already created, create a file /QIBM/UserData/Java400/SystemDefault.properties, then edit it and add the two lines below.
    1. QSH CMD('touch /qibm/userdata/java400/SystemDefault.properties')
    2. EDTF '/qibm/userdata/java400/SystemDefault.properties'
      java.version=1.4
      java.awt.headless=true
  8. 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/')
  9. Add library RME to the library list.
  10. Add a record to the configuration file with the following data : data queue library, data queue name, waiting period, ip address of SMTP server,
  11. Add a file to the '/java/rme/' directory, and ensure that it is the same name as found in the RMEMAILR program.
  12. 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.

PF RMEMAILPF

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('admin@rme.hyphen.co.za':'gareth.uren@hyphen.co.za':
                 '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.