Skip to Content

Hello,

I would like to share the idea how you can manage or kill the session of your Soft State OData Service.

For more information regarding Soft State Support for OData Services look here: http://help.sap.com/saphelp_gateway20sp09/helpdata/en/f6/5f8e5318e83d27e10000000a44538d/content.htm

and here:

http://scn.sap.com/docs/DOC-58760.

As discussed, you will probably implement Stateful or Soft State OData in the applications, where you can gain a lot from this. This can be any application, which is continuously working with considerable amount of data. Typical example would be taking an order with many items and complex pricing or very complex and flexible reports, which are working with the data stored in the memory. By default, your session will timeout according to the settings you set up for your service in the transaction SICF.

Now it comes a tricky question, how big should this timeout be? 1 hour or maybe 1 second? You’llsay, depends on the application. Yes, true. But, isn’t it better to make it manageable?

Imagine in your order taking application you have simply forgotten, or maybe it is just not possible, to release the memory after the order is finished. Your memory will be leaking, right? Even closing the browser will not help. You will see more and more pending sessions in SM04 (AL08) transaction, consuming more and more memory of your system.

SM04.jpg

Below I will describe one way how you can close the Soft State OData session programmatically.

First, what you need to know that it is possible to kill this session right from transaction SM04. Therefore, we will simulate exactly this step.

You can get the session information using CL_SERVER_INFO => GET_SESSION_LIST. After that, you will need to call the function TH_DELETE_USER to kill this session. Let’s to a simple function, where the input parameter would be a path to the OData service.

function zdmsh_delete_odata_session.
 
*”———————————————————————-
 
*”*”Local Interface:
 
*”  IMPORTING
 
*”     VALUE(IV_PATH) TYPE  STRING
 
*”———————————————————————-
 
   
include: tskhincl.
 
   
data: server_info  type ref to cl_server_info.
 
   
data(lv_path) = iv_path.
   
translate lv_path to upper case.
 
   
try.
       
create object server_info.
 
       
data(session_list) = server_info->get_session_list( with_application_info = 1
                                                            tenant
= symandt ).
 
       
loop at session_list assigning fieldsymbol(<fs_session_info>)
         
where user_name  = syuname
           
and logon_type = 3
           
and logon_sub_type = 4
           
and act_program = ‘SAPMHTTP’.
 
         
translate <fs_session_info>application_info to upper case.
 
         
if <fs_session_info>application_info cs lv_path.
 
           
call function ‘TH_DELETE_USER’
             
exporting
                user           
= syuname
               
client          = symandt
                tid            
= <fs_session_info>logon_hdl
                logon_id       
= <fs_session_info>logon_id
             
exceptions
                authority_error
= 1
               
others          = 2.
           
if sysubrc <> 0.
             
continue.
           
endif.
         
endif.
       
endloop.
 
     
catch cx_root.
       
exit.
   
endtry.
 
 
endfunction.

Then you need to call this function somehow. In my case, the function TH_DELETE_USER does not work if I call it from the same session, which I am trying to kill. Don’t know why, but it was the case. Therefore, you need to call it from another session, which can be another OData service or simply a web-rfc function.

I used the last option. For more information regarding web-rfc, see here: http://scn.sap.com/community/netweaver-as/blog/2012/08/07/webrfc–simply-calling-an-rfc-from-javascript

So, the function looks very simple.

function zdmsh_delete_user_webrfc.
 
*”———————————————————————-
 
*”*”Local Interface:
 
*”  TABLES
 
*”      QUERY_STRING STRUCTURE  W3QUERY
 
*”      HTML STRUCTURE  W3HTML
 
*”      MIME STRUCTURE  W3MIME
 
*”  CHANGING
 
*”     REFERENCE(CONTENT_TYPE) TYPE  W3PARAM-CONT_TYPE DEFAULT
 
*”       ‘application/json
 
*”     REFERENCE(CONTENT_LENGTH) TYPE  W3PARAM-CONT_LEN
 
*”     REFERENCE(RETURN_CODE) TYPE  W3PARAM-RET_CODE
 
*”———————————————————————-
 
   
data: path type string.
   
data: rc type numc5.
 
   
sort query_string descending.
   
read table query_string with key name = ‘_OdataSrv.
 
    path
= query_stringvalue.
 
   
call function ‘ZDMSH_DELETE_ODATA_SESSION’
     
exporting
        iv_path
= path
     
importing
        rc     
= rc.
 
   
data: htmldoc like line of html.
 
   
concatenate ‘{“results”: [ {“key”: “path”, “value”: “‘ path ‘”},’
                            
‘ {“key”: “error”, “value”: “‘ rc ‘”}]}’ into htmldocline.
 
   
insert htmldoc into table html.
 
 
endfunction.

After that, you just need to call it via the URL: http://<server>:<port>//sap/bc/webrfc?_FUNCTION=<FUNC_NAME>&_OdataSrv=<SERVICE_PATH>

At last, you need to create a JavaScript function and attach it to proper event (e.g. window.onbeforeunload / window.addEventListener) or a button. From there you can call the above URL, for instance as AJAX request.

Hope it was useful.

If you find any mistake or a bug, or have a better solution, do not hesitate to comment it cout.

BR, Dima

To report this post you need to login first.

3 Comments

You must be Logged on to comment or reply to a post.

  1. Vladislav Volodin

    There is the ICF service /default_host/sap/public/bc/icf/logoff that should also logoff the user.

    Does it do a different thing than you described in the article?

    For others, I would recommend to take a look at the article on SO telling how to deal with window.onbeforeunload event handler. It is quite tricky to send the request when the user closes the window.

    Maybe it would be better to have a short session timeout, but always extend it with asynchronous requests (e.g. http://…/default_host/sap/bc/ping).

    (0) 
    1. Dmitrii Sharshatkin Post author

      Hello Vlad,

      That’s great that you have mentioned a way to logoff from ICF. I just tested it and found the following difference. If i run /icf/logoff it will kill all the session which are currently opened in the browser. If you have several Apps or IC Web Client + ITS + Apps, then all of them will be killed. I tried to manipulate with propagateLogoff and  keepMYSAPSSO2Cookie but the behavior did not change in fact. Only  redirectURL worked as desired. But in most of the cases /icf/logoff shoul work, right? Also you can do automatic redirection.

      So my proposal is capable to work more precise as it keeps 3d-party sessions.

      Thanks for your proposal!

      BR, Dima

      (0) 

Leave a Reply