ibm-midrangerpgjt400control-languagejtopen

IBM i RPG programs are referencing the wrong library after calling them using a JT400 connection pool


I have a Java application that calls CL programs, which then run several RPG programs on an IBM i system, using the JT400 library.

At first, i opened a new connection each time, like this and closed it when done:

new AS400(hostname, username, password);

However due to the amount of connections increasing, i recently started using a connection pool:

@Bean
public AS400ConnectionPool as400ConnectionPool() {
    String hostname = env.getProperty("AS400Hostname");
    String username = env.getProperty("AS400Username");
    String password = env.getProperty("AS400Password");

    AS400ConnectionPool as400ConnectionPool = new AS400ConnectionPool();
    as400ConnectionPool.setMaxConnections(128);

    try {
        // Preconnect 5 connections to the AS400.COMMAND service.
        as400ConnectionPool.fill(hostname, username, password, AS400.COMMAND, 5);
    } catch (ConnectionPoolException e) {
        log.error(e.getMessage());
        e.printStackTrace();
    }
    return as400ConnectionPool;
}

Each connection is now returned to the pool after use, instead of being closed.

Unfortunately, we started seeing the same jobs that have been running perfectly before, sometimes going into status MSGW on the IBM i. (message wait)

While analyzing the job log, i noticed the following type of errors at the end:

CPF4131 appeared during OPEN for a file

It seems to be happening when running jobs from 2 different libraries around the same time. The program usually has around 10 open connections to the IBM i concurrently and many different jobs may be running at the same time, most are from the same one library and only a few are in a different one. Running the same call at a later time then goes through without any issues.

The library in which i'm running the program calls, seems to be looking for files in the other library, that isn't referenced in this program.

e.g. the following CL call:

CALL PGM(ADDPRGXX/TESTCL)

Will eventually result in errors like this in a subsequent RPG call:

TESTRPG *INIT ADDPRGXX OPEN SOMEFILE CPF4131 Level check on file SOMEFILE in library ADDFILXS with member SOMEFILE.

&N Cause . . . . . : The RPG program TESTRPG in library ADDPRGXX received the message CPF4131 while doing an implicit OPEN to file SOMEFILE. See the job log for a complete description of message CPF4131. If the file has a device type of SPECIAL, there may be no message in the job log. &N Recovery . . . : Enter C to cancel, S to obtain a printout of system storage, D to obtain an RPG formatted printout of system storage, or F to obtain a full formatted printout of system storage. &N Possible choices for replying to message . . . . . . . . . . . . . . . : &B D -- Obtain RPG formatted printout of system storage. &B S -- Obtain printout of system storage. &B F -- Obtain full formatted printout of system storage. &B C -- Cancel.

The example SOMEFILE doesn't exist in ADDFILXS but only in ADDFILXX, ADDFILXS is never referenced in the program call.

The CL programs start by adding the necessary libraries and then calls an RPG e.g.:

ADDLIBLE LIB(ADDPRGXX)
MONMSG MSGID (CPF0000)
ADDLIBLE LIB(ADDFILXX)
MONMSG MSGID (CPF0000)
CALL TESTRPG

Does there need to be some reference to the library to use in the subsequent RPG calls? Alternatively should i be doing something else with the connection pool to prevent this?

I've now started using 2 separate pools for each library, which seems to be working. But would prefer to find the root cause and fix it.


Solution

  • I suspect there's more going on than you know (or you've over simplied your example)

    The example SOMEFILE doesn't exist in ADDFILXS but only in ADDFILXX

    But that can't be the case if you're getting

    CPF4131 Level check on file SOMEFILE in library ADDFILXS with member SOMEFILE

    It'd be a different message if SOMEFILE actually didn't exist.

    In any event, there's lots of gotchas trying to change "environments" by changing the library list in the middle of a job's lifetime. Since you've started using connection pools, the connection remains open on the IBM i side and thus the QZDASOINIT (or related jobs) aren't reset by the OS between uses.

    You don't mention rather or not you're using ILE or OPM programs. But each has it's own set of issues and things get worse if mixing them; OPM CL calling ILE RPG.

    The best solution is the one you've come up with, use separate pools for the different environments.

    Not only is it safer, but it will perform better also.