Tony XML Service Gem Samples

(click to open)

Quick Page Table of Contents

Scanning…

Ruby Toolkit Tony …

Goto Main Page
Goto Documents
Goto Ruby Page
Goto Tony Work Ruby Page

xmlservice gem is being developed for Ruby/Rails to IBM i. This gem will allow both local IBM i (PASE) and/or remote LUW access to IBM XMLSERVICE using either DB2 connection (xmlservice iPlugxxx) or a REST connection (Apache CGI xmlcgi.pgm).

Warning - This gem is in early testing, so APIs may change that will impact your scripts.

Today:
    zzcall = XMLService::I_PGM.new("ZZCALL",$toolkit_test_lib,{'error'=>'fast'}) 
    zzcall << XMLService::I_a.new('inchara',1,'s')
    zzcall << XMLService::I_a.new('incharb',1,'r') 
    zzcall << XMLService::I_p.new('indec1',7,4,55.1111) 
    zzcall << XMLService::I_p.new('indec2',12,2,333.22)
    zzcall << XMLService::I_DS.new('inds1',1,
                                   [ 
                                    XMLService::I_a.new('dschara',1,'t'),
                                    XMLService::I_a.new('dscharb',1,'f'),
                                    XMLService::I_p.new('dsdec1',7,4,77.6666),
                                    XMLService::I_p.new('dsdec2',12,2,88888.77)
                                   ])

POSSIBLE: design chat may affect create/new syntax in favor of DSL method.
@pgm =
   input_parms(inchara=>a1,inchara=>a2,[dschara=>t1, ..],...) do
    char :inchara,  1
    char :incharb, 1
    dec :indec1, 7.4
    dec :indec2, 12.2
    struct :inds1,1 do
      char :dschara, 1
      char :dscharb, 1
      dec :indec1, 7.4
      dec :indec2, 12.2
      struct :inds2,1 do
        dec :indec1, 7.4
        dec :indec2, 12.2
      end
    end
  end

This page reflects changes to xmlservice 1.2 (incompatible with 1.0)
xmlservice 1.2 change has removed all output prefixes, thereby output data is longer accessible via xml_ assessors. The replacement technique allows data get/set assessors via root keywords input, response, returndata.

#     D ARRAYMAX        c                   const(999)
#     D dcRec_t         ds                  qualified based(Template)
#     D  dcMyName                     10A
#     D  dcMyJob                    4096A
#     D  dcMyRank                     10i 0
#     D  dcMyPay                      12p 2
#     P zzarray         B                   export
#     D zzarray         PI                  likeds(dcRec_t) dim(ARRAYMAX)
#     D  myName                       10A
#     D  myMax                        10i 0
#     D  myCount                      10i 0

# root:
zzarray = XMLService::I_SRVPGM.new(..)

# root.input:
zzarray.input.myMax = count

# dump_inspect before call includes only root keyword input.
puts zzarray.dump_inspect

zzarray.call # call IBM i

# dump_inspect after call includes root keywords input, response, returndata.
puts zzarray.dump_inspect

# root.output:
puts "count records returned...#{zzarray.response.myCount}"

# root.returndata:
i = 0
zzarray.returndata.dcRec_t.each do |dcRec_t|
  i += 1
  puts "dcRec_t[#{i}]"
  puts "  Name...#{dcRec_t.dcMyName}"
  puts "  Job....#{dcRec_t.dcMyJob}"
  puts "  Rank...#{dcRec_t.dcMyRank}"
  puts "  Pay....#{dcRec_t.dcMyPay}"
end

xmlservice gem connection

xmlservice connect (no yaml file)

  • xmlservice connection data
    url = "http://myibmi/xmlcgi.pgm"        # see XMLSERVICE REST Apache config
    database = "*LOCAL"                     # see wrkrdbdire
    user = "MYUID"                          # IBM i profile
    pwd = "MYPWD"                           # IBM i profile
    ctl = "*here *cdata"                    # see XMLSERVICE reserved words  
    ipc = "*none"                           # see XMLSERVICE public vs. private connection
    size = "1000000"                        # XMLSERVICE size output expected (ibm_db or rest)
    head = "<?xml version='1.0'?>"          # XMLSERVICE XML header return output
    
    • xmlservice gem connection using ActiveRecord
          ActiveXMLService::Base.establish_connection(
             :adapter => 'ibm_db',
             :connection => 'ActiveRecord',
             :database => database,
             :username => user,
             :password => pwd,
             :ctl => ctl,
             :ipc => ipc,
             :size => size,
             :head => head)
      
    • xmlservice gem connection using REST (xmlcgi.pgm)
          ActiveXMLService::Base.establish_connection(
             :connection => url,
             :database => database,
             :username => user,
             :username => user,
             :password => pwd,
             :ctl => ctl,
             :ipc => ipc,
             :size => size,
             :head => head)
      
      

xmlservice connection (using yaml files)

require 'xmlservice'
# sql  - db2 transport no libl 
# sys  - db2 transport with libl
# rest - rest transport 
$test_env = ENV['TEST_ENV']
$test_yaml = ENV['TEST_YAML']

if $test_yaml == nil
  $test_yaml = "../test_authorization/xmlservice.yml"
end
if $test_env == nil
  $test_env = "restpublic"
end

ActiveXMLService::Base.establish_connection(
  :test_yaml => $test_yaml,
  :test_env  => $test_env
)

$toolkit_test_lib = ActiveXMLService::Base.configurations[:test_i_lib];

/path/xmlservice.yml

To skip encrypted passwords simply comment out pwd_yaml: and use plain text password:

# ---------------------------------
# Profile DB2  
db2profile: &db2profile
  username: DB2
  password: MYPASS
  # pwd_yaml: ../test_authorization/password.yml

/path/password.yml (encrypted password)

  • xmlservice gem (interchangeable with ibm_db)
    • pwd_key = ActiveXMLService::Base.generate_key()
    • pwd_enc = ActiveXMLService::Base.generate_password(password,pwd_key)
  • ibm_db gem (interchangeable with xmlservice)
    • pwd_key = ActiveRecord::Base.ibm_db_generate_key()
    • pwd_enc = ActiveRecord::Base.ibm_db_generate_password(password,pwd_key)
# ---------------------------------
# Profile DB2  
db2profile: &db2profile
  username: DB2
  pwd_yaml: ../test_authorization/password.yml
# ---------------------------------
# REST client to IBM i (V6R1)
v6r1rest: &v6r1rest
  connection: "http://174.79.32.155/cgi-bin/xmlcgi.pgm"
  database: "*LOCAL"
# ---------------------------------
# DB2 client to IBM i (V7R1)
v7r1sql: &v7r1sql
  connection: "ActiveRecord"
  adapter: ibm_db
  database: "*LOCAL"
# ---------------------------------
# DB2 client to IBM i (V7R1)
v7r1sys: &v7r1sys
  connection: "ActiveRecord"
  ibm_i_naming: "system"
  ibm_i_libl: "QTEMP DB2"
  ibm_i_curlib: "DB2"
  adapter: ibm_db
  database: "*LOCAL"
# ---------------------------------
# xmlservice state full private connection (yes XTOOLKIT job)
xmlserviceprivate: &xmlserviceprivate
  install: XMLSERVICE
  ctl: "*sbmjob"
  ipc: /tmp/ruby042
  size: 15000000
  head: "<?xml version='1.0'?>"
  test_i_lib: XMLSERVICE
# ---------------------------------
# xmlservice stateless public connection (no XTOOLKIT job)
xmlservicepublic: &xmlservicepublic
  install: XMLSERVICE
  ctl: "*here"
  ipc: "/none"
  size: 15000000
  head: "<?xml version='1.0'?>"
  test_i_lib: XMLSERVICE
# ---------------------------------
# xmlservice state full private connection (yes XTOOLKIT job)
sqlprivate:
  <<: *v7r1sql
  <<: *db2profile
  <<: *xmlserviceprivate
sysprivate:
  <<: *v7r1sys
  <<: *db2profile
  <<: *xmlserviceprivate
restprivate:
  <<: *v6r1rest
  <<: *db2profile
  <<: *xmlserviceprivate
# ---------------------------------
# xmlservice stateless public connection (no XTOOLKIT job)
sqlpublic:
  <<: *v7r1sql
  <<: *db2profile
  <<: *xmlservicepublic
syspublic:
  <<: *v7r1sys
  <<: *db2profile
  <<: *xmlservicepublic
restpublic:
  <<: *v6r1rest
  <<: *db2profile
  <<: *xmlservicepublic

/path/password.yml

DB2: 
  pwd_enc: "YiYNfodSh5MGZVX7TXktEPSrnVlrAPjoyzzn48SdC/k=%0A"
FRED:
  pwd_enc: xSwNlLR8nZ7ar5C3Q+aStSR4B7AhiX/jMsgsVFcflnE=%0A
SALLY:
  pwd_enc: 5+legQzEhgPZ01fwBtZrdljVEtvYfcPGOlPORTnx3Dw=%0A

/path/key.yml

pwd_key: "dHKTuwxppje7zyl0cMRRQA==%0ADwtA7"

xmlservice gem samples

Here a few examples using xmlservice taken from zip directory test/.

Sample PGM call

#     D ARRAYMAX        c                   const(999)
#     D dcRec_t         ds                  qualified based(Template)
#     D  dcMyName                     10A
#     D  dcMyJob                    4096A
#     D  dcMyRank                     10i 0
#     D  dcMyPay                      12p 2
#      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#      * zzarray: check return array aggregate 
#      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#     P zzarray         B                   export
#     D zzarray         PI                  likeds(dcRec_t) dim(ARRAYMAX)
#     D  myName                       10A
#     D  myMax                        10i 0
#     D  myCount                      10i 0
    count = 5
    zzwho = 'Ranger'
    zzarray = XMLService::I_SRVPGM.new("ZZSRV","ZZARRAY",$toolkit_test_lib,{'error'=>'on'})
    zzarray << XMLService::I_Char.new('myName',10,'FlinRock')
    zzarray << XMLService::I_Int32.new('myMax',20)
    zzarray << XMLService::I_Int32.new('myCount',0,'mycount')
    zzarray.setReturn("aggregate", 
            XMLService::I_DS.new("dcRec_t",999,'mycount',
            [ 
              XMLService::I_Char.new('dcMyName',10,'na'),
              XMLService::I_Char.new('dcMyJob',4096,'na'),
              XMLService::I_Int32.new('dcMyRank',0),
              XMLService::I_PackedDecimal.new('dcMyPay',12,2,0.0)
            ]))


    # set input variables for call
    zzarray.input.PARM0.myName = 'Skippy'
    zzarray.input.PARM1.myMax  = 9
    zzarray.input.PARM2.myCount= 0
    puts "\n+++++++++ input normal ++++++++++++++++"
    puts zzarray.to_xml


    # set input variables for call
    zzarray.input.myName = zzwho
    zzarray.input.myMax  = count
    zzarray.input.myCount= 0
    puts "\n+++++++++ input fewer ++++++++++++++++"
    puts zzarray.to_xml

    # call IBM i
    zzarray.call

    # puts zzarray.inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts zzarray.dump_inspect


    # xmlservice error occurred?
    rc = zzarray.xmlservice_error
    if rc
      puts zzcall.dump_error
    end

    # output xml
    puts "\n+++++++++ output xml ++++++++++++++++"
    puts zzarray.out_xml


    # output
    puts "\n+++++++++ output ++++++++++++++++"
    puts "#{zzarray.name}.#{zzarray.func}:\n"
    puts " myName....#{zzarray.response.myName}\n"
    puts " myMax.....#{zzarray.response.myMax}\n"
    puts " myCount...#{zzarray.response.myCount}\n"
    i = 0
    zzarray.returndata.dcRec_t.each do |dcRec_t|
      i += 1
      puts "dcRec_t[#{i}]"
      puts "  Name...#{dcRec_t.dcMyName}"
      puts "  Job....#{dcRec_t.dcMyJob}"
      puts "  Rank...#{dcRec_t.dcMyRank}"
      puts "  Pay....#{dcRec_t.dcMyPay}"
    end

    # output
    puts "\n+++++++++ output long ++++++++++++++++"
    puts "#{zzarray.name}.#{zzarray.func}:\n"
    puts " myName....#{zzarray.response.PARM0.myName}\n"
    puts " myMax.....#{zzarray.response.PARM1.myMax}\n"
    puts " myCount...#{zzarray.response.PARM2.myCount}\n"
    i = 0
    zzarray.returndata.aggregate.dcRec_t.each do |dcRec_t|
      i += 1
      puts "dcRec_t[#{i}]"
      puts "  Name...#{dcRec_t.dcMyName}"
      puts "  Job....#{dcRec_t.dcMyJob}"
      puts "  Rank...#{dcRec_t.dcMyRank}"
      puts "  Pay....#{dcRec_t.dcMyPay}"
    end

Sample System API (Data Queue)

    # ***************************************
    # * CMD - Recreate Data Queue (DLTDTAQ, CRTDTAQ)
    # ***************************************
    dltdatq = XMLService::I_CMD.new("DLTDTAQ DTAQ(#{$toolkit_test_lib}/MYDATAQ)")
    # call IBM i
    dltdatq.xmlservice
    # xmlservice error occurred?
    rc = dltdatq.xmlservice_error
    if rc
      puts dltdatq.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts dltdatq.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    puts dltdatq.response.output

    crtdatq = XMLService::I_CMD.new("CRTDTAQ DTAQ(#{$toolkit_test_lib}/MYDATAQ) MAXLEN(100) AUT(*EXCLUDE)")
    # call IBM i
    crtdatq.xmlservice
    # xmlservice error occurred?
    rc = crtdatq.xmlservice_error
    if rc
      puts crtdatq.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts crtdatq.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    puts crtdatq.response.output

    # ***************************************
    # * PGM - Send Data Queue (QSNDDTAQ) API
    # ***************************************
    # * 1 Data queue name     Input Char(10)
    # * 2 Library name        Input Char(10)
    # * 3 Length of data      Input Packed(5,0)
    # * 4 Data Input Char(*)  Input
    messageSnd = 'System i data queues forever'
    qsnddtaq = XMLService::I_PGM.new("QSNDDTAQ")
    qsnddtaq << XMLService::I_a.new('queueName',10,'MYDATAQ')
    qsnddtaq << XMLService::I_a.new('libName',10,$toolkit_test_lib)
    qsnddtaq << XMLService::I_p.new('lenData',5,0,50.0)
    qsnddtaq << XMLService::I_a.new('dataInput',100,messageSnd)
    # call IBM i
    qsnddtaq.xmlservice
    # xmlservice error occurred?
    rc = qsnddtaq.xmlservice_error
    if rc
      puts qsnddtaq.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts qsnddtaq.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    puts qsnddtaq.response.output
    puts "Send......#{qsnddtaq.name}: #{qsnddtaq.response.dataInput}"

    # ***************************************
    # * PGM - Receive Data Queue (QRCVDTAQ) API
    # ***************************************
    # * 1 Data queue name  Input Char(10)
    # * 2 Library name     Input Char(10)
    # * 3 Length of data   Input Packed(5,0)
    # * 4 Data Char(*)     Output
    # * 5 Wait time        Input Packed(5,0)
    qrcvdtaq = XMLService::I_PGM.new("QRCVDTAQ")
    qrcvdtaq << XMLService::I_a.new('queueName',10,'MYDATAQ')
    qrcvdtaq << XMLService::I_a.new('libName',10,$toolkit_test_lib)
    qrcvdtaq << XMLService::I_p.new('lenData',5,0,50.0)
    qrcvdtaq << XMLService::I_a.new('dataOutput',100,'replace stuff here')
    qrcvdtaq << XMLService::I_p.new('waitTime',5,0,0.0)
    # call IBM i
    qrcvdtaq.xmlservice
    # xmlservice error occurred?
    rc = qrcvdtaq.xmlservice_error
    if rc
      puts qrcvdtaq.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts qrcvdtaq.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    puts qrcvdtaq.response.output
    puts "Receive...#{qrcvdtaq.name}: #{qrcvdtaq.response.dataOutput}"

Sample PASE Shell (system -i WRKSYSVAL)

    # ***************************************
    # * PASE shell utility system - WRKSYSVAL
    # ***************************************
    wrksysval = XMLService::I_SH.new("system -i 'WRKSYSVAL OUTPUT(*PRINT)'")
    # call IBM i
    wrksysval.xmlservice

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts wrksysval.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    # puts wrksysval.response.output.class.name
    output = wrksysval.response.output
    puts output

Sample DB2 query (like STRSQL)

    # ***************************************
    # * DB2 - query
    # ***************************************
    query = XMLService::I_DB2.new("select * from #{$toolkit_test_db2_lib}/animals")
    # call IBM i
    puts "\n+++++++++ input xml ++++++++++++++++"
    puts query.to_xml
    query.xmlservice
    # xmlservice error occurred?
    rc = query.xmlservice_error
    if rc
      puts query.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts query.dump_inspect

    # output
    # puts query.out_xml
    # rows
    puts "\n+++++++++ response output ++++++++++++++++"
    query.response.output.each do |row|
      all = ""
      row.each do |n,v|
        all << "#{n}=#{v} "
      end
      puts all
    end

Sample DB2 query with parms (better than STRSQL)

    # ***************************************
    # * DB2 - query
    # ***************************************
    id = 1
    query = XMLService::I_DB2.new("select * from #{$toolkit_test_db2_lib}/animals where ID < ?",{'id'=>id})
    # call IBM i
    puts "\n+++++++++ input xml ++++++++++++++++"
    puts query.to_xml
    query.xmlservice
    # xmlservice error occurred?
    rc = query.xmlservice_error
    if rc
      puts query.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts query.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    # puts query.out_xml
    # rows
    puts "id < #{query.returndata.id.strip}"
    query.response.output.each do |row|
      all = ""
      row.each do |n,v|
        all << "#{n}=#{v} "
      end
      puts all
    end

Sample DB2 call stored procedure with parms (better than STRSQL)

    # ***************************************
    # * DB2 - query
    # ***************************************
    in_name1 = 'Peaches'
    in_name2 = 'Rickety Ride'
    in_weight = 22.22
    query = XMLService::I_DB2.new("call #{$toolkit_test_db2_lib}/MATCH_ANIMAL(?, ?, ?)",
      {'name1'=>in_name1,"name2"=>in_name2,"weight"=>in_weight})
    # call IBM i
    puts "\n+++++++++ input xml ++++++++++++++++"
    puts query.to_xml
    query.xmlservice
    # xmlservice error occurred?
    rc = query.xmlservice_error
    if rc
      puts query.dump_all()
    end

    # inspect
    puts "\n+++++++++ dump_inspect ++++++++++++++++"
    puts query.dump_inspect

    # output
    puts "\n+++++++++ response output ++++++++++++++++"
    # puts query.out_xml
    # rows
    puts "name1 = #{query.returndata.name1.strip}"
    puts "name2 = #{query.returndata.name2.strip}"
    puts "weight = #{query.returndata.weight.strip}"
    query.response.output.each do |row|
      all = ""
      row.each do |n,v|
        all << "#{n}=#{v} "
      end
      puts all
    end