Ruby --> XMLService --> RPG using data structure

Issue #6 new
Rex Merchant created an issue

Many, many of our programs are the "get record" variety, but the getting involves several tables and some calculations, so it is not a straight database read. We commonly use data structures to pass the output parameters back to the calling program. I THINK I understand the differences among input, response and returndata but I am stuck trying to use a data structure in the returndata context.

This code works, and the thing it returns is the XML blob shown below.

# Get brand info

pgm = XMLService::I_PGM.new('SOSBS27', '*LIBL') <<
    XMLService::I_String.new('returnCode', 7, ' ') <<                        # PARM0
    XMLService::I_PackedDecimal.new('brandCode', 5, 0, 0) <<                 # PARM1
    XMLService::I_DS.new('brandInfo', 1, [                                   # PARM2
      XMLService::I_PackedDecimal.new('brandCodeDummy', 5, 0, 0),
      XMLService::I_String.new('brandShortName', 8, ' '),
      XMLService::I_String.new('brandName', 30, ' '),
      XMLService::I_String.new('brandStatus', 1, ' '),
      XMLService::I_PackedDecimal.new('brandDateDiscontinue', 7, 0, 0),
      XMLService::I_String.new('brandDebitGL', 15, ' '),
      XMLService::I_String.new('brandCreditGL', 15, ' '),
      XMLService::I_String.new('brandPrefix', 3, ' ')
    ]) <<
    XMLService::I_String.new('brandRefCode', 12, ' ') <<                     # PARM3
    XMLService::I_String.new('recordFound', 1, ' ')                          # PARM4


# Set input parameters

pgm.input.PARM0.returnCode = ' '
pgm.input.PARM1.brandCode = brandCode

# call program

pgm.xmlservice

return pgm.response.brandInfo

Output:

Brand info: [#<XMLService::I_DS:0x211d4ba8 @xml_dim="1", @xml_dou=nil, @xml_var="brandInfo", @xml_elem=[#<XMLService::I_PackedDecimal:0x211bf708 @xml_type="p", @xml_size=5, @xml_prec=0, @xml_vary=nil, @xml_var="brandCodeDummy", @xml_enddo=nil, @xml_user_accessor="brandCodeDummy", @xml_data=0.0, @brandCodeDummy=0.0>, #<XMLService::I_Char:0x211be72c @xml_var="brandShortName", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=8, @xml_prec=0, @xml_data="A&B IND", @xml_user_accessor="brandShortName", @brandShortName="A&B IND">, #<XMLService::I_Char:0x211bd890 @xml_var="brandName", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=30, @xml_prec=0, @xml_data="A & B INDUSTRIES INC.", @xml_user_accessor="brandName", @brandName="A & B INDUSTRIES INC.">, #<XMLService::I_Char:0x211bc88c @xml_var="brandStatus", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=1, @xml_prec=0, @xml_data="A", @xml_user_accessor="brandStatus", @brandStatus="A">, #<XMLService::I_PackedDecimal:0x211a3698 @xml_type="p", @xml_size=7, @xml_prec=0, @xml_vary=nil, @xml_var="brandDateDiscontinue", @xml_enddo=nil, @xml_user_accessor="brandDateDiscontinue", @xml_data=0.0, @brandDateDiscontinue=0.0>, #<XMLService::I_Char:0x211a275c @xml_var="brandDebitGL", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=15, @xml_prec=0, @xml_data="", @xml_user_accessor="brandDebitGL", @brandDebitGL="">, #<XMLService::I_Char:0x211a1348 @xml_var="brandCreditGL", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=15, @xml_prec=0, @xml_data="", @xml_user_accessor="brandCreditGL", @brandCreditGL="">, #<XMLService::I_Char:0x2119a3e0 @xml_var="brandPrefix", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=3, @xml_prec=0, @xml_data="A/B", @xml_user_accessor="brandPrefix", @brandPrefix="A/B">], @xml_user_accessor="brandPrefix", @brandCodeDummy=#<XMLService::I_PackedDecimal:0x211bf708 @xml_type="p", @xml_size=5, @xml_prec=0, @xml_vary=nil, @xml_var="brandCodeDummy", @xml_enddo=nil, @xml_user_accessor="brandCodeDummy", @xml_data=0.0, @brandCodeDummy=0.0>, @brandShortName=#<XMLService::I_Char:0x211be72c @xml_var="brandShortName", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=8, @xml_prec=0, @xml_data="A&B IND", @xml_user_accessor="brandShortName", @brandShortName="A&B IND">, @brandName=#<XMLService::I_Char:0x211bd890 @xml_var="brandName", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=30, @xml_prec=0, @xml_data="A & B INDUSTRIES INC.", @xml_user_accessor="brandName", @brandName="A & B INDUSTRIES INC.">, @brandStatus=#<XMLService::I_Char:0x211bc88c @xml_var="brandStatus", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=1, @xml_prec=0, @xml_data="A", @xml_user_accessor="brandStatus", @brandStatus="A">, @brandDateDiscontinue=#<XMLService::I_PackedDecimal:0x211a3698 @xml_type="p", @xml_size=7, @xml_prec=0, @xml_vary=nil, @xml_var="brandDateDiscontinue", @xml_enddo=nil, @xml_user_accessor="brandDateDiscontinue", @xml_data=0.0, @brandDateDiscontinue=0.0>, @brandDebitGL=#<XMLService::I_Char:0x211a275c @xml_var="brandDebitGL", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=15, @xml_prec=0, @xml_data="", @xml_user_accessor="brandDebitGL", @brandDebitGL="">, @brandCreditGL=#<XMLService::I_Char:0x211a1348 @xml_var="brandCreditGL", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=15, @xml_prec=0, @xml_data="", @xml_user_accessor="brandCreditGL", @brandCreditGL="">, @brandPrefix=#<XMLService::I_Char:0x2119a3e0 @xml_var="brandPrefix", @xml_vary=nil, @xml_enddo=nil, @xml_type="a", @xml_size=3, @xml_prec=0, @xml_data="A/B", @xml_user_accessor="brandPrefix", @brandPrefix="A/B">>]

Needless to say, this output is the data structure PARM2. But I don't know how to access the content of individual fields within the data structure, and I suspect that I should be using "returndata" instead of "response." However, I am not able to read the examples on yips and replicate them for my own use.

Comments (3)

  1. Aaron Bartell

    Hi James,

    I've put together a small tutorial to show how this works.

    #Create RPG Program File: /home/aaron/pgm1.rpgle

           dcl-pr pgm1 extpgm;
             char1 char(1);
             dec1 packed(7:4);
           end-pr;
           dcl-pi pgm1;
             char1 char(1);
             dec1 packed(7:4);
           end-pi;
    
           char1 = 'C';
           dec1 = 321.1234;
           *inlr = *on;
           return;
    

    #Compile RPG

    CRTBNDRPG PGM(MYLIB/PGM1) SRCSTMF('/home/aaron/pgm1.rpgle')
    

    #Run Test I use the Rails Console to run tests until I get something working. Start the Rails console:

    $ rails console
    

    Paste the following into the console. Note you need to have the xmlservice Gem specified in your Gemfile file (which it most likely is already).

    pgm = XMLService::I_PGM.new('PGM1', 'MYLIB') <<
          XMLService::I_String.new('char1', 1, ' ') << 
          XMLService::I_PackedDecimal.new('dec1', 7, 4, 0) 
    pgm.call
    pgm.xmlservice_error
    pgm.dump_error
    pgm.response.char1
    

    At this point you will receive the same output as you had before. The call to pgm.response.char1 returned an object with many properties. To learn what accessors exist we can do the following:

    pgm.response.char1.methods.sort
    

    ...which outputs the following...

    => [:!, :!=, :!~, :<=>, :==, :===, :=~, :__id__, :__send__, :`, :acts_like?, :add_user_accessor, :as_json, :blank?, :breakpoint, :capture, :char1, :char1=, :check_enddo, :check_nil, :check_number, :check_prec, :check_size, :check_type, :check_var, :check_vary, :class, :class_eval, :clone, :dclone, :debugger, :deep_dup, :define_singleton_method, :display, :dup, :dupFromUserValue, :dupToUserValue, :duplicable?, :enable_warnings, :enum_for, :eql?, :equal?, :extend, :freeze, :frozen?, :gem, :hash, :html_safe?, :in?, :initialize_doc, :initialize_type2, :initialize_type3, :initialize_type4, :initialize_type5, :initialize_type6, :initialize_type7, :initialize_value, :initialize_zero, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_values, :instance_variable_defined?, :instance_variable_forward_get, :instance_variable_forward_set, :instance_variable_get, :instance_variable_names, :instance_variable_set, :instance_variables, :is_a?, :is_haml?, :kind_of?, :load, :load_dependency, :method, :methods, :nil?, :object_id, :parse_diag_attr, :parse_output_attr, :parse_return_attr, :precision, :presence, :presence_in, :present?, :pretty_inspect, :pretty_print, :pretty_print_cycle, :pretty_print_inspect, :pretty_print_instance_variables, :private_methods, :protected_methods, :psych_to_yaml, :public_method, :public_methods, :public_send, :quietly, :remove_instance_variable, :remove_user_accessor, :require, :require_dependency, :require_or_load, :respond_to?, :send, :setValue, :shortCut, :silence, :silence_stderr, :silence_stream, :silence_warnings, :singleton_class, :singleton_method, :singleton_methods, :size, :suppress, :suppress_warnings, :taint, :tainted?, :tap, :to_enum, :to_f, :to_i, :to_json, :to_json_with_active_support_encoder, :to_json_without_active_support_encoder, :to_param, :to_query, :to_s, :to_xml, :to_yaml, :to_yaml_properties, :trust, :try, :try!, :type, :typeParse, :unloadable, :untaint, :untrust, :untrusted?, :value, :var, :vary, :with_options, :with_warnings, :xml_user_accessor, :xml_user_accessor=]
    

    At this point you'd start invoking the various available methods to learn which one is holding the value returned from RPG. Cutting to the chase, it is the var method.

    pgm.response.char1.var
    

    #tl;dr Try this:

    return pgm.response.brandInfo.var
    
  2. Log in to comment