Murillo Braga · May 26, 2020 go to post

Hi Netanel, thanks for your insightful and detailed response. It  did help a lot :)

Murillo Braga · May 13, 2020 go to post

Hello Netanel, 

Nice framework you've provided, thanks.

I am wondering if it would be of any help to my case: I have used the Studio SOAP wizard to generate some webservice client classes and amongst those classes:

Class RMH.SOAP.s0.Output Extends (%Persistent, %XML.Adaptor) [ ProcedureBlock, SqlTableName = _Output ] {
...
Property Value As %GlobalCharacterStream(XMLNAME = "Value");

And the caller looks like

Class RMH.SOAP.SoapTreeSoap Extends %SOAP.WebClient [ ProcedureBlock ] {
...
Method Run...(Tree As %String, Inputs As %String, Debug As %Integer) As RMH.SOAP.s0.Output 

We do run a daily purge in all of our productions, but I noticed that some globals aren't being taken into consideration. The global related to the class above is occupying 8GB worth of data and its size isn't reduced after the daily purge take place (it uses the ensemble base class Ens.Util.Tasks.PurgeActivityData)

When I checked the global contents, I could definitely spot very old data... so that reinforces my assumption. Could the delete helper take care of this scenario? Or should I develop custom classes for the purge process?

Any help is appreciated.

Many thanks!

Murillo Braga · May 13, 2020 go to post

Hello Netanel, 

Nice framework you've provided, thanks.

I am wondering if it would be of any help to my case: I have used the Studio SOAP wizard to generate some webservice client classes and amongst those classes:

Class RMH.SOAP.s0.Output Extends (%Persistent, %XML.Adaptor) [ ProcedureBlock, SqlTableName = _Output ] {
...
Property Value As %GlobalCharacterStream(XMLNAME = "Value");

And the caller looks like

Class RMH.SOAP.SoapTreeSoap Extends %SOAP.WebClient [ ProcedureBlock ] {
...
Method Run...(Tree As %String, Inputs As %String, Debug As %Integer) As RMH.SOAP.s0.Output 

We do run a daily purge in all of our productions, but I noticed that some globals aren't being taken into consideration. The global related to the class above is occupying 8GB worth of data and its size isn't reduced after the daily purge take place (it uses the ensemble base class Ens.Util.Tasks.PurgeActivityData)

When I checked the global contents, I could definitely spot very old data... so that reinforces my assumption. Could the delete helper take care of this scenario? Or should I develop custom classes for the purge process?

Any help is appreciated.

Many thanks!

Murillo Braga · May 6, 2020 go to post

Hi there Marc,

Do you know whether is there anything to perform the opposite (convert an object into a xml string)?

E.g: 

Class BaseClass.Harvest Extends (%SerialObject, %XML.Adaptor) [ ProcedureBlock ]
{
Parameter ELEMENTQUALIFIED = 1;
...
Property Number As %String(MAXLEN = "", XMLNAME = "Number");
Property PatientNumber As %String(MAXLEN = "", XMLNAME = "PatientNumber");
...

Outcome would be:

<xml>
<Harvest>

   <Number></Number>
   <PatientNumber></PatientNumber>
...

Many thanks

Murillo Braga · May 6, 2020 go to post

Hi there Sean,

Do you know whether is there anything to perform the opposite (convert an object into a xml string)?

E.g: 

Class BaseClass.Harvest Extends (%SerialObject, %XML.Adaptor) [ ProcedureBlock ]
{
Parameter ELEMENTQUALIFIED = 1;
...
Property Number As %String(MAXLEN = "", XMLNAME = "Number");
Property PatientNumber As %String(MAXLEN = "", XMLNAME = "PatientNumber");
...

Outcome would be:

<xml>
<Harvest>

   <Number></Number>
   <PatientNumber></PatientNumber>
...

Many thanks

Murillo Braga · Apr 15, 2020 go to post

Hello Francisco,

Have you managed to do this? I have a similar request to build a pass-through SOAP WebService.

Thanks!

Murillo Braga · Mar 31, 2020 go to post

Hello Carlos,

These settings are a tad confusing because if not set up properly, can cause overlapping and, in my opinion, this is something the management portal should be able to validate and raise the error on the UI side.

In your case, the failure timeout is throwing this due to the fact that its value is lower than the Response Timeout and it shouldn't. 

Practically speaking: the operation will give up retrying after 15s. If the Response timeout is 30s, 15s has gone already (Failure Timeout triggers before the response comes), so logically you need a value here at least greater (double the Response timeout may be ideal).

This is the reason why you probably get the message saying that the Failure timeout exceeded. Furthermore, this should be combined along with the Retry interval, otherwise it will overlap its functioning.

Murillo Braga · Jun 17, 2019 go to post

That is great, Aleksandar! This expression helped me out taking off to something a bit more complex and I am managing to grab what I need so far.

Many thanks, mate

Murillo Braga · Jun 4, 2019 go to post

Hi Alex,

Great, this seems a good solution for it! The "when" is basically holding everybody up within the same block, which is what I needed.

Many thanks for your answer :)

Murillo Braga · May 31, 2019 go to post

Hi Julian,

Thanks for your time.

OK then, but removing the return doesn't affect anything at all. I actually put it there while testing to see if it would impact somehow.

The test that I've just did was getting rid of the return (keeping the order of the "whens") and the message only hit the 1 when target (in this case "ManageEDM". I then switched the order and it only hit the "ManageRIS". See below

Murillo Braga · Jul 17, 2018 go to post

Hi Jan,

Thanks but I want to follow what the deployment tool is advising me to, include everything I need through the management portal export tool. What is the solution in this case then?

Because we know that the export tool has a very poor interface that doesn't allow me to select more than 1 file, hence I need to to stick to creating a "project file" if I want to include a group of custom files for example, but it doesn't seem possible.

I don't really see a way out.

Murillo Braga · Jul 17, 2018 go to post

OK I found it, but now I can't understand why my final XML doesn't include the definition from all files I have included into the project file.

Any ideas?

Murillo Braga · Jul 17, 2018 go to post

Thanks John but I have come across this documentation previously and still couldn't find exactly what I should use in order to achieve my need.

Would you mind pointing me something more specific? (the documentation is very extensive and I guess my need is very straightforward, doesn't seem a complex task).

Cheers

Murillo Braga · Apr 6, 2018 go to post

Hello Eduard,

Do you know if we could specify a shared network folder instead of C: or D: when exporting or importing the XML file?

Because the GUI itself blocks me if I try to change the file path.

Thanks

Murillo Braga · Sep 27, 2017 go to post

Hello Tani,

Thanks for sharing this useful information.

I have the feeling that Intersystems could somehow improve the tool in terms of validating and not allowing timeouts overlapping each other, if you understand what I'm saying.

It is a very common mistake people make when configuring these timeouts and sometimes they end up not enjoying the real benefits they can offer.

I am now very confused while trying to put in context what you described in your article (related to webservices) along with the TCP connection world, because it has got, additionally to the timeouts you've mentioned:

Stay Connected
Connect Timeout
Reconnect Retry
Read Timeout

For example, the reconnect retry sounds very close to the purpose of the Retry Interval, so I am not too confident on how to set these guys up.

Are you able to give me a helping hand?

Thanks

Murillo Braga · Feb 2, 2017 go to post

OK John, thanks for your help so far.

I've been in touch with them, but they couldn't so far figure out what is it... we're discussing, but I will post an update here whenever we figure out the resolution (if any, lol).

Cheers

Murillo Braga · Feb 2, 2017 go to post

Hello mate,

It generates the same error: ERROR #6301: SAX XML Parser Error: invalid character 0x18 while processing Anonymous Stream at line 1 offset 4183

Here is the code:

msg.Value.Rewind()
set fs=##class(%Stream.FileCharacter).%New()
set fs.Filename="D:\DATABASES\OVPATH\temp\test0.xml"
set fs.TranslateTable = "UTF8"
set tSC=fs.CopyFrom(msg.Value)
set tSC=fs.%Save()
reader=##class(%XML.Reader).%New()
fs.Rewind() // might not be necessary, but won't hurt
Set sc = reader.OpenStream(fs)
if $$$ISERR(sc)
{
set fs=##class(%Stream.FileCharacter).%New()
set fs.Filename="D:\DATABASES\OVPATH\temp\errorOpen0.xml"
do fs.Write($$$StatusDisplayString(sc))
set tSC=fs.%Save()
}

Murillo Braga · Feb 1, 2017 go to post

John,

Just to let you know, I am still a beginner with ObjectScript/Cache/Healthsare, so please excuseany primary mistakes you may encounter :)

Can you kindly help me out to write this piece of code you advised? (P.S: msg.Value is the stream)

set fs=##class(%Library.GlobalCharacterStream).%New()
set fs.TranslateTable = "UTF8"
set tSC=fs.CopyFromAndSave(msg.Value)
  sc= xread.OpenStream(???)
if $$$ISERR(sc)
{
...
}

---

I came up with that a few moments ago: (at this point I have the stream available (msg.Value) and I will handle it in 2 different ways: by writing is a file and trying to open it (OpenFile) and by reading it (OpenStream))

  //
  // 1st approach - it succeeds, so the file errorOpenFile.xml is NOT generated
  //    
  d msg.Value.Rewind()
  set fs=##class(%Stream.FileCharacter).%New()
  set fs.Filename="D:\DATABASES\OVPATH\temp\test.xml"
  set fs.TranslateTable = "UTF8"
  set tSC=fs.CopyFrom(msg.Value)
  set tSC=fs.%Save()
    
  s reader=##class(%XML.Reader).%New()
  Set sc = reader.OpenFile("temp/test.xml")
    
  if $$$ISERR(sc)
  {
    set fs=##class(%Stream.FileCharacter).%New()
    set fs.Filename="D:\DATABASES\OVPATH\temp\errorOpenFile.xml"
    do fs.Write($$$StatusDisplayString(as))
    set tSC=fs.%Save()
  }    

  //
  // 2nd approach - it fails, so I have the file errorOpenStream.xml generated
  //    
  Set xread = ##class(%XML.Reader).%New()
  Set xread.IgnoreNull=1                  
  d msg.Value.Rewind()    
  s sc= xread.OpenStream(msg.Value)
    
  if $$$ISERR(sc)
  {
    set fs=##class(%Stream.FileCharacter).%New()
    set fs.Filename="D:\DATABASES\OVPATH\temp\errorOpenStream.xml"
    do fs.Write($$$StatusDisplayString(sc))
    set tSC=fs.%Save()
  }

Murillo Braga · Jan 31, 2017 go to post

My 1st message on this post shows the piece of code where the pInput is originally fed.

And as I told there, I write the output content to a file and once I open this file, the contents are shown properly and the character is there, intact.

Murillo Braga · Jan 31, 2017 go to post

Hello John,

Thanks again for your help!

There you go the outcome:

1st one:

<?xml version="1.0" encoding="UTF-8" ?>< ... (more content)

2nd one:

60
63
120

I'm not sure about the BOM, but the XML returned does state the UTF-8 encoding.

Murillo Braga · Jan 30, 2017 go to post

Hello mate,

Thanks for you quick response. Actually there was no specific reason for using the FileBinary, so I managed to change it to FileCharacter and used also the property "TranslateTable = "UTF8", which hence allowed the file to be written with the special character I wanted.

By discovering that, I came back to the 1st place I originally thought the issue would be and now I guess that it's the right place to look at:

Method OnProcessInput(pInput As %Stream, Output pOutput As %RegisteredObject, ByRef pHint As %String) As %Status
{
    // Create an instance of %XML.Reader
    Set xread = ##class(%XML.Reader).%New()
    Set xread.IgnoreNull=1
        
    // Begin processing of the file
    pInput.Rewind()
    
    sc= xread.OpenStream(pInput)
   
     if $$$ISERR(sc)
{
set fs=##class(%Stream.FileCharacter).%New()
set fs.Filename="c:\TEMP\OnProcessInput00.xml"
set fs.TranslateTable = "UTF8"
do fs.Write($$$StatusDisplayString(sc))
set tSC=fs.%Save()
}

---

Here I had the file created and the error message written in it (ERROR #6301: SAX XML Parser Error: invalid character 0x18 while processing Anonymous Stream at line 1 offset 4627).

So I presume that
sc= xread.OpenStream(pInput)

Is erroring, because the stream contains a special character.

What do you think?

Thanks

Murillo Braga · Jan 26, 2017 go to post

Hey John, thanks for you response!

I wrote some debug piece of code to write into a xml file the pInput content and that's what I get:

<?xml version="1.0" encoding="UTF-8" ?> ... <Value><![CDATA[ ... <P>SORRY TO SAY THAT THIS CHARACTER WILL MESS THIS UP  ?</P> ... ]]></Value>

Where you see the question mark, it is indeed the place the weird character is supposed to be.

By opening the file with Notepad++ and checking the 'Encoding' menu, it shows 'Encode with UTF-8 without BOM'.

Any clues?

Thanks

Murillo Braga · Jun 24, 2016 go to post

My team leader advised me to do one thing that did the trick: stop the production, save the business rule and then restart the production and resend the message again.

He said it sounds like it's something related to memory management done by the Ensemble, because for safety reasons/keep the messages flowing correctly, it keeps some previous compiled version in memory until a certain point and then brings new one as soon as it realizes that either it's the right time to do it or I've ordered it to do so. I might be saying bullshit, but as I've said, I'm just a begginer in this environment.

Thanks mates!

Murillo Braga · Jun 24, 2016 go to post

My team leader advised me to do one thing that did the trick: stop the production, save the business rule and then restart the production and resend the message again.

He said it sounds like it's something related to memory management done by the Ensemble, because for safety reasons/keep the messages flowing correctly, it keeps some previous compiled version in memory until a certain point and then brings new one as soon as it realizes that either it's the right time to do it or I've ordered it to do so. I might be saying bullshit, but as I've said, I'm just a begginer in this environment.

Thanks mates!