How to share sessions between modules on a Google App Engine Java application?
Asked Answered
C

3

4

When I store something in the session via HttpSession in module A:

HttpSession session = req.getSession(true);
session.setAttribute("username", "Eng.Fouad");

then I try to retrieve this information from within module B (during the same browser session):

HttpSession session = req.getSession(true);
String username = session.getAttribute("username"); // null!

I got null as a value, which means different session.

How to share session across multiple modules in GAE?


Old Answer which I think it doesn't work well:

I've been trying to solving this issue for weeks. It turns out that the modules don't share sessions because the cookies are different across different sub-domains (module1.apphost.com cookies != module2.apphost.com cookies). To solve it, simply set cookies domain in web.xml of each module:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">

  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
    <param-value>.apphost.com</param-value>
  </context-param>
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
    <param-value>/</param-value>
  </context-param>
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionURL</param-name>
    <param-value>none</param-value>
  </context-param>

  ...

</web-app>

EXTRA:

Here is a list of all init parameters you can use with Jetty cookies:

enter image description here


EDIT: Workaround for development environment:

  1. Make the port of each module fixed (using JVM arg -Dcom.google.appengine.devappserver_module.{module_name}.port=8081). For example, module1 is always hosted at localhost:8888, and module2 is always hosted at localhost:8889. See this answer.
  2. Bind the localhost with the port of each module to a custom domain using Fiddler. For example, moule1.gaelocal.com points to localhost:8888 and moule2.gaelocal.com points to localhost:8889. See this answer.
  3. Update web.xml of each module and replace .apphost.com with .gaelocal.com (or just use .apphost.com for both environment).

Curiosa answered 31/12, 2014 at 19:19 Comment(0)
V
1

You can implement a combination of HttpServletFilter and HttpSessionListener that synchronizes accross both webapps. When a request modifies session state, save it to a persistent store (db), and for each requests, checks if the session objects are up to date with db.

Note that this require both web app to be served under the same domain (eg: mydomain.com/webapp1 and mydomain.com/webapp2). Otherwise the JSESSIONID cookie wouldn't be delivered by the browser.

There's an off the shelf solution that does this such as Hazelcast. It's designed for load balancing / failover but you might be able to use it for the intended purpose.

Also consider the possibility using HttpSession is a wrong architectural design. Maybe you should be transacting with a database / API instead?

Vestavestal answered 6/1, 2015 at 22:25 Comment(1)
What I need is to get the full benefits from GAE modules, where each module should be hosted on a separate subdomain. Regarding your last point, GAE stores the HttpSession attributes in both DataStore and MemCache.Curiosa
S
0

HttpSession is inteded for use in a monolithich environment in which the servlet container has contact directly with a singular client. One implementation suggestion is to use a database API to store the current state of the client session. Since you are using GAE, Google's datastore come to mind.

https://cloud.google.com/appengine/docs/java/gettingstarted/usingdatastore

Straddle answered 6/1, 2015 at 22:30 Comment(1)
The problem here is related to the client side state (which is stored in cookies). The server stores the HttpSession attributes in both DataStore and MemCache.Curiosa
H
0

I am just a beginner. But still you could try setting the domain for the cookie in your config file and retrieve sessions from there.

<context-param>
    <param-name>root_path</param-name>
    <param-value>/portal</param-value>  
</context-param>
...
...
<session-config>
    <cookie-config>
      <http-only>true</http-only>
    </cookie-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

I hope this helps.

May be this link is helpful for you.

share-session-data-between-2-subdomains

Hedelman answered 13/1, 2015 at 5:8 Comment(1)
This is a servlet 3.0 feature. GAE supports only servlet 2.5.Curiosa

© 2022 - 2024 — McMap. All rights reserved.