czwartek, 11 lipca 2013

Oracle Coherence-Web: Session sharing between Weblogic and Tomcat


Recently I've been preparing a demo to show how we can share web session objects between Weblogic (12.1.1) and other application servers and in this example I've used Tomcat 6.0.37.
The task seemed to be easy as official Oracle documentation described the necessary steps well but real life experience is always different :)
If you follow the steps below you should sucessfully configure common session for WLS and Tomcat.
Assumptions:
1. I assume you have Coherence server cluster configured and running. Configuration could be done using WLS Console as in 12.1.1 it allows to manage coherence servers and clusters in the same way as normal managed servers.
2. There is simple "counter" application that stores Integer object in the session and increments the number by every http request to the app. For some reasons I used ear file in WLS and simple war file for Tomcat however the application is exactly the same. It consists simple Servlet that retrieves session and increment the counter.
3. Weblogic application is already configured with session storing in Coherence - this is simple Coherence-Web demo that I demonstrate in WINS sessions

Steps to share sessions between WLS and TC:

1. Follow official Oracle documentation how to set up your application (war) for Tomcat with Coherence:

There is webInstaller.jar that first inspect your war file and generate coherence-web.xml with set of different parameters that instructs your web app (war) how interact with coherence. Later after you run webInstaller with -install option, it changes your war file:
  • by adding coherence.jar and coherence-web.jar
  • by adding coherence-web.xml and by changing web.xml content
  • by wrapping your servlets in com.tangosol.coherence.servlet.api23.ServletWrapper - so http request will always go through  ServletWrapper first and then go to your original one.
  • by adding JSP directive:
    <%@ page extends="com.tangosol.coherence.servlet.api23.JspServlet" %>
    
  • Important: Above directive coused that my JSPs didn't want to compile in Tomcat. There was some problem with log() function not properly implemented in
    com.tangosol.coherence.servlet.api23.JspServlet.
    So far I don't have fix for it. That was mainly the reason to test Servlets only instead of JSPs.
  • You need to also remember that every time you add new servlet to your application it's worth to repeat webInstaller job with -inspect and -install options.

2. Adding tangosol-coherence-override.xml

tangosol-coherence-override.xml consists information about coherence server cluster running somewhere in the network. Tomcat container needs to connect to coherence servers and store session objects there. Without this file that correctly points to coherence server cluster, Tomcat will not join to existing cluster and initiate your own one which is not correct!
tangosol-coherence-override.xml should be in war file on the classpath: for example in: WEB-INF/classes

3. Changing web.xml context parameters

You need to change some parameters in web.xml which was updated by webInstaller after -install operation.
  1. <param-name>coherence-session-cookie-path</param-name>
    <param-value>/</param-value>
  2. <param-name>coherence-session-cookie-name</param-name>
    <param-value>JSESSIONID</param-value>
  3. <param-name>coherence-scopecontroller-class</param-name>
    <param-value> com.tangosol.coherence.servlet.AbstractHttpSessionCollection$GlobalScopeController </param-value>
  4. <param-name>coherence-session-id-length</param-name>
    <param-value>52</param-value>                                      </param-value>
  5. <param-name>coherence-session-affinity-token</param-name>
    <param-value>!</param-value>
Parameter #1: Cookie path needs to be the same for both applications in WLS and TC. That's why I set up for "/" but if both applications have the same context eg. /counter then this parameter could be "/counter"

Parameter #2: Cookie name for both applications should be also the same. JSESSIONID is a default value but I put it here just to be sure that both apps have it identical.

Parameter #3: This parameter instructs Coherence to share objects between different applications. It must be configured on both WLS and Tomcat web.xml-s.

Parameter #4: Important! When left default, Tomcat uses 12 characters for sessin id encoding but WLS by default uses 52. When WLS gets 12 lenght session ID in cookie from Tomcat, then doesn't check if session objects exists but discard cookie without checking in coherence. This is probably just because lenght does't match. So it's very importat to make sure that cookie value lenght is the same in both apps servers.

Parameter #5: Important! WLS adds to cookie value apart of JSESSIONID also hash of managed server id. When Tomcat gets such a cookie then it needs to remove WLS hash id from cookie and then check in coherence if session already exists. Setting this parameter to ! instructs Tomcat to remove it from session.

Very important!
There is a bug in Coherence 3.7.1 causes that coherence-session-affinity-token is ignored. You need to download a patchset 6 and use coherence.jar and coherence-web.jar from 3.7.1.6. Patch for it is:

Patch 14468425: COHERENCE 3.7.1.6 FULL DISTRIBUTION

I spent 2 additional days fighting with this problem of cookie value and finally found the solution on metalink. It really shows the value of Oracle Support when developing solutions and no blog post from entire Internet doesn't mentioned about it.
Take coherence.jar and coherence-web.jar from 3.7.1.6 and replace them in Tomcat application war file in WEB-INF/lib.

4. Testing your Tomcat application

Start Tomcat and using manager install your war file. Look at catalina.out if Tomcat joined the cluster mentioned in tangosol-coherence-override.xml. At this stage Tomcat should share sessions with WLS application.

5. Troubleshooting

If it doesn't work like expected, check logs file from WLS managed servers and Tomcat if both servers joined the same coherence cluster.
Check also cookie generated by WLS and Tomcat if it is the same with common path eg "/" and affinity suffix from WLS.
Check if your servlets get wrapped by coherence servelt on Tomcat. If not, then of course session will be taken from internal Tomcat heap instead of coherence.
You can aslo use coherence client:
java -cp $COHERENCE_HOME/lib/coherence.jar:./conf:./ com.tangosol.net.CacheFactory
where on ./conf directory you need to place tangosol-coherence-override.xml and session-cache-config.xml. You need to reffer session-cache-config.xml in tangosol-coherence-override.xml like this:
<configurable-cache-factory-config>
      <init-params>
         <init-param>
            <param-type>java.lang.String</param-type>
            <param-value system-property="tangosol.coherence.cacheconfig">
               session-cache-config.xml</param-value>
        </init-param>
      </init-params>
</configurable-cache-factory-config>
When coherence client joins the cluster connect to appropriate cache name: session-storage. This is default cache name for storing sessions in Coherence-Web.
Issue the following command to connect to session-storage:
cache session-storage
Later you can check number of elements in cache (command: size) or try to retrieve object using command: get. The command itself will fail as this coherence client doesn't have access to appropriate java object but at least you check if object with specific key exists.
Finally, if you're still unable to make it work, contact me and I will try to help.

6. Running my "counter" examples

Here you can find ear file for WLS, and here you can find war file for Tomcat.
After deploying to apps servers you can run counter servlet at the following URL:
http://<your host>:<your port>/counter/counterServlet.
Coherence cluster is called: Coherence-cluster1 and on my virtual machine can be reached at 10.0.3.15:8888.
I hope this post will be usefull for you when setting up coherence for session sharing.
Michal.