Monday, July 04, 2016

APEX session isolation across multiple browser tabs - Problem Solved (in APEX 5.1)

Since the genesis of Oracle Application Express, customers have asked for a way to open multiple browser tabs (or windows) of an APEX application and have the session state isolated between the respective tabs.  There is one and only one APEX session associated with a client, and because of this behavior in APEX, customers would find that the session state manipulated in one browser tab would collide with the session state of the other browser tab.

This has always been a vexing problem to solve for many years.  Back in 2007, I remember Carl Backstrom had spent countless hours researching for some handle or unique identifier to a browser window that we could correlate with a distinct browser session cookie, but he was never able to identify a feasible solution.  Customers have long asked for a solution, but all we were able to propose were rather cumbersome work arounds (ensure all items necessary for session state were posted with the page, or use the multiple DNS aliases "trick" for each tab).

In October 2015, our friends from BiLog arranged an informal meeting with a couple large enterprise customers from Croatia.  Goran, who was from one of the enterprise customers in the insurance industry, stated that the session management behavior of APEX presented a real problem for them.  Their typical scenario involved a sales representative who would meet with a customer in-person.  Because they wanted to offer insurance quotes or initiate insurance applications on multiple products, the sales representative would open up multiple tabs of their APEX application.  Of course, the session state across all of these tabs would collide and effectively corrupt the quoting process.  As Goran stated at the time, it became more and more difficult to justify the use of APEX because of this troublesome behavior.  I had no immediate answer, but I told him we would redouble our efforts and look at this problem again.

In February of this year, I had one of those lightbulb moments, and realized that we had been thinking about this problem the wrong way, and we needed to turn it inside out.  In APEX, there is always a single browser session cookie associated with an APEX session.  We were always trying to come up with a way to generate a new and differentiated browser session cookie every time a new tab was opened, and then associate this new browser session cookie with a new APEX session.  But the new approach was to simply keep the one and only one browser session cookie, and have this associated with multiple APEX sessions on the server.  I expressed my idea to the supremely intelligent Christian Neumueller of the APEX development team, and he went about with a masterful design and implementation of this feature.

In Application Express 5.1, we are introducing a new request to the APEX engine named APEX_CLONE_SESSION.  When requested from an existing APEX session, this will generate a new APEX session identifier and associate it with the existing browser session cookie.  Additionally, it will copy all of the session state values from the old session to the new session.  You, the developer, would have to provide a link for your end users to open up new browser tabs, and include APEX_CLONE_SESSION in the request of the URL.  So instead of your end users manually opening up a new tab from your APEX application, you would have to give them a prescribed way to open new tabs - could be a dynamic action or a button or a link.  The URL in the new tab should include APEX_CLONE_SESSION in the "Request" portion of the APEX URL.

An example URL would be:
f?p=&APP_ID.:&APP_PAGE_ID.:&APP_SESSION.:APEX_CLONE_SESSION

Because we were a bit paranoid about this feature until we could thoroughly vet the security of it, by default, this capability is turned off.  You can override this setting for a specific workspace by using the Administration API:

apex_instance_admin.set_workspace_parameter(
    p_workspace => 'JOELS_WORKSPACE',
    p_parameter => 'CLONE_SESSION_ENABLED',
    p_value     => 'Y');

or you can enable it for the entire instance using:
apex_instance_admin.set_parameter(
    p_parameter => 'CLONE_SESSION_ENABLED',
    p_value     => 'Y');

This feature is enabled instance-wide on the Application Express 5.1 Early Adopter site at https://apexea.oracle.com.  We would welcome your feedback about this feature.  And if you're reading this blog post after APEX 5.1 is generally available, please feel free to try it in your own APEX 5.1 (or later) instance or on https://apex.oracle.com.

Update March 27, 2017:  In the production release of APEX 5.1, there is no workspace parameter for CLONE_SESSION_ENABLED.  It can only be enabled/disabled at the instance-level and not on an individual workspace basis.

17 comments:

  1. Really good news and glad to have the confirmation following the reveal at Kscope16

    ReplyDelete
  2. Hi Joel,
    what happens if I open a link containing APEX_CLONE_SESSION when no other Apex session currently exists?

    For instance, imagine you have two or three apex pages embedded inside a single HTML page using EMBED and each of these embedded pages contains APEX_CLONE_SESSION in the URL.

    Thank you
    Flavio

    ReplyDelete
  3. Hi Flavio,

    This scenario will be no different than the "session doesn't exist" flow.

    However, given the scenario you describe, it doesn't sound like "clone session" is desirable. I think it would be preferable to have "session joining" established for the application. This way, it doesn't matter which link you use into the application, once a session is established, the other links will be able to "attach" to that existing session.

    Joel

    ReplyDelete
  4. Hi Joel

    Can you tell us how sesson timeout and session expiry work for multiple clone sessions.

    Is session timeout per clone session, or for the cookie session?
    Session expiry would logically (to me) apply to the cookie session.

    Mark

    ReplyDelete
  5. Hi Joel,
    Will this work when using the builder such that I could have the app builder open and the sql workshop open and using both?

    regards,
    Jason

    ReplyDelete
  6. Hi Mark - I believe when one session times out, then all sessions will be extinguished. They won't extend into perpetuity. But the idle time will be a function of the activity of sessions correlated to the one browser session cookie. If one logs out, then all are effectively logged out.

    Hi Jason - good question. I haven't tried it. But using your example, you can use the App Builder and SQL Workshop *today* without worrying about any collision of separate state. App Builder and SQL Workshop are distinct applications, under the hood.

    Joel

    ReplyDelete
  7. Good point so i'd revise it to be could we potentially develop 2 pages at once in the builder.

    ReplyDelete
  8. Good point so i'd revise it to be could we potentially develop 2 pages at once in the builder.

    ReplyDelete
  9. Jason - I confirmed with Dr. Neumueller. For now, you won't be able to clone session with the Application Builder (or any "internal" applications).

    ReplyDelete
  10. We have lots of master-detail forms, connected with anchor e.g. in reports. In request-way we have to add request in each anchor and every single page-opening will copy session. User opens product list and open / compare / process multiple products with middle-click on anchors - it is common way in web-applications. But if the user open only one product, why we should clone session? Two different links is not an option. We can't prohibit user's opportunity to open Anchor in new tab using common browser feature.

    Moreover, what about collections? If you copy all stuff with the session, consistency of the collection will be broken. Collection sometimes is used as a Session-alive array, that catches some changes in application. If such a collection is copied, it misses changes from "different tab".

    Multiple page launch in our application is handled with special "instance"-item, that will be passed with each submit or get request. Special process restores separately stored item values via special process. But such way is a pain and unexpected behavior of items handling.

    ReplyDelete
  11. Hi Joel

    Can you commit or reject is this function exist in final vesrion ?

    ReplyDelete
  12. Hi Andrzej,

    This functionality is in production APEX 5.1.

    Joel

    ReplyDelete
  13. Hi Joel,

    I just tested this and was not able to allow session cloning for a single workspace.

    The workspace was recently upgraded from Apex 5.0 to Apex 5.1.

    begin
    apex_instance_admin.set_workspace_parameter(
    p_workspace => 'MYWORKSPACENAME',
    p_parameter => 'CLONE_SESSION_ENABLED',
    p_value => 'Y');
    end;
    /

    ORA-20987: APEX - Instance parameter not found - Contact your application administrator.
    ORA-06512: at "APEX_050100.WWV_FLOW_ERROR", line 1028
    ORA-06512: at "APEX_050100.WWV_FLOW_ERROR", line 1395
    ORA-06512: at "APEX_050100.WWV_FLOW_INSTANCE_ADMIN", line 678
    ORA-06512: at line 2

    This is somewhat consitent with the documentation for the set_workspace_parameter procedure. The CLONE_SESSION_ENABLED is not mentioned there in the available parameter list.

    However enabling it at instance level seemed to work.

    begin
    apex_instance_admin.set_parameter(
    p_parameter => 'CLONE_SESSION_ENABLED',
    p_value => 'Y');
    end;
    /

    PL/SQL procedure successfully completed.

    Although for set_parameter there the doc also misses this CLONE_SESSION_ENABLED parameter.

    But first tests showed that the session cloning works very well now.

    Regards and keep up the good work
    Sven

    ReplyDelete
  14. Hello Joel,
    Thanks for adding this critical feature. I enabled session cloning a few days ago, but users started complaining that after applying changes and going to the IR page, all the filters of the IR are reset.
    I understand that this is the expected results of cloning the session. But, as you know, what matters is the end-user. So, is there any workaround for this? Or this is the cost the user has to bare? Or am I missing something here?

    ReplyDelete
  15. Hi Fateh,

    This is a deficiency in the implementation. Today, in APEX 18.1, the clone operation will not clone the in-session reports for Interactive Reports nor Interactive Grids. Bug 28061001 is filed to address this (hopefully in a forthcoming patch set).

    Joel

    ReplyDelete
  16. Hi Joel,

    We've been using this extremely useful feature for some time but I recently had some users reporting occasional issues with dialog page cannot be rendered successfully errors after enabling rejoin sessions. After some investigating, I've noticed that after navigating the clone and original session are now ending up with the same session id, which I'm guessing is the cause of these errors. Are rejoin sessions and clone session mutually exclusive?

    Thanks,
    Richard

    ReplyDelete
  17. Hi Richard,

    Sorry, but you're correct. Rejoin sessions cannot be used in conjunction with Session Cloning. It's not practical for the two to ever work together.

    Joel

    ReplyDelete