UPDATED! Stateful BSP Applications: New State Management Option
Introduction
Using stateful BSP applications poses an obvious problem: how do we remove the server state for browser based application. If the user navigates outside of our application or shuts down their browser, our server state remains, consuming valuable system resources. For a while now BSP programmers have had the option of routing the start of their applications through a copy of a one of two pages in the SYSTEM BSP Application.
We have the pages session_single_frame.htm and session_buffered_frame.htm. Single Frame can be used under normal conditions and buffered frame is used for when your application uses delta handling. These pages show you how you can load your application into a frame. You then register a JavaScript function to fire on the OnUnLoad event of this fameset. This JavaScript function then launches a popup window that will clear up your applications current server state.
The Problem
If you have tried this solution, then you know that it works reasonable well under most situations. So what is the problem? First it uses a popup window. To most end users, popup windows that fire without their triggering an action are as bad as SPAM. The situation has become so serious, that we have popup blockers being built into just about every internet browser. Before you know it, you have some user who doesn’t know how to set a popup exception calling your support desk wanting to know why the record he was working on before break says that he still has it locked. I have even seen an Internet Explorer Patch that broke IE’s ability to render output into the popup. You end up with a nice empty popup window and a mountain of dead stateful sessions back on your server. Let’s just say that the day that patch rolled out, we had lots of grouchy support desk technicians.
The Solution
Well now that my name is mud with the local support desk, what can I do to redeem myself. Lucky SAP has come to the rescue with a new solution to the state management problem. An example of this new solution is available in BSP application ITSM as of 620 SP44 or 640 (not sure what SP it introduced in for 640 – however it is there in SP9). Now don’t fret if you aren’t quite at the latest support package. Most of the functionality in this solution is JavaScript. I was able to get the coding from a 640 sandbox system and then successfully use it in our 620 SP42 system. The only thing I can tell you is to give it a try and see what happens.
The main difference between the two solutions is that the new one doesn’t rely on popup boxes to destroy the session state. Instead it uses some special functionality built into the ICM to close the session. The following is an explanation of how the ICM works to accomplish this that Brian McKellar shared a while back in a related subject. I will just quote him here again, since he explains it better than I ever could.
The ICM supports a sap-sessioncmd=CANCEL mode. With this, the session is killed by ICM, and then the incoming URL is still processed inside a new session. We just require an URL that looks exactly like the application URL in the part up to the name of the application, so that the session id cookie will be send with it. After ICM has cancelled the session, the URL will still be processed. So we require an URL that will be processed by the BSP runtime without any problems (and without opening a new session!). For this, we just use a special 1×1 URL. The BSP runtime has a performance improvement that will always reply with a 1×1.gif for an incoming URL of the format “…/1×1”. However, this 1×1 image is cached, and the trick will only work once. So we just add one timestamp to make the URL unique for the browser, and have it trigger the loading of the 1×1 image.</p>
This solution as explained is very much what makes up the new logon session management. What SAP does is in JavaScript is create an Image that refers to the 1×1.gif but also passes on the URL the Context ID and the Session Command CANCEL. The following are those two lines of JavaScript:</p>
<textarea rows=”4″ cols=”79″>
img=new Image;
img.src = document.location.href+”/1×1.gif?sap-contextid=<%=
cl_http_utility=>escape_url( runtime->server->session_id ) %>
&sap-sessioncmd=CANCEL”;
</textarea></p>
<STRONG><FONT size=3>The Sample</FONT></STRONG><br>
Incase you don’t have the required support package level to see the example in ITSM, the following is a sample page that uses this solution:</p>
<textarea rows=”10″ cols=”79″>
<%@page language=”abap” %>
<%@extension name=”htmlb” prefix=”htmlb” %>
<%@extension name=”xhtmlb” prefix=”xhtmlb” %>
<%@extension name=”phtmlb” prefix=”phtmlb” %>
<%
” Copy this page into your BSP application, and change line below.
” This page should always used be as entry point into application.
DATA: target_page TYPE STRING VALUE ‘index.do’.
DATA: frame type string.
frame = sy-uzeit.
%>
<script language=”JavaScript”>
<%= runtime->GET_DOMAIN_RELAX_SCRIPT( ) %>
// Delete the cookie with the specified name.
function DelSso2Cookie(sName,sPath)
{
var sso2Domain = location.hostname;
if (location.hostname.indexOf(“.”)>0)
sso2Domain = location.hostname.substr(location.hostname.indexOf(“.”)+1);
p=””;
if(sPath)p=” path=”sPath“;”;
document.cookie = sName“=0; expires=Fri, 31 Dec 1999 23:59:59 GMT;”p + “domain=”sso2Domain“;”;
}
function exitBSPApplication(newTargetUrl)
{
<%
if runtime->session_manager->is_running = 0.
%>
img=new Image;
img.src = document.location.href+”/1×1.gif?sap-contextid=<%= cl_http_utility=>escape_url( runtime->server->session_id ) %>&sap-sessioncmd=CANCEL”;
<%
” If you want to destroy the SSO2 cookie along with the server session,
” please uncomment the function below
%>
//DelSso2Cookie(“MYSAPSSO2″,”/”);
for(i=0;i<5000;i++)for(e in document.all) tmp=e.innerHTML;
<%
endif.
%>
document.getElementById(“<%= frame %>_FRAMESET”).onunload = null;
if(newTargetUrl) window.setTimeout(‘{document.location.href=”‘newTargetUrl‘”;}’, 750);
}
0)`
`sso2Domain = location.hostname.substr(location.hostname.indexOf(“.”)+1);`
`p=””;`
`if(sPath)p=” path=”sPath“;”;`
`document.cookie = sName“=0; expires=Fri, 31 Dec 1999 23:59:59 GMT;”p + “domain=”sso2Domain“;”;`
`}`
into html.
****Begin Exit Function
concatenate html
`function exitBSPApplication(newTargetUrl)`
`{`
into html.
****Log Off Action
if mc_runtime->session_manager->is_running = 0.
data: context_id type string.
data: session_id type string.
session_id = mc_runtime->server->session_id.
context_id = cl_http_utility=>escape_url( session_id ).
concatenate html
`img=new Image;`
`img.src = document.location.href+”/1×1.gif?sap-contextid=`
context_id
`&sap-sessioncmd=CANCEL”;`
into html.
****Delete SSO2 Cookie?
if destroysso2cookie = abap_true.
concatenate html
`DelSso2Cookie(“MYSAPSSO2″,”/”);`
into html.
endif.
concatenate html
`for(i=0;i<5000;i++)for(e in document.all) tmp=e.innerHTML;`
into html.
endif.
****Build the Frame
concatenate html
`document.getElementById(“`
frame
`_FRAMESET”).onunload = null;`
`if(newTargetUrl) window.setTimeout(‘{document.location.href=”‘newTargetUrl‘”;}’, 750);`
`}`
“
into html.
****Display the FrameSets
concatenate html
“
`
Hi,<br/> I am using the same code that you had specified in the Sample code section . Here below is that piece of code that I am using still i am getting the Pop-up box and still the session is hanging if I use the Pop-up blocker in the browser:<br/><br/><%@page language="abap" %><br/><%@extension name="htmlb" prefix="htmlb" %><br/><%@extension name="xhtmlb" prefix="xhtmlb" %><br/><%@extension name="phtmlb" prefix="phtmlb" %><br/><%<br/> " Copy this page into your BSP application, and change line below.<br/> " This page should always used be as entry point into application.<br/> DATA: target_page TYPE STRING VALUE 'source.do'.<br/> DATA: frame type string.<br/> frame = sy-uzeit.<br/>%><br/><html><br/> <script language="JavaScript"><br/> <%= runtime->GET_DOMAIN_RELAX_SCRIPT( ) %><br/> // Delete the cookie with the specified name.<br/> function DelSso2Cookie(sName,sPath)<br/> {<br/> var sso2Domain = location.hostname;<br/> if (location.hostname.indexOf(".")>0)<br/> sso2Domain = location.hostname.substr(location.hostname.indexOf(".")1);<br/> p="";<br/> if(sPath)p=" path="sPath";";<br/> document.cookie = sName"=0; expires=Fri, 31 Dec 1999 23:59:59 GMT;"+p + "domain="sso2Domain";";<br/> }<br/> function exitBSPApplication(newTargetUrl)<br/> {<br/><%<br/> if runtime->session_manager->is_running = 0.<br/>%><br/>img=new Image;<br/>img.src = document.location.href"/1x1.gif?sap-contextid=<%= cl_http_utility=>escape_url( runtime->server->session_id ) %>&sap-sessioncmd=CANCEL";<br/><%<br/> " If you want to destroy the SSO2 cookie along with the server session,<br/> " please uncomment the function below<br/>%><br/>//DelSso2Cookie("MYSAPSSO2","/");<br/>for(i=0;i<5000;i)for(e in document.all) tmp=e.innerHTML;<br/><%<br/> endif.<br/>%><br/> document.getElementById("<%= frame %>_FRAMESET").onunload = null;<br/> if(newTargetUrl) window.setTimeout('{document.location.href="'newTargetUrl+'";}', 750);
}
any suggestion why??.
we have following SP's applied in our system:
SAP_BASIS 620 0043 SAPKB62043SAP
Basis Component SAP_ABA 620 0043 Cross-
Application ComponentSAP_APPL 470 0021
Logistics and AccountingSAP_HR 470 0028
Human ResourcesABA_PLUS 100 0010
Thanks in advance.
Thanks,
Greetson
The examples you and Brian McKellar provide are excellent. The only problem that still remains is getting the process to work when running the BSP's through the Portal.
We have tried both ways and outside the portal they work fine. Once we call the BSP's through the portal, only the main BSP gets terminated, the other BSP's called by the main one remain open.
Any suggestions?
Thanks,
Johnny
Can you plesae send me the code(entry page .htm one) that you had implemented in your BSP .
Thanks in Advance.
Thanks,
Greetson
The examples you and Brian McKellar provide are excellent.
The only problem that remains is getting this to work when you execute the BSP's through the portal.
We have tried both options and found that all sessions are closed only when running the BSP's outside the portal. When you run it through the portal, only the main BSP is closed correctly. The BSP called by the main one remains open.
Any suggestions?
I am trying to trouble-shoot a "strange" problem we are having with a BSP application running from our portal. I see you mentioned that "strange" things may happen if you try handling session states in the BSP as well as from the portal itself. We have a situation (that we cannot duplicate) where a user's appraisal gets updated with the values from their subordinate's appraisal. We don't see this as being an application logic error.
We are at a loss and thought I would bounce this off you.
Regards,
Calvin
I am trying to trouble-shoot a "strange" problem we are having with a BSP application running from our portal. I see you mentioned that "strange" things may happen if you try handling session states in the BSP as well as from the portal itself. We have a situation (that we cannot duplicate) where a user's appraisal gets updated with the values from their subordinate's appraisal. We don't see this as being an application logic error.
We are at a loss and thought I would bounce this off you.
Regards,
Calvin
Hi Thomas!<br/><br/>Our system in on WAS 6.20 SP 34 (BASIS and ABA).<br/>Your sample page works really fine, thanks for that!<br/><br/>I also tried the BSP Extension way. But this run to errors. The first I could solve:<br/>- My BSP Extension (called zni) had no BSP Element Basis Class. After I filled this field with CL_BSP_ELEMENT (like in htmlb and the others) the syntax errors disappeared.<br/><br/>But the second problem I cannot solve:<br/>- When executing a page with the <zni:sessionLoader> an exception CX_SY_REF_IS_INITIAL is thrown. The point is at the call of mc_runtime:<br/><br/> relax_script = mc_runtime->get_domain_relax_script( ).<br/><br/>In debugger I can see that mc_runtime is initial. Is there something missing or is our SP34 the problem??<br/><br/>Hope for help!<br/><br/>Regards,<br/>Mathias<br/>
I was able to recreate the problem in my system SP42 when I didn't surround my extension with the htmlb:content tag.<br/><br/>Problem:<br/><%@page language="abap" %><br/><%@extension name="htmlb" prefix="htmlb" %><br/><%@extension name="ZKEG" prefix="ZKEG" %><br/><%-- <htmlb:content design="DESIGN2003" ><br/> <htmlb:document><br/> <htmlb:documentHead>
%><br/><ZKEG:sessionLoader TargetPage="index.do" /><br/><%</htmlb:documentHead><br/> </htmlb:document><br/> </htmlb:content> --%><br/><br/>Works Fine:<br/><%@page language="abap" %><br/><%@extension name="htmlb" prefix="htmlb" %><br/><%@extension name="ZKEG" prefix="ZKEG" %><br/><htmlb:content design="DESIGN2003" ><br/> <htmlb:document><br/> <htmlb:documentHead><br/> <ZKEG:sessionLoader TargetPage="index.do" /><br/> </htmlb:documentHead><br/> </htmlb:document><br/></htmlb:content>Yep, that's it!Mathias
Just to know:
if you work with firefox and you just close the Tab where BSP is running, the session is not deleted.
If you close the firefox window it works.
Sergio
On a side note, as I tested with Firefox I had to remove my htmlb:content tag from my hosting page. I then got dumps because me->mc_runtime was initial. If anyone runs into this problem, it can be fixed by adding the following code to the beginning of the DO_AT_BEGINNING method.
IF me->mc_runtime IS INITIAL.
me->mc_runtime = m_page_context->get_runtime( ).
ENDIF.
You can say to firefox to present itself as IE 6 o NN7..
Have also a look in the BSP Forum the the thread titled "Browsers different from IE 6 and NN 7 produce dumps with DESIGN2003"
Sergio
When you add a page attribute to the default.htm page and you put code in the Oninitialization handler of this page to put the value of the parameter in an attribute of the application class, sessions will not be killed anymore when the parameter is used in the URL.
Is there a solution for this problem?
Just off the cuff, you might be able to create a single stateless page that actually accepts the URL parameters. This page could then write the values into a Server Cookie and then redirect you to the Default page (which is then stateful from that point forward). You could have a little rountine in Default to load these values from the Server Cookie and into your application class. I will have to play with this a little however.
Let me know if you need any additional info from me.
Thanks,
Sarah
In a stateful BSP, When a user clicks on the same URL as the one used for the current session, a new transaction lock is created, and exists right up to the point where call_view is executed, then he lock disappears.
The session handling is correctly executed for the old session.
The bsp is being called from the crm webclient.
Your comments appreciated.