Setting JT400 to connect to IBM i (AS400) using po

2019-07-10 20:54发布

I'm trying to connect to IBM midrange (AS400) machine from my java program and then reset a user's password. Using Jt400.jar, I manage to do so. But the problem is, I need to set the port to specificly use port 23. I want it to follow tn5250 on how it connect to AS400. From the IBM website here, I knew I can do so by using as400.connectToPort(23).

What confuses me, when I add that method, I got a java.lang.RuntimeException: java.lang.NegativeArraySizeException. I did try to search what's causing this exception which lead me to here and more explanation here. This is my code:

public void executeSetPassword(final String userName, final GuardedString password)  {

    if ((userName != null) && (password != null)) {
        final String host = configuration.getHost();
        final String remoteUser = configuration.getRemoteUser();
        GuardedString passwd = configuration.getPassword();
        boolean isSuccessful;

        final AS400 as400 = new AS400();

        try {
            as400.setSystemName(host);
            as400.setUserId(remoteUser);

            passwd.access(new Accessor(){
                @Override
                public void access(char[] clearChars) {
                    try {
                        as400.setPassword(new String(clearChars));
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }});

            as400.setGuiAvailable(false);
            as400.connectToPort(23);

            final CommandCall cc = new CommandCall(as400);
            final StringBuilder command = new StringBuilder();
            password.access(new Accessor(){
                    @Override
                    public void access(char[] clearChars) {
                            command.append("CHGUSRPRF USRPRF(" + userName + ") PASSWORD(" + new String(clearChars) + ")");
                    }});
            try {
                isSuccessful = cc.run(command.toString());


                logger.info("command status is = " + isSuccessful);
                // getMessageList returns an array of AS400Message objects
                for(AS400Message msg : cc.getMessageList()){
                    logger.info(
                            "  msg: " + msg.getID() + ": " + msg.getText());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e){
            throw new RuntimeException(e);
        }
    }
}

This is the log file:

Thread Id: 1    Time: 2015-06-29 14:27:05.592   Class: com.mastersam.connectors.AS400.AS400ConnectorTests   Method: updateTest(AS400ConnectorTests.java:150)    Level: INFO Message: Running Update Test
Thread Id: 1    Time: 2015-06-29 14:27:05.705   Class: org.identityconnectors.framework.api.operations.UpdateApiOp  Method: update  Level: OK   Message: Enter: update(ObjectClass: __ACCOUNT__, Attribute: {Name=__UID__, Value=[fikrie1]}, [Attribute: {Name=__PASSWORD__, Value=[org.identityconnectors.common.security.GuardedString@408a7bb8]}], OperationOptions: {})
Thread Id: 1    Time: 2015-06-29 14:27:07.749   Class: org.identityconnectors.framework.api.operations.UpdateApiOp  Method: update  Level: OK   Message: Exception: 
java.lang.RuntimeException: java.lang.NegativeArraySizeException
at com.mastersam.connectors.AS400.AS400Connector.executeSetPassword(AS400Connector.java:261)
at com.mastersam.connectors.AS400.AS400Connector.update(AS400Connector.java:199)
at org.identityconnectors.framework.impl.api.local.operations.UpdateImpl.update(UpdateImpl.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.local.operations.ConnectorAPIOperationRunnerProxy.invoke(ConnectorAPIOperationRunnerProxy.java:97)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.local.operations.ThreadClassLoaderManagerProxy.invoke(ThreadClassLoaderManagerProxy.java:96)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.DelegatingTimeoutProxy.invoke(DelegatingTimeoutProxy.java:98)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.LoggingProxy.invoke(LoggingProxy.java:76)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at org.identityconnectors.framework.impl.api.AbstractConnectorFacade.update(AbstractConnectorFacade.java:176)
at com.mastersam.connectors.AS400.AS400ConnectorTests.updateTest(AS400ConnectorTests.java:156)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Caused by: java.lang.NegativeArraySizeException
at com.ibm.as400.access.AS400XChgRandSeedReplyDS.read(AS400XChgRandSeedReplyDS.java:58)
at com.ibm.as400.access.AS400ImplRemote.getConnection(AS400ImplRemote.java:823)
at com.ibm.as400.access.AS400ImplRemote.connectToPort(AS400ImplRemote.java:408)
at com.ibm.as400.access.AS400.connectToPort(AS400.java:1152)
at com.mastersam.connectors.AS400.AS400Connector.executeSetPassword(AS400Connector.java:239)
... 52 more
FAILED: updateTest
java.lang.RuntimeException: java.lang.NegativeArraySizeException
at com.mastersam.connectors.AS400.AS400Connector.executeSetPassword(AS400Connector.java:261)
at com.mastersam.connectors.AS400.AS400Connector.update(AS400Connector.java:199)
at org.identityconnectors.framework.impl.api.local.operations.UpdateImpl.update(UpdateImpl.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.local.operations.ConnectorAPIOperationRunnerProxy.invoke(ConnectorAPIOperationRunnerProxy.java:97)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.local.operations.ThreadClassLoaderManagerProxy.invoke(ThreadClassLoaderManagerProxy.java:96)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.DelegatingTimeoutProxy.invoke(DelegatingTimeoutProxy.java:98)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.identityconnectors.framework.impl.api.LoggingProxy.invoke(LoggingProxy.java:76)
at com.sun.proxy.$Proxy10.update(Unknown Source)
at org.identityconnectors.framework.impl.api.AbstractConnectorFacade.update(AbstractConnectorFacade.java:176)
at com.mastersam.connectors.AS400.AS400ConnectorTests.updateTest(AS400ConnectorTests.java:156)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Caused by: java.lang.NegativeArraySizeException
at com.ibm.as400.access.AS400XChgRandSeedReplyDS.read(AS400XChgRandSeedReplyDS.java:58)
at com.ibm.as400.access.AS400ImplRemote.getConnection(AS400ImplRemote.java:823)
at com.ibm.as400.access.AS400ImplRemote.connectToPort(AS400ImplRemote.java:408)
at com.ibm.as400.access.AS400.connectToPort(AS400.java:1152)
at com.mastersam.connectors.AS400.AS400Connector.executeSetPassword(AS400Connector.java:239)
... 52 more

So, why does adding one method from jt400 causes a NegativeArraySizeException?

While looking for alternative, I found more info on the JT400 method here, then tried to use as400.connectService(). From here, I assume the service that I should be using is COMMAND and SIGNON. This is part of my code after trying this method:

final AS400 as400 = new AS400();                
        try {

            as400.setSystemName(host);
            as400.setUserId(remoteUser);
            passwd.access(new Accessor(){
                @Override
                public void access(char[] clearChars) {
                    try {
                        as400.setPassword(new String(clearChars));
                    }catch (Exception e) {
                        e.printStackTrace();
                    }
                }});
            as400.setGuiAvailable(false);

            as400.connectService(7);      //I added this
            as400.setServicePort(7, 23);  //I added this
            as400.setServicePort(6, 23);  //I added this
            logger.info("port is = " + as400.getServicePort(7));
            final CommandCall cc = new CommandCall(as400);
            final StringBuilder command = new StringBuilder();
            password.access(new Accessor(){
                    @Override
                    public void access(char[] clearChars) {
                            command.append("CHGUSRPRF USRPRF(" + userName + ") PASSWORD(" + new String(clearChars) + ")");
                    }});
            try {

                isSuccessful = cc.run(command.toString());
                as400.setServicePort(2, 23); //I added this
                logger.info("port is = " + as400.getServicePort(2));
}

According to the log, the port is 23. But when I double check using Wireshark apps, the port that it use to connect to AS400 is not 23. Please guide me if I'm doing a mistake anywhere.

Other thing that I have tried,

  1. Swap line between as400.connectService() and as400.setServicePort()

    • Causes the same error as the previous one : java.lang.NegativeArraySizeException
  2. Check either port 23 is available to use or not. Use tn5250 to connect to AS400. The connection is ok.

  3. Set as400.connectToPort() to use other port.

    • Causes the same error like using port 23.

1条回答
姐就是有狂的资本
2楼-- · 2019-07-10 21:50

connectToPort() returns a Socket object, not an AS400 object. Therefore, you can't use any AS400 classes to interact with that returned Socket object.

You might consider changePassword() instead of trying to stuff commands down the telnet port.

changePassword

public void changePassword(java.lang.String oldPassword,
                  java.lang.String newPassword)
                    throws AS400SecurityException,
                           java.io.IOException

Changes the user profile password. The system name and user profile name need to be set prior to calling this method.

Parameters:
    oldPassword - The old user profile password.
    newPassword - The new user profile password.
Throws:
    AS400SecurityException - If a security or authority error occurs.
    java.io.IOException - If an error occurs while communicating with the system.
查看更多
登录 后发表回答