Hi all,
In 11.6.4, I'm using the HTTP client to perform a number of operations in SharePoint via its REST API. The code is running on a Webspeed agent in PASOE. Monitoring the sessions using the Windows Resource Monitor, I see that a thread starts up and just stays in an active state and never dies, as opposed to other threads that show as greyed-out after they're done, and eventually quit. After a few calls, the agent is unable to handle any new requests. The problem of threads not dying is limited to those that contact SharePoint.
All my SharePoint code is contained in static methods in a single class, and I'm careful to DELETE OBJECT everything associated with the HTTP client in those methods when I'm done. My HTTP headers are set to "close" as opposed to "keep-alive" and I'm at a loss as to why the agent threads are hanging around.
I have run the PKB's leakCheck.p and the only new objects in memory after calling one of my methods are several instances of OpenEdge.NET.HTTP.BuilderRegistry - I understand from a Communities post by Peter Judge that this is expected, and OK.
I understand that 11.7.5 and v12 have several fixes for memory leaks in the HTTP client that have not been fixed in 11.6, but I'm not aware of any problem - fixed or not - around threads getting stuck in 11.6.
Here is a code sample:
Invoked like this:
Am I doing anything obviously wrong?
TIA
Tarby
In 11.6.4, I'm using the HTTP client to perform a number of operations in SharePoint via its REST API. The code is running on a Webspeed agent in PASOE. Monitoring the sessions using the Windows Resource Monitor, I see that a thread starts up and just stays in an active state and never dies, as opposed to other threads that show as greyed-out after they're done, and eventually quit. After a few calls, the agent is unable to handle any new requests. The problem of threads not dying is limited to those that contact SharePoint.
All my SharePoint code is contained in static methods in a single class, and I'm careful to DELETE OBJECT everything associated with the HTTP client in those methods when I'm done. My HTTP headers are set to "close" as opposed to "keep-alive" and I'm at a loss as to why the agent threads are hanging around.
I have run the PKB's leakCheck.p and the only new objects in memory after calling one of my methods are several instances of OpenEdge.NET.HTTP.BuilderRegistry - I understand from a Communities post by Peter Judge that this is expected, and OK.
I understand that 11.7.5 and v12 have several fixes for memory leaks in the HTTP client that have not been fixed in 11.6, but I'm not aware of any problem - fixed or not - around threads getting stuck in 11.6.
Here is a code sample:
Code:
CLASS Interface.IF012-SharePoint FINAL:
METHOD PUBLIC STATIC VOID UploadFileFromMemory (INPUT pmFile AS MEMPTR,
INPUT pcSharePointFileName AS CHARACTER,
INPUT pcSharePointFileType AS CHARACTER,
INPUT plApplySuffix AS LOGICAL,
INPUT pcSite AS CHARACTER,
INPUT pcSharePointFolder AS CHARACTER,
OUTPUT pcMessage AS CHARACTER):
DEFINE VARIABLE oRequest AS IHttpRequest NO-UNDO.
DEFINE VARIABLE oRequestBody AS OpenEdge.Core.Memptr NO-UNDO.
DEFINE VARIABLE oResponse AS IHttpResponse NO-UNDO.
DEFINE VARIABLE cFile AS CHARACTER NO-UNDO.
DEFINE VARIABLE cTenantName AS CHARACTER NO-UNDO.
DEFINE VARIABLE cAccessToken AS CHARACTER NO-UNDO.
DEFINE VARIABLE cURI AS CHARACTER NO-UNDO.
/* Get the tenant name from Config */
Interface.IF012-SharePoint:GetConfigValue(INPUT "{&SharePointConfigItem}",
INPUT "TenantName",
OUTPUT cTenantName).
IF cTenantName = "" THEN DO:
pcMessage = "IF012-SharePoint:UploadFileFromMemory could not retrieve the tenant name from system config.".
RETURN.
END.
/* Get the auth token from Config */
Interface.IF012-SharePoint:GetAuthToken(OUTPUT cAccessToken,
OUTPUT pcMessage).
IF pcMessage <> "OK" THEN
RETURN.
IF GET-SIZE(pmfile) = 0 THEN DO:
pcMessage = "IF012-SharePoint:UploadFileFromMemory could not read the local file from memory.".
RETURN.
END.
/* If the user wants to use a suffix on the filename to avoid an existing file being overwritten,
we have to find out what the current highest suffix for the filename is, and increment it by one. */
IF plApplySuffix THEN
DO:
Interface.IF012-SharePoint:GetNextFreeFileName(INPUT pcSharePointFileName,
INPUT pcSharePointFileType,
INPUT pcSite,
INPUT pcSharePointFolder,
OUTPUT cFile,
OUTPUT pcMessage).
IF pcMessage <> "OK" THEN RETURN.
END.
ELSE cFile = pcSharePointFileName + "." + pcSharePointFileType.
oRequestBody = NEW OpenEdge.Core.Memptr(pmFile).
CASE pcSite:
WHEN "" then
cURI = SUBSTITUTE("https://&1.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('&2')/files/add(url='&3',overwrite=true)",
cTenantName,
pcSharePointFolder,
cFile).
OTHERWISE
cURI = SUBSTITUTE("https://&1.sharepoint.com/sites/&2/_api/web/GetFolderByServerRelativeUrl('&3')/files/add(url='&4',overwrite=true)",
cTenantName,
pcSite,
pcSharePointFolder,
cFile).
END CASE.
oRequest = RequestBuilder:Post(cURI, oRequestBody)
:AcceptJson()
:AddHeader("Connection", "close")
:AddHeader("Authorization", cAccessToken)
:HttpVersion("HTTP/1.1")
:Request.
oRequest:ContentType = "application/octet-stream".
oRequest:ContentLength = GET-SIZE(pmFile).
oResponse = ClientBuilder:Build():Client:Execute(oRequest).
IF oResponse:StatusCode = INTEGER(OpenEdge.Net.HTTP.StatusCodeEnum:OK) THEN
pcMessage = "OK".
ELSE
pcMessage = "IF012-SharePoint:UploadFileFromMemory was unable to upload a file to the SharePoint folder: " + cUri
+ CHR(10) + CHR(13)
+ CHR(10) + CHR(13)
+ "Status code: " + STRING(oResponse:StatusCode)
+ CHR(10) + CHR(13)
+ "Status reason: " + oResponse:StatusReason
+ CHR(10) + CHR(13).
FINALLY:
DELETE OBJECT oRequest NO-ERROR.
DELETE OBJECT oRequestBody NO-ERROR.
DELETE OBJECT oResponse NO-ERROR.
END FINALLY.
END METHOD.
END CLASS.
Invoked like this:
Code:
USING Interface.IF012-SharePoint.
IF012-SharePoint:UploadFileFromMemory
(input mPhoto,
input cfile,
input "jpg",
INPUT FALSE,
input cSharepointSite,
input cSharepointFolder,
output cMessage).
SET-SIZE(mPhoto) = 0.
Am I doing anything obviously wrong?
TIA
Tarby
Last edited: