In Retrospect, It Was Pretty Easy to Leak Resources
Contents
Since ABAP has garbage collection, most of the time just clearing references is enough to dispose of resources. Sometimes, however, a close( )
call is also required.
HTTP Connections
Transaction SM59
allows HTTP connections to be configured:

SM59 - Technical Settings
The proxy settings are obviously handy, but especially nice is the option for configuring logon credentials:

SM59 - Logon & Security
This removes the responsibility of handling sensitive credentials in ABAP code:
|
|
Anyone with experience using HTTP APIs will notice one shortcoming: there’s no support for any other method of authorization than basic authorization. So if the endpoint requires a bearer token or a custom HTTP header, SM59
logon settings are not much use to us.
This requirement for other methods of authorizations was exactly the case with a couple different developments required by a customer. My solution, along the lines of dependency injection, was to create a small service from which clients could request REST clients:
|
|
This service hid any authorization -related concerns from clients. Thus, after the service instance had been created with the required configuration in place, it could just be injected into clients that needed to access external HTTP servers. This injection also allowed those clients to be unit testable by mocking the HTTP client service and the REST clients it produced.
Out of Memory
Everything worked fine for a while, until a mysterious error message started to appear:

No memory for processing HTTP, HTTPS, or SMTP query
We dealt with requests and responses that carried fairly small amounts of text data, so I was confused as to how an SAP Application Server could ever run out of memory with our usage. Turns out that the content was not the problem, but the number of HTTP clients we were creating.
My ZIF_REST_CLIENT_SERVICE
created a new IF_HTTP_CLIENT
instance for each HTTP request. IF_HTTP_CLIENT
’s existence, however, is special: if it has been used in a HTTP call, it’s not enough to just clear references to it. To free all resources associated with it, close( )
needs to also be called.
In my defense, I’d like to direct the jury to the description of the close( )
method:

IF_HTTP_CLIENT methods
To me the description reads more like it is intended for closing a connection before the response has been received. Even the documentation of the whole interface does not mention the special role of the close( )
method. Only the longer documentation for the method spells it out clearly:

close( ) method documentation
Adding close( )
calls to properly free resources got rid of the out of memory error messages, but this was the first case I encountered where garbage collection was not enough to get rid of ABAP objects. The ambiguous/non-specific error message was also not especially helpful in resolving the issue.
Guidelines / Consistency
Ultimately the question we’re left with is “how to make APIs hard to misuse”. Because ABAP objects only rarely need to be disposed of in an explicit manner, there are little if any established hints as to when this should take place. In IF_HTTP_CLIENT
the special discard method is called close( )
and described as Close of HTTP connection
; in GUI-related objects it is free( )
with description Destructor
. I’d argue that the latter is a stronger signal as to the special nature of the method. But in CL_GUI_ALV_GRID
, free( )
is just one among 400 other methods, 90 of which are public. Only the fact that all GUI-related objects have (or rather, inherit) the free( )
method establishes it as special. For IF_HTTP_CLIENT
, no such family of related classes and thus no such established consistency, exist.
One option might be to have a global interface somewhat like IDisposable
in C# that would act as a signal that the object needs to be explicitly disposed of.
Destructors don’t exist in ABAP, and might not even be good enough if the garbage collection did not execute between HTTP calls.