Problem Description
The BSP runtime itself does not do any session handling. If a BSP application is stateful, then the application itself must provide session management code that will cleanup the session on the server when the application is terminated. However, once the BSP application is run inside SAP's Enterprise Portal (EP6), then the BSP application can request that EP6 manage the session. This means that each time an application switch is triggered within the portal, or a logoff is triggered from the portal, that the BSP application will be terminated and that session will be closed on the backend. This section describes troubleshooting guidelines when the sessions are not closed. One way that the problem can be verified, is to use transaction SM04
to see whether the HTTP session for the specific user is removed when the application is terminated in the portal. Another typical variation on this problem is the message that specific objects which should be edited, are locked by yourself. These locks are typically been held by a BSP application that is not active anymore, but which still has an open session on the backend. A typical example of such a message is: "The Business Partner XYZ is currently locked by you" ("Der Geschäftspartner XYZ ist zur Zeit von Ihnen gesperrt").
On the backend, two interesting transactions can be used to verify that this problem occurs.
SM04 | Lists all open sessions. BSP sessions will have type = HTTP. |
---|---|
SM12 | Lists all locks that are currently set. |
Once a BSP application is closed, it should not be listed in SM04, and no locks should be held in SM12. The rest of this page describes different reasons that cause this problems, and troubleshooting steps to follow to see if the specific reason is relevant.
Is Session Management Activated?
By default, BSP does not activate any form of session management. This must be explicitly required by the application. As first step, verify that the application did actually request session management.
- Start transaction SE80
- Select "BSP Applications"
- Enter name of the application
- Double-Click on the root node
- Select the Properties tab
- Check and verify that both checkboxes are set
The Stateful checkbox states that the application should be run stateful. Only stateful applications will keep open sessions on the application server. Note that it is technically possible for a BSP application to not have this checkbox set, and to set the state programmatically with ABAP source code. However, our experience is that in nearly 99% of the cases this checkbox is set, and if not set it is usually a part of the problem.
The Support Portal Integration checkbox is the most important one. It tells the BSP application that the specific application requests that the EP6 will handle the session management. Important: The EP6 session management is requested with this checkbox, and does NOT in any way depend, nor check, that the BSP application actually runs in a portal or not.
When this checkbox triggers is that a small piece of JavaScript code is rendered out at the top of each page, to instruct the page to register itself with the Distributes Session Management (DSM) of EP6. A small section of the code typically emitted looks as follow:
function SAPCLT_SessInfo() { this.protocolVersion = "1.0"; this.sessUrl = "http://<host>.<domain>.<ext>:<port>/sap(bD1lbi==)/bc/bsp/sap/<app>/<page>"; this.GUSID = "SID:ANON:b20main_B20_21:zqPa5HSrBvljbAbfKmiUNkJK6GN3qdc8SUPUztx_-ATT"; this.lastSessCmd = ""; this.redirectURL = ""; this.dTimeout = "300 "; }
- To verify that this code is emitted, start the BSP application in the portal.
- Somewhere on the page, use the Right Mouse Button (RMB)
- In the browser context menu, select "View Source"
- Inside the source, verify that session management code is available (search for
SAPCLT_SessInfo
).
The most interesting bit of source is the this.sessUrl
variable, which is the termination URL that will be called by the portal.
Complex Proxy in Landscape?
The technique whereby the session management from EP6 of BSP applications work is that the BSP will be started with a specific URL which is generated by EP6, and will then register itself with the portal with a termination URL. This termination URL is generated on the server by the BSP runtime, and is usually the same as the startup URL.
Sometimes complex proxy landscapes are used whereby the browser will connect to a specific port on the proxy, but different port numbers are used on the application server. This port change is a typical security criteria to achieve a stronger DMZ (short for "demilitarized zone", a computer or small subnetwork that sits between a trusted internal network and an untrusted external network, usually Internet).
Let us assume a typical scenario where the proxy is listening on port 1080, and the server actually on port 8080 (which is not open on the firewall). Then the user will enter the URL http:// host.ext:1080/URL
in the browser. Note that the browser does NOT know anything about the proxy. The browser thinks that it is actually/already talking to the server. The browser will connect to the proxy (pseudo server) on port 1080 and will send the following HTTP header:
GET /URL HTTP/1.1 Accept: */* Accept-Language: en-us,de;q=0.5 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; T312461; .NET CLR 1.0.3705; .NET CLR 1.1.4322) Host: host.ext:1080
Notice that the first line is just the HTTP verb and the URL on which to operate. It does not contain the host relevant data. (This is not always so, when the browser accesses not intranet sites, it will include the full URL in the first line.) Very important is the Host header. This header contains the name (host name and port) that the browser thinks it is talking to! Comment: the default port number for HTTP requests is 80, and in this case the port number itself is not listed. Then the URL will just be http:// host.ext/...
and the {{Host}] header only the name with no port number. Thus if no port number is listed, just think ":80"!
In this scenario the browser opens a connection to the proxy on port 1080, and then sends the HTTP request. The proxy will now open a connection to port 8080 on the server, and then forward the HTTP request transparently to the server. Thus, when the server looks into the incoming HTTP request, directly at the Host header, it knows under what name the browser expects to reach the server. And this is the key to the complete puzzle.
If the server now wishes to generate a termination URL, it should NOT use its own port 8080, and also not its own name (server.hidden.com), as the browser can not contact it directly. The browser can only talk to proxy, that is externally visible on the firewall. So the termination URL that the server generate must be of the form http:// host.ext:1080/...
to enable the browser to later reach the server again via the proxy.
However, there are (older!) proxy systems that attempt to hide their existence not only from the browser, but also from the server. What these proxies does, is to change the Host header to such a form, that the server sees its own name in the HTTP request. Thus, the Host header will be "server.internal:8080". The server receives the HTTP request and ''sees'' that the browser is talking directly to it. So, when the now generates a termination URL, it will be of the form http:// server.internal:8080/...
. And it is exactly this termination URL which the browser can not understand. The browser does not know a machine server.internal, and the browser can not make a connection on port 8080, as this is blocked by the firewall.
Problem in Summary: the terminal URL generated does not contain the correct host information.
To verify that this information is correct, see the section Session Management in Portal#Is Session Management Activated? to find the correct source code in the browser. Verify that the termination URL (this.sessURL
) is contains the correct host name, which must be the one that was also used to start the application.
Another elegant technique to verify that the proxy server is NOT changing the Host header, is to send a HTTP request to the server, and to ask the server to just display all the headers it has received. This can be achieved with the URL /sap/bc/echo?header=1
.
- Start the BSP application /sap/bc/echo?header=1 in the browser.
- Verify that the value of host header matches exactly the name and port from the URL
In principle, when a proxy is used, it must preserve the Host
header and must NOT translate the Host
header in any way.
Specifically for Apache proxies, this feature is only available from version 2 upwards. Reference Using Proxies.
Protocol Switch (HTTPS-->HTTP) through Proxy?
A very special case is the use of HTTPS on the internet, and then from the proxy to the server HTTP is used. This is effectively a variation of Session Management in Portal#Complex Proxy in Landscape?. Therefor the reason is referred to that section for background information.
In this case, the browser requires and uses a HTTPS URL that usually has the format https:// host.ext:1443/URL
, where 1443 would be the HTTPS port in use. The proxy forwards HTTP request to the server on a HTTP port without a changed Host header. The server see an incoming HTTP request, and will by default generate a http:// host.ext:1443/URL
where the protocol is set to http (server sees an incoming HTTP request), but on the HTTPS port 1443 (from the Host header). In this case again the termination URL will not work.
- Use Right Mouse Button (RMB) on the specific BSP application to get a context menu.
- Use the option "View Source" to look at the source code. Search for "this.sessURL".
- Use the option "Properties" and look at the attribute "Address".
- Verify that both the protocol and the port match exactly.
Usually to make this case to work, the SAP Web Dispatcher must be configured to inform the server that HTTPS protocol is in use by the browser. This feature is activated by the wdisp/add_clientprotocol_header = 1
option in the configuration and must be set if a protocol switch is done. This information is transfered from the Web Dispatcher to the server in a added HTTP header field called ClientProtocol
, which will then have the value "https". With an Apache proxy this can be achieved with the directive RequestHeader set ClientProtocol https
. Reference Using Proxies.
CRM Framework?
The see a problem where the CRM framework picks up a portal version number from a place where it is not available anymore. Thus the CRM framework gets an invalid portal version, and from this an incorrect URL is generated, that results in the loss of the session in the backend. This has no immediate affect in the browser. Only on the next roundtrip is a new session opened, and then the CRM framework detects that it is started in an illegal way, and raises an exception that no APPL object has been supplied. See Portal-Stylesheet ignored or loss of session in portal (CRM).
1 Comment
Unknown User (ir1xun0)
Great article! But if you have a single BSP application split into many pages in a workset, how do you get the session ID to be shared among the different pages? We are battling this issue right now... it gives you a new session ID for each click which results in poor performance.