1

The main purpose of the java program below is to use the AS400FileRecordDescription class from the jtopen (version 9.6) to retrieve the record format of a physical file on iseries. It does that by calling the retrieveRecordFormat() method in this class.

This program works fine if the connection is an unsecured connection (the connection url does not contain the secure=true paramater). But under a secured connection (the connection url contains the secure=true paramater), it failed with this error: "javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake". Any idea what I'm doing wrong here?

import java.sql.Connection;
import java.sql.DriverManager;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400FileRecordDescription;
import com.ibm.as400.access.AS400JDBCConnection;
import com.ibm.as400.access.RecordFormat;

public class TestIseriesSecureConnection {

    public static void main(String[] args) {

        Connection conn = null;
        AS400 system = null;
        try {
            // get standard jdbc connection
            Class.forName("com.ibm.as400.access.AS400JDBCDriver");
            // notice the secure=true parameter, if that is removed, the program works fine.
            conn = DriverManager.getConnection("jdbc:as400://myiseries;secure=true;naming=system;errors=full;prompt=false;libraries=*LIBL;timeFormat=iso;dateFormat=iso;dateSeparator=-", "myuser", "mypassword");

            // cast connection into AS400 jdbc connection class to get the AS400 object
            AS400JDBCConnection as400Conn = (AS400JDBCConnection) conn;
            system = as400Conn.getSystem();

            // get the record format of a file on iseries
            RecordFormat recordFormats[] = null;
            AS400FileRecordDescription fileRecordDescription = new AS400FileRecordDescription(system, "/QSYS.LIB/%LIBL%.LIB/MYFILE.FILE");

            // This is where it error out if the connection is a secure connection 
            recordFormats = fileRecordDescription.retrieveRecordFormat();

            for (int myIx = 0; myIx < recordFormats.length; myIx++) {
                System.out.println(recordFormats[myIx].toString());
            }
            conn.close();
        }
        catch(Exception ex) {
            ex.printStackTrace();
        }
        finally {
            try {
                if (conn != null) {
                    conn.close();
                }
            }
            catch (Exception ex) {
                ex.printStackTrace();
            }
        }

        System.exit(0);
    }

}
HockChai Lim
  • 1,675
  • 2
  • 20
  • 30
  • We opened a PMR with IBM and they said the reason it is not working is because I can't use a AS400 object using a secured connection. For secure connection, I need to use SecureAS400 object, which I think is not a very robust design for 2 reasons. 1) There is no method in AS400JDBCConnection that allows me to get a SecureAS400 from it. 2) Most J2EE developers are likely to use container managed connection pool to manage connections. This type of connection typically uses data source config file to config connection url, which allow to switch from secure and non-secure at will. – HockChai Lim Oct 19 '18 at 18:46
  • So, unless I can somehow get a SecureAS400 object from the AS400JDBCConnection object, I'll have to implement my own connection pooling for the SecureAS400 objects just to switch to a secure connection. Disappointing because this is probably the only system that requires me to make code changes for switching to secured connection. I can understand the need to perform code change if this is a low level c socket api type programming, but not for this. AS400 object should have been coded to handle it correctly base of type of connection that it has. Sorry for the ranting. I feel better now :) – HockChai Lim Oct 19 '18 at 18:57
  • I think it's worth making the point that such classes in jt400 are not JDBC and thus the connection they use is not a JDBC one (and thus, or certainly in my experience, not susceptible to normal connection pooling). These record format classes are talking to the database, but in a native way not a SQL way, hence their lack of relationship to JDBC. I don't think you should be looking to AS400JDBCConnection at all for this specific requirement. Sorry, I should have spotted this before. – MandyShaw Oct 20 '18 at 08:36
  • 1
    @MandyShaw, I understand. But if a Connection object can handle both the secured and the unsecured connection seamlessly, I don't see why the AS400 class can't be designed to do the same. My guess is that SecureAS400 is an afterthought, and the JTOpen developer is not willing to spend time to change the AS400 class to handle both types of connection. – HockChai Lim Oct 22 '18 at 14:33

2 Answers2

0

What version of IBM i OS?

What version of Java?

Not uncommon to see on IBM i 7.1 since it doesn't support the latest versions of TLS and ciphers.

Charles
  • 21,637
  • 1
  • 20
  • 44
  • Our system is on V7R3. I'm running the program from my pc, which is using java 8. – HockChai Lim Oct 17 '18 at 14:31
  • Just to clarify, the problem appears to be happening on AS400FileRecordDescription class or its retrieveRecordFormat method only. The secured connection is working fine if I do the standard jdbc stuffs, like createStatement and executeQuery. – HockChai Lim Oct 17 '18 at 15:29
  • I'm suspicious about this, sounds like a bug to me. The 'record format' classes are not used very much in my experience (which I don't understand - they're great). Pragmatically, could you connect without SSL just to pick up the record format? – MandyShaw Oct 17 '18 at 17:56
  • @MandyShaw That stand alone java program is just a program that I created to demo the problem. The actual code is in a J2EE web app that runs on a TOMEE server. It uses connection pooling. While it is possible to create a different unsecured data source with different pooling and use it where that method is used, it is not ideal. I have created a PMR with IBM to see if there is a better work around. – HockChai Lim Oct 18 '18 at 14:53
0

After a bit more back and forth with IBM support, we finally figured out that the problem was caused by the retrieveRecordFormat method is using the DDM/DRDA service to serve the request. We've ssl cert install on several diff host servers but not on the DDM/DRDA. That explained why other type of requests are working fine under ssl. So, once I've the cert installed on the DDM/DRDA host server, the program works fine even with the plain old AS400 object.

HockChai Lim
  • 1,675
  • 2
  • 20
  • 30