Using Java 8 Optional to set Current User ModelAttribute in Spring Security

This post will be a bit of a follow on from that last one which discussed using a User entity from a database in Spring Security Authentication Object, so it’s probably worth reading that first.

The new Optional  class in Java 8 lets us create a neat little mechanism for transferring our User entity, if one exists, into every controller method, using a ControllerAdvice  along the way.

Starting with the UserPrincipal  class from the last post we’ll make the following modification:

Remove the existing get method

and add this new one

Let’s dissect what’s happening here.

Optional.ofNullable(authentication)  will create an Optional<Authentication>  using the input Authentication  object, unless it is null, in which case an empty Optional<Authentication>  will be created. If there is no logged in user we expect the input Authentication  object to be null  and so we are able to create an Optional  that will only have a value if a user is logged in, and be empty otherwise.

The next part .map(auth -> ((UserPrincipal)auth.getPrincipal()).user) will use a mapping function which takes the Authentication  object from the Optional  created above, if it exists and applies the input mapping lambda (which extracts the DB User  entity from the input Authentication  object, by way of UserPrincipal ) to create an Optional<User> . This Optional  will contain the User entity if someone is logged in, otherwise it will be empty.

Now we have a way to create Optional Users, which will be present only if there is a user logged in using Spring Authentication.

Next we will create a ControllerAdvice  that will set a ModelAttribute  for the User , if it is present.

Spring will plumb the Authentication  object for us if there is a logged in user and we can go ahead and use the method we just created above to extract the Optional<User>  from the input Authentication. We then take advantage of Optional<User>.ifPresent(Consumer<? super User>) to set the model attribute "currentUser"  if the user is logged in.

If there is no user logged in then no action is taken, which is exactly the behaviour we want.

Now we can use this ModelAttribute  in controllers, let’s simplify the HelloController  from the last post.

or alternatively bypass the controller completely and just use it directly in the view, such as the following Thymeleaf expression

What do you think?  Is this something you would find useful?

As usual any comments are appreciated below!



3 thoughts on “Using Java 8 Optional to set Current User ModelAttribute in Spring Security”

    1. Thanks for the comment, of course you can do that, but you’re repeating the code to extract the User entity from the principal object across your controllers, along with null checks etc. I thought this would make your controller a little neater.

  1. hi,
    i followed your tuto seemed pretty simple to me but i still have “ cannot be cast to integration.model.UserPrincipal” error . do you have any idea about how to deal with it

Leave a Reply

Your email address will not be published. Required fields are marked *