Thank you both for your quick replies.

That was exactly what I was looking for....

I think I will be using both...one to stop the other processes accessing the global + locks to really ensure no other processes access the global.

My code will be something like the following:

// Stop other ensemble jobs accessing to the global to avoid bad messages. // Jobs are such as services/processes/operations by name. DO ##class(Ens.Director).EnableConfigItem("xxx",0,0)$$$LOGINFO("xxx Disabled")// Add a lock to control access to the global.// 0 => 1 attemp only.LOCK +^lockname:0// If lock is unsuccesfull, $TEST variable = 0If '$TEST {$$$LOGERROR("Lock cannot be obtained. Process cannot continue.")Quit tSC }$$$LOGINFO("LOCK on")*** code here to update global ***// Start other ensemble jobs accessing to the global to avoid bad messages. // Jobs are such as services/processes/operations by name. DO ##class(Ens.Director).EnableConfigItem("xxx",1,0)$$$LOGINFO("xxx Enabled")// REmove lock to control access to the global.LOCK -^lockname$$$LOGINFO("LOCK off")

In my case, processes accessing the global are just to read data from global, the global will not be changed by them. It is just once a month the global needs to be updated and only then is when the locks would be required.

Well...after trying and trying for a while I have more information to share:

As the testing store procedure with no input parameters was working fine... I decided to play with it and copy the code from the other procedure into this testing one. I did, and magically the call worked. But it was still not working with the store procedure I want to use. I checked the input parameter in case that was the problem and it could be the "MAX" for the varchar. Maybe this is what is causing issues. If I set 1000, 2000 or any other value...it works fine, no issues at all, even I manage to run the store procedure I want with that input parameter set to a numeric value and not "MAX" and it worked...but then I changed it to "MAX" and after a few messages that did work...stopped working and I am having the same problem now...

Memory allocation failure

So I know the code is fine, the call to the store procedure is fine...I guess is something with the connection or the way the ODBC talks to the database or how that input parameter is passed to the database.

I would appreciate any suggestion... 

Thanks

Thanks but that would be similar as the code that worked for me...What I really want is to pass the parameter as a parameter in the call to execute the procedure.

Anyway as I say in the new comment...I don't think the problem is within the code but with the odbc or with the "MAX" for the input parameter.

Thanks

The point is that storeprocedure has been used for ages with another integration engine and with other applications...and that call never had any problem. That store procedure was configure to accept an incoming string with any length...that is why the VARCHAR(MAX) was used.

Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.

Thanks for your help Robert...

I have changed the input parameter in the storeprocedure to VARCHAR(8000) instead of VARCHAR(MAX) and is working so far...

Thanks

Thanks for your response. Maybe I was a little bit unclear...sorry about that.

I did not include the full message, just the first characters as an example of the structure of the message I am receiving.

Basically, I am receiving a message (string) from a database (pInput As EnsLib.SQL.Snapshot), and converting that string into an HL7 message (##class(EnsLib.HL7.Message).ImportFromString(pInput.GetData(1))).

The string I am receiving is fine, nothing is missed, but when the string is converted into HL7, part of the message just dissapears. I cannot see any limitation on the number of characters, and if I check the size of the converted HL7 is not close to any round number as 2,000, 3,000...

I am going to try to change the schema to a custom one with the same structure I am receiving and check if that works...

Thanks

Thanks for your quick response.

As far as I can understand, that code is to create the task...and that can be done in ensemble as in ..."System Operation/Task Manager/New Task". The problem is that when creating the task you must specify a "Task Type" and there is no way that those types can be created easily...a part from in Studio.  In the "New Task" screen I can read the following:

For user-defined tasks you must first create a new subclass of the %SYS.Task.Definition class which will then be selectable as a 'Task type'.

Which means there is a way to create a class that creates a "Task Type" that later can be selected when creating a new task. But this is my problem. I don't know how to create that class and if needs to be stored in a specific location for ensemble to get that new type.

Thanks

It worked. What I did is the following:

Start & stop with a few seconds diff. so the service runs but stop immediately.

START:WEEK-*-03T10:45:00

,STOP:WEEK-*-03T10:45:10

and use "Call Interval=999999999" so the following run during start/stop times is longer than that time so it will only run once.

Thanks

Thanks Robert...very helpful

I noticed that I need to have an ADAPTER to be configured for that service to work...otherwise Init method will not run. As soon as I had an adapter configured...$$$LOGINFO and OnInit method worked...

Thanks

WOW...that was quick...thanks Sean

1) CacheTemp needs to be the name of the class or the name of the global? I mean:

^XXX.Global.CacheTempGlobal OR ^CacheTempGlobal

2) The process I designed read the file with the updated data, and upload line by line unless is a duplicate...so basically every line requires a query against the Temp global to check if that entry already exist or not. Sometimes, the new entry needs to replace the value in the temp global, so for that I delete the entry in the temp global and then add the new one. (That part is quite complex and I do not think is relevant for the global problem). Once the temp global contains all data from the file is when I start the process to export the global to a file, modify the name of the global in the file to point to the LIVE one and then when I update the LIVE global with that file.

I cannot use the merge command as the file with the updated data includes all data not just new entries but everything...so I rather delete the LIVE global completely and then import the new global file.

3) In order to avoid so many deletions of data to the temp global, I was thinking maybe to upload the content of the file into an array or something, remove all duplicates from there and then the final data to be uploaded to the temp global. But I am not sure if that will have a real improvement with just uploading/deleting to the temp global directly.

Thanks

1) my question is because when I create the global I have to specify the package as well:

Package: XXX

Name: XXX

I am not sure if the CacheTemp has to be included in the package name or just class name so: XXX.CacheTempGlobal or CacheTempGlobal

2) About how the global is structured:

    ^XXX.Stored.GlobalD    =    3
     ^XXX.Stored.GlobalD(1)    =    $lb("","Code3","TESTING3","","","FIRCROFT, LONDON ROAD","GREEN","EGHAM","",$c(0)," 0BS","1",$c(0),"A","P","H1","19740401","19910401",$c(0),$c(0),$c(0),$c(0),"0",$c(0),$c(0),$c(0),$c(0),$c(0))
     ^XXX.Stored.GlobalD(2)    =    $lb("","Code2","TESTING2","","","FIRCROFT, LONDON ROAD","GREEN","EGHAM","",$c(0)," 0BS","1",$c(0),"A","P","H2","19740401","19910401",$c(0),$c(0),$c(0),$c(0),"0",$c(0),$c(0),$c(0),$c(0),$c(0))
     ^XXX.Stored.GlobalD(3)    =    $lb("","Code10","TESTING10","","","FIRCROFT, LONDON ROAD","GREEN","EGHAM","",$c(0)," 0BS","1",$c(0),"A","P","H3","19740401","19910401",$c(0),$c(0),$c(0),$c(0),"0",$c(0),$c(0),$c(0),$c(0),$c(0))

Thats how the global looks like. So basically the search the interfaces run is jut to check a specific field in the message is in the global field 14 (H1,H2,H3...) and if so translate that code to global field 1 (Code2, Code3, Code10...). But when importing the data any of the other fields can change...so that's why is better to remove the global completely and upload everything from the file.

The problem with the logs is when so many duplicates are found in the file and the last one needs to be kept in the global...that made every single duplicate new code to be uploaded and the existing one to be removed...which I think generates an entry for each action...

Thank Sean

When creating the class linked to the global a package name is required...but anyway I think it worked. So thank you very much for your help.

Not sure if this will help but I was having problems to connect to a database in ensemble. I needed to call a store procedure and one of the problems was because of the input variables was a VARCHAR(MAX).

Have a look in case it can help... Post

Apparently this is exactly what I am looking for: intersystems help but the problem is that I would prefer to use the standard file operation rather than create a new custom one.

Writes a string to the file and appends to the string the characters specified in the LineTerminator property. By default, the LineTerminator is a carriage return followed by a line feed (ASCII 13, ASCII 10).

If your operating system requires a different value for the LineTerminator property, set the value in the OnInit() method of the business operation. For example:

 Method OnInit() As %Status
  {
      Set ..Adapter.LineTerminator="$C(10)"
      Quit $$$OK
  }

You can also make the property value to be dependent on the operating system:

 Set ..Adapter.LineTerminator="$Select($$$isUNIX:$C(10),1:$C(13,10))"

Yo are absolutely right although I am still confused.

I copied httprequest.Get("http://www.intersystems.com",2) from one example found in the documentation so I was expected to work. Also, to get data from a website don't think you have to use https or SSL right? I tried with different APIs in other applications and just passing the right URL I was able to retreive the data.

About httprequest.HttpResponse  you are right again... I was using httprequest.HttpResponse.Data and outputtodevice but I was having an error as the object did not exist...so I tried to check if the object was really created or not...

What would be the right script to connect then? I am trying to get data from this API https://api.postcodes.io/postcodes/

Thanks

I have tried to created an SSL/TLS configuration but not sure why is not working:

It does not matter what I try to test it...always returns the same error:

ERROR #989: SSL connection failed, make sure server address and port (not url) is specified

I tried "intersystems.com" 443, "postcodes.io" 443...nothing

Those sites I am trying to connect to....don't really need anything special to connect...just url

Thanks

Thanks for your help... I think the problem I am having is not with my code but with ensemble or IT. Apparently somehow the connection to external content is blocked. I can access to the websites with no issues from web browsers but when trying to access from studio or test SSL from ensemble...error!!

Is there any security configuration to block that kind of access in ensemble?

Thanks

Thanks for the help:

1. I have tried from the server where ensemble is running. In IE, I can access www.intersystems.com but when trying from studio...nothing blank response...all from the same matchine!

2. I tried that and yes...ERROR #6059: Unable to open TCP/IP socket to server www.intersystems.com:80 so I think you are right but I cannot believe the problem is no visibility when in IE I can access the website with no issues.

I have tried by IP, apparently 38.111.0.52

so  in IE:  http://38.111.0.52:80 => ok, https://38.111.0.52:443 => ok

but using:

Set httprequest=##class(%Net.HttpRequest).%New()
Set httprequest.Server = "38.111.0.52"
Set httprequest.Port=80
set status = httprequest.Get("/",2)
DO $system.OBJ.DisplayError(status)

ERROR #6059: Unable to open TCP/IP socket to server 38.111.0.52:80

I have no idea what's going on

not working but ping could be blocked in a firewall...and when I tried from my local PC, ping did not work either...

I could be wrong but I am pretty sure is something blocking that connection but maybe based on the protocol...not sure...what I cannot understand is why browse to the web site works but httprequest not.

Thanks

Thanks but I am afraid that did not work... when adding that into my service code and run it... I had an error message:

ERROR <Ens>ErrException: <UNDEFINED>zOnInit+14^CUH.Serv.ODSCodeGlobalUpdate.1 *%request -- logged as '-' number - @' Do ##class(Ens.Util.Log).LogInfo($classname(),"OnInit",%request.GetCookie("Username"))'

ERROR <Ens>ErrException: <UNDEFINED>zOnInit+13^CUH.Serv.ODSCodeGlobalUpdate.1 ^CacheTemp.EnsUsername(960) -- logged as '-' number - @' Do ##class(Ens.Util.Log).LogInfo($classname(),"OnInit",^CacheTemp.EnsUsername($job))'

Thank you but not sure about what you said.

I don't have a %request. It is just a Business Service doing nothing...and all I want is to get the username who enable it last time. Well, actually not last time. The service is normally off, so when is turned on, I want the username to be recorded in the log.

I have a function which actually run "write $USERNAME" and if I run it from Studio returns the username!

That's exactly what I am doing...using OnInit method:

Method OnInit() As %Status
{
SET tSC=$$$OK
// Add info to the log.
$$$LOGINFO("*******************************")
$$$LOGINFO("Run by:"_$Username)
$$$LOGINFO(" > "_$SYSTEM.Process.UserName())
...

Nothing works...

Found the issue.

The store procedure was adding extra breakline at the end of the first SPM segment and ensemble identify that as end of message.

All sorted now.

Thanks all for your help.