Java – Best practices for using HTTP sessions(Java)

designjavajeesession

My Question is not about how to use HTTP session or how values are being used in session. Question is more oriented about approach.

In my current application there are few values being stored in the Session and we require those values every now and than, here are few values we fetching from session

  1. Store
  2. Language
  3. Customer
  4. few others

I can fetch these values from session like

request.getSession().getAttribute( "name" )

I need those values not directly in my Controller, but in other layer (say Facade) so I have 2 options

  1. Pass each required values to Facade method by request.getSession().getAttribute( "name" ).
  2. Create a method in each Facade Class like.

Method in Facade

 private Object getSessionValue(final String key) {
    ServletRequestAttributes reqAttr = (ServletRequestAttributes) RequestContextHolder
                            .currentRequestAttributes();
            return reqAttr.getRequest().getAttribute(key);
}

Though both are working find in my case, but with one exception, I need to have this method on each Facade Class or need to fetch each object in Controller.

Is there any other way or approach which might be more clean or my current approach is fine

Best Answer

My personal approach would be not to use the session everywhere. I'd try to reduce its usage at the controller layer. In the controller I'd extract what I need for my business logic and the later will never know that there is a web session involved. This will make that logic portable to non-web applications, and will work with all its data in a type-safe manner that is free of boilerplate code.

If you want to avoid the boilerplate code of obtaining the request, then the session, and then the items from the session, your method approach is fine enough, and a common practice in my experience. If you are using it in Java, you can improve it a little by adding some generics:

 public static <T> T getSessionValue(final String key) {
    ServletRequestAttributes reqAttr = (ServletRequestAttributes) RequestContextHolder
                        .currentRequestAttributes();
        return (T) reqAttr.getRequest().getAttribute(key);
}

You can use it now like this:

Integer someSessionInt = SessionUtils.<Integer>getSessionValue("someSessionIntKey");

I am assuming the method is defined in a static SessionUtils class. If you define it in a base controller class, want to use this from inside of a controller, you should call it this way:

Integer someSessionInt = this.<Integer>getSessionValue("someSessionIntKey");

The this keyword can be substituted with super, but without it a compile error would occur due to the generics.


In addition to my suggestion above, there is another way of hiding the session usage and have a session-free and independent API/facade. By sticking to the programming-to-interfaces paradigm you can have interface implementations that use the session, but it is never shown by the interfaces you enforce in your facade/api. So, for instance you may have a general purpose authorization service, exposed trough interface, that shows you who is the currently logged user, if s/he is a guest and whether s/he has a particular permission. Your application then could use a concrete implementation of the service interface that gets the user from the session. When you use the service, the interface does not expose anything related to the session, so all usages remain session agnostic, and type safe.