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?
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.