Yep, that’s another story of “always check if serialising and de-serialising works as expected”. And some kind of reminder for future-me if I forgot about this! ;-)
Session of logged users seems to be a pretty easy topic, yep? For sure it is! What if you want to share that session between different instances of your app? That seems quite easy too - let’s store it in a database and you’re good to go.
Need and sort of “background”
For my last project, I’m using a simple web framework called Javalin, which runs default on Jetty. And after making PoC I’ve come across of topic “single user using many app instances”. Fortunately, there is even tutorial about it on Javalin page (here). I’ve checked it, wrote a bit code aaaand… it is not working as expected!
Problem
When enabled saving session into database and user was… logged out instantly! Error 401 was sent from the secured resource and frontend was redirecting to the login which invalidates session (which, in fact, was desired behaviour). But the question is - why this 401 was sent if the user logged in correctly?
After debugging and looking into saved session object in database I’ve found out that there is NO USER DATA THERE!
Wait, what? I’m sure that I’ve put that data into the session. It works if the session was in memory!
Let’s see how writing and reading values into session looks in Javalin:
// saving value
ctx.sessionAttribute("mystery", "I like trains");
// and reading value to the "value" variable
var value = ctx.sessionAttribute("mystery");
Pretty simple, yep? And this is how saving user details was in my app:
var userDetails = new UserDetails();
// ... filling up data and saving to session
ctx.sessionAttribute("USER", userDetails);
Looks the same… and not working. But mystery
above works, so what the heck is going on?!
Solution!
You might already know because I’ve already written it in the beginning - serialisation. Session store (from class JDBCSessionDataStoreFactory
) didn’t know how to save object with user details to the database. So it simply ignores it. And the rest of the app didn’t work because there was no user data, so no info about user roles, so no cookies and big “NONONO”.
So, solution was simply to serialise and de-serialise it, for example as a JSON. For that I’ve used Jackson mapper:
// yep, simple com.fasterxml.jackson.databind.ObjectMapper
var objectMapper = new ObjectMapper();
// serialize before saving to session
var userDetails = new UserDetails();
// ... filling up data and saving to session
ctx.sessionAttribute(
"USER",
objectMapper.writeValueAsString(userDetails)
);
// and reading it in some other place
String userDetailsStr = ctx.sessionAttribute(
USER_SESSION_KEY
);
var userDetails = objectMapper.readValue(
userDetailsStr,
UserDetails.class
);
And everything started to work smoothly and as expected!
Takeaways
I will repeat myself from the beginning - always check if serialising and de-serialising works as it should. And additionally - check if data is saved. That can save a lot of work and time. :-)
Top comments (0)