We have encountered an error with an RPGLE program calling out to Java methods to perform credit card encryption and decryption. This problem was first seen in December 2011 but was treated as a one-off (a bad cc#). In the last 6 months we are seeing it more frequently, sometimes a couple times a week.
For some background on where this is happening, this is a single RPGLE program and a single line of code, one for encryption one for decryption that is failing at times. This single program is part of a ?never-ending? job that is ended normally minutes before midnight and restarted minutes after midnight ? in other words, the job runs all day. As a transaction requires encryption and decryption, this job performs that function. The number of occurrences of encryption and decryption calls within this job ranges anywhere between 10,000 times to 100,000 times a day depending on the time of year. I point all this out to ensure it is clear that this one RPGLE program, with only one call to each method and these calls succeed without error 99.99% of the time.
An example of the error we are receiving is:
Message ID . . . . . . : RNQ0301 Severity . . . . . . . : 99
Message type . . . . . : Inquiry
Date sent . . . . . . : 05/23/13 Time sent . . . . . . : 02:05:53
Message . . . . : Java exception received when calling Java method (C G D
F).
Cause . . . . . : RPG procedure CCR0032 in program CWMPPGM/CCR0032 received
Java exception "java.lang.IllegalArgumentException: Missing argument" when
calling method "decrypt" with signature "([B)[B" in class
"com.cwi.encryption.CCEncryptDecrypt".
Of course if it is the Encrypt that fails, the message will reflect this method instead of Decrypt. What this is telling me is that we are not passing the correct parameters to the method decrypt. The ?([B) [B? is expecting an array of bytes as an input and again as an output.
When I look at the valid signatures for this method using qsh cmd('javap -s com.cwi.encryption.CCEncrypt Decrypt'), I receive the following information (I included only those signatures I think are relevant ? could be wrong!):
Compiled from "CCEncryptDecrypt.java"
public class com.cwi.encryption.CCEncryptDecrypt extends java.lang.Object{
java.lang.String keySelector;
Signature: Ljava/lang/String;
public byte[] decrypt(byte[]);
Signature: ([B)[B
public byte[] encrypt(byte[]);
Signature: ([B)[B
Here is the definition of the java methods within the package being accessed.
public byte[] decrypt(byte[] encryptedCard) {
public byte[] encrypt(byte[] creditCard){
That is three locations telling me that the decrypt & encrypt methods are expecting an array of bytes on input and returning an array of bytes. So that brings me to the prototype, invocation and declarations in the RPGLE program.
Declarations
C *Entry PLIST
C Parm Company 3
C Parm Action 1
C Parm CCIn 16
C CCOut Parm CCOut 16
D EncDec S O Class(*JAVA:
D 'com.cwi.encryption.CCEncryptDecrypt'
D )
Method Prototypes
D decrypt PR 16A Varying
D extProc(*JAVA:
D 'com.cwi.encryption.CCEncryptDecrypt'
D :'decrypt')
D 16A varying const
D encrypt PR 16A varying
D ExtProc(*JAVA:
D 'com.cwi.encryption.CCEncryptDecrypt'
D :'encrypt')
D 16A const varying
Method Invocation
* Call Encode routine
C Action IFEQ 'E'
C Eval CCOut = Encrypt(EncDec:CCIn)
C Endif
* Call Decode routine
C Action IFEQ 'D'
C Eval CCOut = Decrypt(EncDec:CCIn)
C Endif
When I look at all this, it all looks correct to me. I don?t quite follow why the instance is being passed on the RPGLE call when it is not defined as being expected in the java, but I am guessing that is likely the convention for doing this type of call -> pass the instance of the class as the first parm? I have never prototyped and called Java methods so I am out of my league here but nothing jumps out as completely wrong. Nothing jumps out at me as to how either method could be called and be missing an argument, as the error message indicated.
Any assistance in pointing me in the right direction to finding and solving this mystery is very much appreciated. I can provide any additional code snippets, job logs or program dumps if there is a feel that these would be helpful. Thank you in advance.
For some background on where this is happening, this is a single RPGLE program and a single line of code, one for encryption one for decryption that is failing at times. This single program is part of a ?never-ending? job that is ended normally minutes before midnight and restarted minutes after midnight ? in other words, the job runs all day. As a transaction requires encryption and decryption, this job performs that function. The number of occurrences of encryption and decryption calls within this job ranges anywhere between 10,000 times to 100,000 times a day depending on the time of year. I point all this out to ensure it is clear that this one RPGLE program, with only one call to each method and these calls succeed without error 99.99% of the time.
An example of the error we are receiving is:
Message ID . . . . . . : RNQ0301 Severity . . . . . . . : 99
Message type . . . . . : Inquiry
Date sent . . . . . . : 05/23/13 Time sent . . . . . . : 02:05:53
Message . . . . : Java exception received when calling Java method (C G D
F).
Cause . . . . . : RPG procedure CCR0032 in program CWMPPGM/CCR0032 received
Java exception "java.lang.IllegalArgumentException: Missing argument" when
calling method "decrypt" with signature "([B)[B" in class
"com.cwi.encryption.CCEncryptDecrypt".
Of course if it is the Encrypt that fails, the message will reflect this method instead of Decrypt. What this is telling me is that we are not passing the correct parameters to the method decrypt. The ?([B) [B? is expecting an array of bytes as an input and again as an output.
When I look at the valid signatures for this method using qsh cmd('javap -s com.cwi.encryption.CCEncrypt Decrypt'), I receive the following information (I included only those signatures I think are relevant ? could be wrong!):
Compiled from "CCEncryptDecrypt.java"
public class com.cwi.encryption.CCEncryptDecrypt extends java.lang.Object{
java.lang.String keySelector;
Signature: Ljava/lang/String;
public byte[] decrypt(byte[]);
Signature: ([B)[B
public byte[] encrypt(byte[]);
Signature: ([B)[B
Here is the definition of the java methods within the package being accessed.
public byte[] decrypt(byte[] encryptedCard) {
public byte[] encrypt(byte[] creditCard){
That is three locations telling me that the decrypt & encrypt methods are expecting an array of bytes on input and returning an array of bytes. So that brings me to the prototype, invocation and declarations in the RPGLE program.
Declarations
C *Entry PLIST
C Parm Company 3
C Parm Action 1
C Parm CCIn 16
C CCOut Parm CCOut 16
D EncDec S O Class(*JAVA:
D 'com.cwi.encryption.CCEncryptDecrypt'
D )
Method Prototypes
D decrypt PR 16A Varying
D extProc(*JAVA:
D 'com.cwi.encryption.CCEncryptDecrypt'
D :'decrypt')
D 16A varying const
D encrypt PR 16A varying
D ExtProc(*JAVA:
D 'com.cwi.encryption.CCEncryptDecrypt'
D :'encrypt')
D 16A const varying
Method Invocation
* Call Encode routine
C Action IFEQ 'E'
C Eval CCOut = Encrypt(EncDec:CCIn)
C Endif
* Call Decode routine
C Action IFEQ 'D'
C Eval CCOut = Decrypt(EncDec:CCIn)
C Endif
When I look at all this, it all looks correct to me. I don?t quite follow why the instance is being passed on the RPGLE call when it is not defined as being expected in the java, but I am guessing that is likely the convention for doing this type of call -> pass the instance of the class as the first parm? I have never prototyped and called Java methods so I am out of my league here but nothing jumps out as completely wrong. Nothing jumps out at me as to how either method could be called and be missing an argument, as the error message indicated.
Any assistance in pointing me in the right direction to finding and solving this mystery is very much appreciated. I can provide any additional code snippets, job logs or program dumps if there is a feel that these would be helpful. Thank you in advance.
Comment