Add support for XMLSERVICE's multiple call

Issue #4 new
Aaron Bartell created an issue

Today the xmlservice Gem only supports one program call in an interaction with XMLSERVICE(RPG). This is in contrast to the Node.js itoolkit which has an .add() method allowing multiple pgm/cmd/etc calls to be made in a single round-trip to XMLSERVICE(RPG).

Comments (4)

  1. Former user Account Deleted

    Something like this ...

    usage ...
    
        multi_call = I_Multiple.new
    
        cmd = XMLService::I_CMD.new("CHGLIBL LIBL(QTEMP #{$toolkit_test_lib})", {'multiple' => multi_call})
        cmd.xmlservice   # this is not execute, but collection of delayed execute mutiple
    
        zzcall = XMLService::I_PGM.new("ZZCALL",$toolkit_test_lib,{'error'=>'fast', 'multiple' => multi_call})
        zzcall.input_parms 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 "dsdec1", 7, 4
           dec "dsdec2", 12, 2
         end
        end
        # normal parm set stuff (same as always)
        zzcall.execute   # this is not execute, but collection of delayed execute mutiple
    
    
        # ok, now really call xmlservice as multiple
        multi_call.execute # ok, this really called, out data in normal place for cmd and zzcall
    

    and here is the new class xmlservice.rb

     class I_Multiple                                    # change (new)
      def initialize()
        @xml_collect = Array.new
      end
      def collect(callme)
        @xml_collect.push(callme)
      end
      def to_xml()
        count = 1
        xmlin = ""
        @xml_collect.each do |callme|
          xmlin << "\n<task" + count.to_s + ">\n"
          xmlin << callme.to_xml
          xmlin << "\n</task" + count.to_s + ">\n"
          count += 1
        end
        xmlin
      end
      def xmlservice()
        # one thread at a time please
        @xml_is_error = true
        ActiveXMLService::Base.semaphore.synchronize {
          # user supplied connection
          if @xml_options && @xml_options.has_key?(:connection)
            adapter = ActiveXMLService::Base.adapter_factory(@xml_options)
          # standard rails connection (singleton)
          else
            adapter = ActiveXMLService::Base.connection
            # I believe "the Rails way" would be to lead them down a best-practice path,
            # xmlservice over db2 stored procedures is most common connection (best)
            if adapter.nil?
              adapter = ActiveXMLService::Base.adapter_factory('connection'=>'ActiveRecord')
            end
          end
          adapter.xmlservice(self)
          @xml_doc = adapter.out_doc
        }
        @xml_is_error = self.parse_diag_attr
        if !@xml_is_error
          count = 1
          @xml_collect.each do |callme|
            @xml_doc.elements.each("/myscript/" + "task" + count.to_s) do |task|
              callme.set_xml_doc(task)
            end
            count += 1
          end
        end
      end
      def execute()
        self.xmlservice
      end
     end                                                 # change (new)
    
    
     class I_CALL < I_Meta
      attr_accessor :input, :reponse, :return
      def initialize(options)
        @multiple = false                                # change
        if options && options.has_key?('multiple')
          @multiple = options['multiple']
          options.delete('multiple')
        end                                              # change
        @xml_options = ActiveXMLService::Base.symbolize_keys(options)
        @xml_is_error = true
        @input = I_Data.new
        @response = I_Data.new
        @returndata = I_Data.new
      end
      def set_xml_doc(doc)                               # change
        @xml_doc = doc
        @xml_is_error = self.parse_diag_attr
        self.parse_output_attr
        self.parse_return_attr
      end                                                # change
      def xmlservice()
       if @multiple                                      # change
        collect(self)
       else                                              # change
        @xml_is_error = true
        # one thread at a time please
        ActiveXMLService::Base.semaphore.synchronize {
          # user supplied connection
          if @xml_options && @xml_options.has_key?(:connection)
            adapter = ActiveXMLService::Base.adapter_factory(@xml_options)
          # standard rails connection (singleton)
          else
            adapter = ActiveXMLService::Base.connection
            # I believe "the Rails way" would be to lead them down a best-practice path,
            # xmlservice over db2 stored procedures is most common connection (best)
            if adapter.nil?
              adapter = ActiveXMLService::Base.adapter_factory('connection'=>'ActiveRecord')
            end
          end
          adapter.xmlservice(self)
          @xml_doc = adapter.out_doc
        }
        @xml_is_error = self.parse_diag_attr
        self.parse_output_attr
        self.parse_return_attr
       end                                               # change
      end
    
  2. Former user Account Deleted

    HEY ... never ran this code, so this is just a idea, but looks like it would work after fixing the missing stuff

    ALSO ... i think @xml_is_error in I_MULTIPLE is wrong ... not sure about full error thing ... maybe push it into class with set_xml_doc ...

    anywho ... there ye be

  3. Former user Account Deleted

    Here, i like this one better ...

        cmd = XMLService::I_CMD.new("CHGLIBL LIBL(QTEMP #{$toolkit_test_lib})")
        # cmd.xmlservice -- forget this call i want to join multi
    
        zzcall = XMLService::I_PGM.new("ZZCALL",$toolkit_test_lib,{'error'=>'fast')
        zzcall.input_parms 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 "dsdec1", 7, 4
           dec "dsdec2", 12, 2
         end
        end
        # normal parm set stuff (same as always)
        # zzcall.execute -- forget this call i want to join multi
    
    
        # ok, now really call xmlservice as multiple
        multi_call = I_Multiple.new
        multi_call.add(cmd)
        multi_call.add(zzcall)
        multi_call.execute # ok, this really called, out data in normal place for cmd and zzcall
    
    
    
    
    
     class I_Multiple                                    # change (new)
      def initialize()
        @xml_collect = Array.new
      end
      def add(callme)
        @xml_collect.push(callme)
      end
      def to_xml()
        count = 1
        xmlin = ""
        @xml_collect.each do |callme|
          xmlin << "\n<task" + count.to_s + ">\n"
          xmlin << callme.to_xml
          xmlin << "\n</task" + count.to_s + ">\n"
          count += 1
        end
        xmlin
      end
      def xmlservice()
        # one thread at a time please
        @xml_is_error = true
        ActiveXMLService::Base.semaphore.synchronize {
          # user supplied connection
          if @xml_options && @xml_options.has_key?(:connection)
            adapter = ActiveXMLService::Base.adapter_factory(@xml_options)
          # standard rails connection (singleton)
          else
            adapter = ActiveXMLService::Base.connection
            # I believe "the Rails way" would be to lead them down a best-practice path,
            # xmlservice over db2 stored procedures is most common connection (best)
            if adapter.nil?
              adapter = ActiveXMLService::Base.adapter_factory('connection'=>'ActiveRecord')
            end
          end
          adapter.xmlservice(self)
          @xml_doc = adapter.out_doc
        }
        count = 1
        @xml_collect.each do |callme|
          @xml_doc.elements.each("/myscript/" + "task" + count.to_s) do |task|
            # note you have to stip off <taskn>stuff</taskn>
            # and replace with <myscript>stuff</myscript>
            # for parsing in callme.set_xml_doc
            callme.set_xml_doc(task)
          end
          count += 1
        end
      end
      def execute()
        self.xmlservice
      end
     end                                                 # change (new)
    
    
     class I_CALL < I_Meta
      :
      def set_xml_doc(doc)                               # change
        @xml_doc = doc
        @xml_is_error = self.parse_diag_attr
        self.parse_output_attr
        self.parse_return_attr
      end                                                # change
      :
    
  4. Former user Account Deleted

    New version you only add the new class I_Multiple and add one method to I_CALL set_xml_doc ... easy ... and ... well kinda cute (opinion)

  5. Log in to comment