2

Under Google App Engine any object that you want to store in a HttpSession has to implement Serializable, and all of its fields have to be serializable, because an instance running in GAE might be migrated from one JVM to another. This means that if I want to store a FooBar instance into an HttpSession I can't have a field in it pointing back to the HttpSession.

However, I can store the ID returned by getId(). According to this question the ability to get a session from its ID has been depreciated for security reasons, but the GAE implementation is different. According to this blog post you can use the ID to get the DataStore entity representing the HttpSession, but I want a reference to the Java object, not the underlying data being used to migrate it between JVMs.

So, is there any way to do what I want?

Community
  • 1
  • 1
Matthew Cline
  • 2,312
  • 1
  • 19
  • 36
  • 1
    Okay, so i had to read your question like three times or so to understand what you're trying to accomplish. However i still cannot see a practical use for what you're asking. If you store your `FooBar` object in your `HttpSession` with `#setAttribute(name, obj)` you can get that object from your session any time (while in that session). Why do you want to create a circular reference when you will always refer to the `FooBar` object via its parent `HttpSession`? When you don't have the session object you should not be able to access any data associated with it. So why break session security? – konqi Nov 16 '15 at 08:40

1 Answers1

3

Relevant paragraph from your link:

A Datastore entity of kind "_ah_SESSION" is created for each new HttpSession. The entity key is "_ahs" + session.getId(). Each _ah_SESSION entity has two properties "_values" and "_expires".

The "_values" property is simply the serialized byte[] representation of a HashMap that includes the the session data.

So what you can do is as follows:

// When putting FooBar to session
FooBar fooBar;
HttpSession session;
session.setAttribute("fooBar", fooBar);

And, on the other side:

// When getting session from datastore
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Key sessionKey = KeyFactory.createKey("_ah_SESSION", sessionId);
Entity sessionEntity = datastore.get(sessionKey);
byte[] sessionBytes = sessionEntity.getProperty("_values");

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sessionBytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
Map<?, ?> sessionMap = (Map) objectInputStream.readObject();
FooBar restoredFooBar = (FooBar) sessionMap.get("fooBar");

I wrote the code from memory, so please test it in production first and add standard things like cast check, but the general idea is the same.

Ibrahim Arief
  • 8,742
  • 6
  • 34
  • 54
  • I've documented this approach to resolve a problem with losing session data, https://stackoverflow.com/questions/51014992/google-app-engine-session-loses-attribute – Neill Jul 14 '18 at 15:26