Advanced Queuing possible without Oracle Client?

Discussion of open issues, suggestions and bugs regarding ODAC (Oracle Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
MDrueck
Posts: 18
Joined: Fri 01 Apr 2011 14:06
Location: Germany

Advanced Queuing possible without Oracle Client?

Post by MDrueck » Wed 24 Jun 2020 10:58

Hi,

here it says:
Direct Mode

Allows your application to work with Oracle directly via TCP/IP without involving Oracle Client, thus significantly facilitating deployment and configuration of your applications.
Is that also true when I try to use Advanced Queuing?

Which properties of TOraSession do I have to set accordingly?

Thanks in advance, Markus

MaximG
Devart Team
Posts: 1822
Joined: Mon 06 Jul 2015 11:34

Re: Advanced Queuing possible without Oracle Client?

Post by MaximG » Fri 10 Jul 2020 16:21

What features of Advanced Queueing are you going to use? Our components don't offer a dedicated option for enabling or disabling Direct Mode for Advanced Queueing.

MDrueck
Posts: 18
Joined: Fri 01 Apr 2011 14:06
Location: Germany

Re: Advanced Queuing possible without Oracle Client?

Post by MDrueck » Wed 12 Aug 2020 08:50

MaximG wrote: Fri 10 Jul 2020 16:21 What features of Advanced Queueing are you going to use? Our components don't offer a dedicated option for enabling or disabling Direct Mode for Advanced Queueing.
Sorry, I don't know how to answer that question. ;-) I just want that the ODAC components work, nothing more nothing less. In the meantime me managed to connect to the database and successfully ENQUEUE a message. Now our main problem is, how to dequeue. We are connecting in directe mode.

So we have code:

Code: Select all

function TfrmMainAOS.DequeueFARMS : Boolean;
var
  Agents           : TQueueAgents;
  Agent            : TQueueAgent;
  QueueMessage     : TQueueMessage;
begin
  Result := False;
  try
    Agents := TQueueAgents.Create;
    try
      Agents.Add.Address := edtLEJQueueTo.Text;
      Agent := TQueueAgent.Create;

      OraQueue.QueueName                  := edtLEJQueueTo.Text;
      OraQueue.DequeueOptions.WaitTimeout := AQ_NO_WAIT;
      OraQueue.DequeueOptions.Navigation  := qnNextMessage;
      OraQueue.DequeueOptions.DequeueMode := dqmRemove;

      try
        Agent := TQueueAgent.Create;
        try
          OraQueue.Listen(Agents, Agent, FLEJTimeOut);
          var DequeueOptions: TDequeueOptions := TDequeueOptions.Create;
          try
            DequeueOptions.DequeueMode := dqmBrowse;
            QueueMessage := TQueueMessage.Create;
            try
              OraQueue.Dequeue(QueueMessage, DequeueOptions);
              OraQueueMessage(OraQueue, QueueMessage.MessageId, QueueMessage.MessageProperties);
            finally
              FreeAndNil(QueueMessage);
            end;
          finally
            FreeAndNil(DequeueOptions);
          end;
        finally
          Agent.Free;
        end;
      except
        on E : System.SysUtils.Exception do
        begin
          Log.Fatal(Format('OraSession.LastError:     [%d]', [OraSession.LastError]));
          HandleExceptionPrim(E, E.message, 10, 'TfrmMainAOS.DequeueFARMS');
        end;
      end;
    finally
      Agents.Free;
    end;

    Result := True;
  except
    on E : System.SysUtils.Exception do begin
      Log.Fatal(Format('OraSession.LastError:     [%d]', [OraSession.LastError]));
      HandleExceptionPrim(E, E.message, 11, 'TfrmMainAOS.DequeueFARMS');
    end;
  end;
end;
And:

Code: Select all

procedure TfrmMainAOS.OraQueueMessage(Sender: TOraQueue; const MessageId: string;
  const MessageProperties: TQueueMessageProperties);
var
  ObjectPayload   : TOraObject;
  FileName        : string;
  MsgId           : string;
  PayLoad         : string;      // Die eigentlichen Nutzdaten
  EnqueueTime     : TDateTime;
begin
  OraQueue.DequeueOptions.MessageId        := MessageId;
  OraQueue.DequeueOptions.DeliveryMode     := qdmPersistentOrBuffered;
  OraQueue.DequeueOptions.DequeueCondition := EmptyStr;
  EnqueueTime                              := MessageProperties.EnqueueTime;

  Log.Info(Format('MessageProperties.Delay = [%d]', [MessageProperties.Delay]));
  if MessageProperties.Delay > AQ_NO_DELAY then begin
    MWWait(MessageProperties.Delay * 1000);
  end;

  case MessageProperties.State of
    qmsReady     : Log.Info('MessageProperties.State = qmsReady');
    qmsWaiting   : Log.Info('MessageProperties.State = qmsWaiting');
    qmsProcessed : Log.Info('MessageProperties.State = qmsProcessed');
    qmsExpired   : Log.Info('MessageProperties.State = qmsExpired');
  end;

  if {(IncSecond(EnqueueTime,MessageProperties.Expiration) <= now) and } (MessageProperties.State = qmsReady) then begin
    try
      ObjectPayload := TOraObject.Create;

      try
        memXMLData.Lines.Clear; // das ist ein TMemo auf dem Formular
        FileName := Format('%s\FARMS To AM %s.xml', [edtTxtImportUpdateFolder.Text, FormatDateTime('YYYY DD MM - HH NN SS', Now)]);
        Log.Info(Format(' Message ID: [%s]', [MessageId]));
        Log.Info(Format(' Enqueue Time : [%s]', [FormatDateTime('YYYY DD MM - HH NN SS', EnqueueTime)]));
        Log.Info(Format(' Dequeue Attempts : [%s]', [IntToStr(MessageProperties.Attempts)]));

        try
          var DequeueOptions: TDequeueOptions := TDequeueOptions.Create;
          try
            DequeueOptions.DequeueMode := dqmRemove; // Es ist standardmäßig beim Create auf dqmRemove gesetzt, hier einfach zum Hinweis
            // hier jetzt die richtige Message holen, die über das Event übergeben wurde (MessageId)
            MsgId := OraQueue.Dequeue(ObjectPayload, MessageProperties, DequeueOptions);
          finally
            FreeAndNil(DequeueOptions);
          end;
        except
          on E : System.SysUtils.Exception do begin
            Log.Fatal(Format('OraSession.LastError:     [%d]', [OraSession.LastError]));
            Log.Fatal(Format('OraQueue.Empty            [%s]', [E.Message]));
          end;
        end;

        // hier die Daten holen die in der Payload stehen
        if ObjectPayload.AttrIsNull['text_lob'] then begin
          PayLoad := ObjectPayload.AttrAsString['text_vc']
        end else begin
          PayLoad := ObjectPayload.AttrAsLob['text_lob'].AsWideString;
        end;

        Log.Info(Format('DEQUEUE: MsgId: [%s]; Length: [%d]', [MsgId, ObjectPayload.AttrAsInteger['text_len']]));
        memXMLData.Lines.Add(PayLoad);
        OraQueue.Session.Commit;
        Log.Info(Format('OraSession.LastError: [%d]', [OraSession.LastError]));
      finally
        FreeAndNil(ObjectPayload);
        memXMLData.Lines.SaveToFile(FileName);
      end;
    except
      on E : System.SysUtils.Exception do begin
        Log.Fatal(Format('OraSession.LastError:     [%d]', [OraSession.LastError]));
        HandleExceptionPrim(E, E.message, 12, 'TfrmMainAOS.OraQueueMessage');
      end;
    end;
  end else begin
    Log.Fatal(Format(' Error message expired -> Message ID: [%d]', [MessageId]));
  end;
end;
The big question is, when do I know that the queues is empty? How often do I have to get a record from the queue in OraQueueMessage?

Thanks in advance.

MaximG
Devart Team
Posts: 1822
Joined: Mon 06 Jul 2015 11:34

Re: Advanced Queuing possible without Oracle Client?

Post by MaximG » Fri 28 Aug 2020 09:06

Thank you for the information. We will investigate the described issue and let you know the results shortly.

Post Reply