Cache Ensemble

Hello,

Working on to learn very basic CUSTOM Business Service which sends to a EnsLib.File.PassthroughOperation.

But operation is not writing to File and erroring out (No Stream contained in StreamContainer Request")'.

How do convert the object to STREAM and wrap in the StreamContainer so the operation does not error and write to a file.

Thanks.

Persistent Class

Class Hospital.PatientApptRequest Extends %Persistent
{
Property PatientId As %Stream.FileCharacter;
Property PatientName As %Stream.FileCharacter;
..

 

Custom Service reads from a file

Method OnProcessInput(pInput As %FileCharacterStream, Output pOutput As %RegisteredObject) As %Status
{
set tSC = $$$OK
    set pInput.LineTerminator=$c(10)
try 
{
while 'pInput.AtEnd {
          set tMsg = ##class(Hospital.PatientApptRequest).%New()
          
          set tLine = pInput.ReadLine()
          set tMsg.PatientId = tLine
          
          set tLine = pInput.ReadLine()
          set tMsg.PatientName = tLine
          
          do pInput.ReadLine()
          
          set tRequest1=##class(Ens.StreamContainer).%New(tMsg)
      
          set tSC = ..SendRequestAsync(..TargetConfigNames,tRequest1)
} }
catch ex 
{
set tSC = ex.AsStatus()
}
quit tSC
}
 

Sample File contents

1

ABC

 

2

DEF

Thanks,

Jimmy Christian.

 

  • 0
  • 0
  • 112
  • 6
  • 2

Answers

Hi Jimmy,

The problem - I think - is that you are passing an object of class Hospital.PatientApptRequest (which is not a stream) into an Ens.StreamContainer. What should work is

set tRequest1=##class(Ens.StreamContainer).%New(pInput)

Of course this makes the tMsg object redundant, but maybe you have another purpose for that elsewhere in your code.

As an aside, it is a good habit to have your class Hospital.PatientApptRequest inherit from Ens.Request instead of %Persistent. This is relevant when you want to purge old message traces.

Have fun developing your integration skills!

Thank you Aldo for checking this out. I tried to make it much simpler by using what you suggested. I was hoping the operation to  accept it since pInput is a Stream.

But still the same error. Operation does not find STREAM in the ENS. StreamContainer.

Class Hospital.ApptListFileService Extends Ens.BusinessService
{
Parameter ADAPTER = "EnsLib.File.InboundAdapter";
Parameter SETTINGS = "TargetConfigNames";
Property TargetConfigNames As Ens.DataType.ConfigName;
Property SentMsg As %FileCharacterStream;

Method OnProcessInput(pInput As %FileCharacterStream, Output pOutput As %RegisteredObject) As %Status
{
set tSC = $$$OK
    set pInput.LineTerminator=$c(10)
try 
{
while 'pInput.AtEnd {
          do pInput.ReadLine()
         
          set tRequest=##class(Ens.StreamContainer).%New(pInput)
  
          set tSC = ..SendRequestAsync(..TargetConfigNames,tRequest)
}

did you try to Save your Stream.Container ?

set tSC tRequest.%Save()

before 

set tSC = ..SendRequestAsync(..TargetConfigNames,tRequest)

Yes, I did. 

       set tRequest=##class(Ens.StreamContainer).%New(pInput)
      do tRequest.%Save()
      set tSC = ..SendRequestAsync(..TargetConfigNames,tRequest)

Thanks,

Jimmy Christian.

Ens.StreamContainer's %New() method expects a string as the first parameter rather than a stream object.

Something like this should work:

set tRequest=##class(Ens.StreamContainer).%New()
set tSC=tRequest.StreamSet(pInput)

Or if you're trying to send one Ens.StreamContainer for each line from the input file you could do this:

while 'pInput.AtEnd {
    set tReadLength=32000
    set tLine=pInput.ReadLine(.tReadLength,.tSC)
    set tRequest=##class(Ens.StreamContainer).%New(tLine)
    //... do other stuff
}

One other thing you should be aware of. The following will not work if TargetConfigNames has more than one target selected:

set tSC = ..SendRequestAsync(..TargetConfigNames,tRequest)

You should add a loop using $LENGTH and $PIECE and do a SendRequestAsync for each item in TargetConfigNames' comma-separated string.

Thank you Marc. Looks like this  Issue is resolved . Appreciate your input.

Are you sure about:

Property PatientId As %Stream.FileCharacter;
Property PatientName As %Stream.FileCharacter;

Both of these fields are less than 3 641 144 characters in size, so

Property PatientId As %VarString;
Property PatientName As %VarString;

Would probably work.

You can add ToStream() method to your class to provide serialization, if you need to (Or just add JSON or XML adaptors to generate XML or JSON (de)serializations automatically).

Hello Eduard,

I used %Stream.FileCharacter to resolve the error on Operation which is complaining that "No Stream contained in StreamContainer Request".

I am going to use the JSON serialization once i  refer to some document about it. 

Thank you for help.

Jimmy Christian.