将 JT400 设置为使用端口 23 连接到 IBM i (AS400)

Setting JT400 to connect to IBM i (AS400) using port 23

我正在尝试从我的 java 程序连接到 IBM 中端 (AS400) 机器,然后重置用户密码。使用 Jt400.jar,我设法做到了。但问题是,我需要将端口设置为专门使用端口 23。我希望它在如何连接到 AS400 时遵循 tn5250。从 IBM 网站 here,我知道我可以使用 as400.connectToPort(23).

让我感到困惑的是,当我添加该方法时,我得到了 java.lang.RuntimeException: java.lang.NegativeArraySizeException。我确实尝试搜索导致此异常的原因导致我 here and more explanation here。这是我的代码:

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);
        }
    }
}

这是日志文件:

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

那么,为什么从 jt400 添加一个方法会导致 NegativeArraySizeException?

在寻找替代方案时,我找到了有关 JT400 方法的更多信息 here,然后尝试使用 as400.connectService()。从这里,我假设我应该使用的服务是COMMANDSIGNON。这是尝试此方法后我的代码的一部分:

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));
}

根据日志,端口是23。但是当我使用Wireshark应用程序仔细检查时,它用于连接AS400的端口不是23。如果我在任何地方做错了,请指导我。

我试过的其他东西,

  1. as400.connectService()as400.setServicePort()

    之间的换行
    • 导致与前一个相同的错误:java.lang.NegativeArraySizeException
  2. 检查端口 23 是否可用。使用 tn5250 连接到 AS400。连接正常

  3. 设置 as400.connectToPort() 使用其他端口。

    • 导致与使用端口 23 相同的错误。

connectToPort() returns 一个 Socket 对象,而不是 AS400 对象。因此,您不能使用任何 AS400 类 与返回的 Socket 对象进行交互。

您可以考虑使用 changePassword() 而不是尝试在 telnet 端口下填充命令。

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.