I'm relatively new to Play and trying to fulfill a pretty simple use case. The application is protected by a Single Sign On gateway that passes a header to the application with user ID I can then look up against a database to get the user information.
When I detect the header, I want to first look in the session to see if we've already done the DB lookup. If it's already in the session, I can proceed. Otherwise, I can perform the lookup one time and then store the value in the session. I understand Play session is really just a 4k cookie, but that's fine for my purposes.
The problem I've been having is successfully adding the value to the session and having it available in my template to display the user's information on every request. I can't seem to add anything in to the session. I tried a global doFilter and I've been struggling with action composition. Here's a truncated example I'm working with now:
class UserRequest[A](val userObject : Option[String], request: Request[A]) extends WrappedRequest[A](request)
object SessionAction extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
if (request.session.get("user").isEmpty) {
// The Scala JSON stuff built in doesn't let me just serialize a Java object without decorating it
// And we can't store anything but Strings in Session so....
val mapper = new ObjectMapper();
val user = my.package.Global.apiClient.getUserService().getUserByEmail(request.headers.get("AUTH_USER").get)
try {
val userSerialized = mapper.writeValueAsString(user)
Logger.info(s"Writing serialized string to session for user $userSerialized") // Attempt to add it to the session. This doesn't throw an error, but "user" is always None later
request.session + ("user" -> userSerialized)
Logger info ("Is session empty? " + request.session.get("user"))
block(new UserRequest(Some(userSerialized), request))
} catch {
case e: Exception => Logger.warn("Error when trying to load user session", e)
}
}
block(request)
}
}
Even at the end of the Session Action call when I print out if the session is empty, I get "None." I can verify the the DB retrieval and everything is working, it's just storing and retrieving the actual value I'm having trouble with. In my controller then I try to do something like this:
def index = SessionAction {implicit request =>
val userString = request.userObject // The docs on Action Composition do something like this but request.userObject doesn't exist for me
Logger.info(s"User request is $userString")
Ok(views.html.index("Page title..."))
}
The end result is I want to be able to display the user name on every template (implicit request) without having to explicitly pass it around.
Thanks in advance for any help.
- William