Hi to all,

as probably all of ABAPers that touch UI5 for even the simplest (transactional) applications, I found some bottlenecks, one of them is the pessimistic object locking, which in ABAP is the standard way to deny multi-user changes of the same object at one time. I found only a little information about the possibilities here, so I managed to write this information to share with you and expect any corrections / improvements you find.

As the UI5 application is stateless by default, ABAP enqueue statement is meaningful only during the execution of the backend ICF handler methods. After the program flow, the session is closed and thereafter all locks in the server enqueue table are lost for the corresponding session. Stateful session is the concept that can be helpful for (mostly) desktop applications, built in UI5.

To try it, create an ICF handler in SICF transaction, create a handler class by implementing the IF_HTTP_EXTENSION interface and use this class as the ICF node handler. Create some call to the SAP backend using e.g. loadDataNew statement (but any ajax will do). In the ABAP class and it’s HANDLE_REQUEST method, write:

     server->set_session_stateful( stateful = if_http_server=>co_enabled ).

What this statement does is (surprisingly) keeping the session stateful. Ater this call was made, although the call is ended already, you can see that there is another connection in transaction SM04 as the HTTP session type. This means, that your handler is instantiated and it’s context is held in the memory for as long as the session is kept alive. Any ENQUEUE calls that are made till the session is closed are held in the ABAP enqueue table. Any parameters / attributes in the handler class you create / fill will be there unce you make another call from the UI5 application (for the particular session only).

So how to close the session:

  • wait for the session timeout – this can be set (to a lower value only according to the server default session) in SICF transaction for a particular node in it’s Service data tab,
  • close the session by another call to the SAP backend and using the statement server->set_session_stateful( stateful = if_http_server=>co_disabled ).

Of course, it is recommended not to rely on the internal mechanism of terminating the sessions, because you probably use too much resources of the server even those are not needed any more. A programmer in ABAP is often confrontated by a long-time duration of reports or processes, which would time-out once they are held in foreground (the same applies for example in a Webdynpro for ABAP application, which runs in portal – once the user does not touch the application, it time-outs). For this purpose – in webdynpro ABAP one would use the timer element. Here, in UI5, one of the solutions is using the jsWindow.setInterval( ) function, which could call a dummy method in SAP backend to prevent from time-outing.

Different approaches to stateful sessions

  • you can make the whole application stateful (which means you would make some initialization call to the SAP, creating the stateful session and closing it once the user logs off, or navigates somewhere else, or closes the window etc.),
  • make the application “hybrid” – meaning, it’s state is managed according to it’s context (once the user tries to lock an object, create the session, lock the object there using ENQUEUE and keep it locked until the situation changes – e.g. user switches to the processing of another object).

The design depends on the application itself and you should choose the most suitable for your scenario.

What in fact does the set_session_stateful( ) method?

It creates a response cookie in the handler class (and also sets some attributes for it’s own processing), which is sent to the browser. The name of the cookie is sap-contextid. The UI5 programmer does not really need to think about it, as the browser will make the next call using this cookie in the request header automatically. That is the way that SAP’s HTTP dispatcher is able to connect the (next) request to the specific user session, which provides him with the data that the programmer can buffer in his handler class. It also makes it possible to raise the use_count field of the locked objects in the same session (which you can check in the SM12 transaction).

Once the session is closed:

  • if it is closed by the server (session time-outed), the browser does not know this yet. The browser still sends the cookie in request header, but SAP framework does not find any corresponding context (session), so it creates a new one. Of course, any object locks and “buffered” data in the handler class are lost in this case,
  • if it is closed by the programmer (meaning, he / she called set_session_stateful( ) method to disable it, the cookie is deleted at client (in fact, it is sent to the client with the expiration in the past – browser evaluates this as the command to delete the cookie). Everything else applies here the same – system closes the session, locks for the session are lost (if there are still any). But the next time UI5 makes any calls to the backend, it does not send any cookie, so SAP is not confused with looking for any open sessions for that user.

And what about multi-connections from the same user?

It happens, that once an user runs the application from another instance of the browser, he / she would create a new instance at the server. As for the object blocking, this is the same as a new session in SAP GUI (and once the object is locked, the user would get a message, that the object is locked by himself). However, the user does not have to create a new instance, but he can create a new tab / window in the same browser instance. In this scenario, the application would send the same cookie request as the previous one (as the cookies are shared among the tabs). This means, different tabs would act as the same session.

This is where the “buffering” mechanism and the possibility to store values in the attributes of the handler class takes place. One of the solutions is to create an own “guid” once the application is initialized (either in SAP backend or in javascript of the app itself) – for every “tab”, or to say – for every instance of the application. Send this guid along all other form fields and let the backend decide. Once the application tries to lock the object, first compare, if the object is not locked already in the attribute of the handler class using a different guid. This ensures, that one user would not be able to change the same object in different tabs. If you would use only the ENQUEUE FM, you would raise the use_count of the object in the lock table sending no lock-errors, which could make trouble.

Please feel free to confront / add any information that would make the process event more transparent.

To report this post you need to login first.

10 Comments

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

    1. Jozef Vaclavek Post author

      This is our pilot project in UI5, which is a full customer development without any standard functionality behind it. The project is in testing for now, but probably will not be changed too much and will be used as such in production.

      A lot of work – yes, comparing to the classic ABAP transactions. And even comparing to Webdynpro, but the GUI responsibility is incomparable and in fact we did not find an easier solution – is there any?

      (0) 
      1. Krishna Kishor Kammaje

        By reading documentation, I see below options.

        Using WebSockets, you may just notify the other person changing the same object. I think this would satisfy most use cases.

        Or by using stateful web sockets, you may even recreate exact pessimistic locking. 

        (0) 
        1. Jozef Vaclavek Post author

          Hi, Krishna, thank you for you interest in this topic. The main purpose of the document was to find the best solution for locking of the objects SAP-like. So imagine you will have an user working in a (standard / customer) transaction in any SAP module.

          You would still want some feature to be available using UI5 technology. And you would want the transaction-like behaviour – so once anybody locks the object in the UI5 (mobile / cell / PC / web-service…) should lock the object for the user in SAP – so he / she can not change it.

          As I believe websockets are an interesting technology – simulating or behaving like a web-server. But once you build your applications upon an existing system (SAP), you probably can’t use it’s benefits. Or can you? You still need to lock the entry in SAP using the ENQUEUE functions.

          (0) 
  1. Francis Edward Borromeo

    Hi Josef,

    Thanks for sharing this step. I’ve implemented the session stateful and it already extends the session. however i am not able to disable the session I opened using the code

      server->set_session_stateful( stateful = if_http_server=>co_disabled ).

    the session still exists in SM04.

    (0) 
    1. Jozef Vaclavek Post author

      Hi, Francis,

      please check, whether you really have a http session there and you do not see the one you probably are developing in (e.g. SAPLogon). So in the column relation type (I do not know the exact English name) – you should / should not see HTTP (but you still can see GUI there).

      (0) 
      1. Francis Edward Borromeo

        Thanks for the reply Josef.

        I can see the HTTP session in SM04. I see the other session with my own SAPGUI login and another entry for the HTTP session since it has the terminal id/IP address with the type ‘Plugin HTTP’.

        I made separate ICF handlers: one for ‘open’ and another for ‘close’. what i saw during debug is that there are two sessions: one for the old session from the open service, and another for the current session from the close service. what i think happens is that the close service only closes the current session it is on and not the previous stateful session from the open service.

        I made it somehow now but not using the code for: set_session_stateful. I made a logic which gets the TID and terminal/ip add from the users currently logged in via FMs used in SM04 namely, TH_SERVER_LIST, TH_USER_LIST and delete the stateful session via TH_DELETE_USER. wondering how you made the code for server->set_session_stateful( stateful = if_http_server=>co_disabled ) work?


        Regards,


        Francis

        (0) 
        1. Jozef Vaclavek Post author

          Hi, it is exactly as you wrote – a different handler creates a separate session – I believe as far as it belongs to a different ICF node . So once you would like to use different handlers (classes) from different paths in icf, you will not be able to close the session you once opened. It works in my scenario because there is only one handler to do both tasks – and in fact this is the only one correct scenario that could work. The applications goes to the ICF node via a link. The dispatcher in ABAP stack looks for all open sessions with the same link / path and filters this with the cookie the browser provides. Using this approach it is possible to connect to the existing session with other asynchronou (AJAX) calls from the application.

          Of course, this can get much more complicated once you use the portal integration and start the applications in separate windows and your browser crashes and so on. But still, it is one way to do the stuff and the problems can be workarounded.

          (0) 
          1. Francis Edward Borromeo

            I see. I’ll try to make it work using only one class and ICF node/URL. you have some custom logic there i presume where it checks if the URL was accessed for an open or a close request? I noticed when I accessed the same URL it still uses the same terminal id for the session in SM04 though the time field is reset.

            i am thinking if I use the same ICF node/URL and just pass parameters (either for open or close) into it, this is assuming the statement stateful = if_http_server=>co_disabled will work.

            (0) 
            1. Jozef Vaclavek Post author

              In fact this is not a big deal. Simply the session expires once the icf node, which is handled using your abap class time-outs. That is what you will see in SM04.

              Session itself in the browser works different – as creating it using if_http_server=>co_enabled sets a response cookie to the browser. So every next request to the same domain (icf URL) is made using the cookie. And your application does not even have to know that, browser takes care.

              I do not have any special logic to pair the session with the url. Just try to create the session, store any value in the handler attribute and then create another call there. When you put a break-point there you will see that the attribute is set already.

              (0) 

Leave a Reply