从 Java 调用 i 系列程序会产生无效输出
我正在使用 jtopen/jt400 工具包从 Java(实际上是 JRuby,但我在纯 Java 中看到了同样的问题)调用 IBM i-series r5v4(又名 AS/400)上的程序。这对于某些程序来说效果很好,而对于其他程序来说,输出字节包含全零,这是错误的,有时甚至是无效的(例如在 ZonedDecimal 的情况下)。没有消息附加到 ProgramCall、JobList 或 SYSOPR.MSGQ 上。有谁知道为什么会发生这种情况?
展示一些代码(我相信任何使用过该库的人都可以理解 Java 的 Ruby 渲染):
as400 = AS400.new(host, user, password)
call = ProgramCall.new(as400)
call.program = "/QSYS.LIB/LIBRARY_NAME.LIB/PROGRAM_NAME.PGM"
# Prepare converters
text1_converter = AS400Text.new(1)
text3_converter = AS400Text.new(3)
decimal92_converter = AS400ZonedDecimal.new(11, 2)
# Prepare parameters
call.parameter_list = []
# Input parameters
call.parameter_list << ProgramParameter.new(text1_converter.to_bytes('N'))
call.parameter_list << ProgramParameter.new(decimal92_converter.to_bytes(1500.25))
# Output parameters
call.parameter_list << ProgramParameter.new(text3_converter.byte_length)
call.parameter_list << ProgramParameter.new(decimal92_converter.byte_length)
# Execute the call
call.run
# Show the results
puts "Text3 output value: " + text3_converter.to_object(params[2].output_data).to_s
puts "Decimal92 output value: " + decimal92_converter.to_object(params[3].output_data).to_s
正如我所说,这对于某些程序来说效果很好,而对于其他程序来说,params[2]。 output_data
将是一个 [0, 0, 0] 的字节数组,这不是预期的结果。更糟糕的是, params[3].output_data 将为 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],这对于 ZonedDecimal 来说是无效的字节值.new(9, 2).有人可以帮我吗?
I'm using the jtopen/jt400 toolkit to call programs on an IBM i-series r5v4 (aka AS/400) from Java (actually: JRuby, but I've seen the same problem in pure Java). This works just fine for some programs, while for other programs, the output bytes contain all zeroes, which is just wrong and sometimes even invalid (for instance in case of a ZonedDecimal). There are no Messages attached to the ProgramCall, in the JobList or on the SYSOPR.MSGQ. Does anyone know why this happens?
To show some code (I'm sure anyone that has worked with the library can understand this Ruby rendering of the Java):
as400 = AS400.new(host, user, password)
call = ProgramCall.new(as400)
call.program = "/QSYS.LIB/LIBRARY_NAME.LIB/PROGRAM_NAME.PGM"
# Prepare converters
text1_converter = AS400Text.new(1)
text3_converter = AS400Text.new(3)
decimal92_converter = AS400ZonedDecimal.new(11, 2)
# Prepare parameters
call.parameter_list = []
# Input parameters
call.parameter_list << ProgramParameter.new(text1_converter.to_bytes('N'))
call.parameter_list << ProgramParameter.new(decimal92_converter.to_bytes(1500.25))
# Output parameters
call.parameter_list << ProgramParameter.new(text3_converter.byte_length)
call.parameter_list << ProgramParameter.new(decimal92_converter.byte_length)
# Execute the call
call.run
# Show the results
puts "Text3 output value: " + text3_converter.to_object(params[2].output_data).to_s
puts "Decimal92 output value: " + decimal92_converter.to_object(params[3].output_data).to_s
As I said, this works just fine for some programs, while for others, params[2].output_data
will be a byte array of [0, 0, 0], which is not the intended results. Even worse, params[3].output_data
will be [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], which are invalid byte values for a ZonedDecimal.new(9, 2). Can anyone help me out?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实证明,您必须始终在输出参数上设置有效的
input_data
,即使这些值未在任何地方使用。如果不这样做,它们将不会被初始化,并且将包含垃圾(但内存位置通常会包含零,就像我的情况一样)。如果程序随后没有显式设置输出值(这恰好是我选择输入参数的情况),则“垃圾输入等于垃圾输出”这一说法成立。当然,防御性编程建议程序员初始化这些值或确保在代码可以采用的每个路径中设置它们,这可以从一开始就防止此问题发生。然而,合同似乎总是在输出参数上设置值,所以我错误地使用了 API。
It turns out you must always set a valid
input_data
on the output parameters, even when the values are not used anywhere. If you don't, they will not be initialized and they will contain garbage (but often the memory locations will contain zeroes, as in my case). If the program subsequently doesn't explicitly set the output values, which happened to be the case for my choice of input parameters, then the dictum garbage in equals garbage out holds.Of course, defensive programming suggests that the programmer initializes such values or makes sure they are set in every path that can be taken through the code, which would have prevented this problem from occurring in the first place. However, it seems the contract is to always set values on the output parameters, so I was wrongly using the API.