Ravi
Ravi

Reputation: 2558

Accessing session variables outside servlet

I'm working on a java webapp where I need to access records from database based on user login id.I set the login details in session variable after successful login.

I want to do is something like this

Select * from proj_recs where user_id= user_id (from session)

Right now I'm passing username as a parameter, but I believe it's not a good practice. Is there a better way of accessing session variables outside servlet ?

Servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub

        User user = (User) request.getSession().getAttribute("userInfo");

        System.out.println(user);

        if(user != null){
            Gson gson = new Gson();
            returnJsonResponse(response,gson.toJson(user));
            return;
        }
}

In data layer package

public Accrual getAccruals(String accrualID,String userid) throws AccrualNotFoundException{

    String sql = Select * from db_acc where acc_id= accrualID and user_id=userid;

}

The problem is I have to modify all my methods with userid. Is there a way I can set user details into some static class and access the details where ever i want in the application without modifying the method signature? But I believe static classes are share between different user requests.

Upvotes: 5

Views: 5518

Answers (3)

fajarkoe
fajarkoe

Reputation: 1563

The solution that you are looking for is Thread Local (google it). It allows you to access thread-specific data using static method.

You can start reading http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/. Using examples from there, you need to create:

public class MyThreadLocal {

    public static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static void set(User user) {
        userThreadLocal.set(user);
    }

    public static void unset() {
        userThreadLocal.remove();
    }

    public static User get() {
        return userThreadLocal.get();
    }
}

in your servlet, do this:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    User user = (User) request.getSession().getAttribute("userInfo");
    MyThreadLocal.set(user);
    try {
       // call data layer
    } finally {
        MyThreadLocal.unset();
    }
}

in your data layer, you can retrieve the user by doing this:

public void dataLayerMethod(ExistingParameters parameters) {
    User user = MyThreadLocal.get();
}

Notice that you don't need to change the method signature of the data layer.

Thread Local is a bit confusing at first, but you will get familiar very quickly once you read the article.

Upvotes: 2

Serge Ballesta
Serge Ballesta

Reputation: 148880

With strict separation of concerns, the data layer should have nothing to do with the session or request. But you need the username (user_id from you example) in service or data layer. The simplest is effectively to collect it in controller (controller has access to request and session), pass it to service layer, and forward it to data layer.

An alternative (used by security framework like Spring Security or Apache Shiro) is to store it in thread storage at beginning of the request treatement, and carefully clean it out at end (in a filter). Then a static method of an utility class can give it to any part of your application. But you get a dependency to the framework each time you use the utility class. To reduce undue dependances, you can have your own Holder class, with a static method that calls the one of the framework : the dependance is limited to the holder class.

There is a third solution if you use Spring. You can have a session scoped bean, with aop proxying, that you can inject in any bean that need access to your variable. Thanks to aop proxying you will have access to the data from current session, even from a singleton bean.

In my own apps, I use first method in simple cases (few classes) and third method when I want to avoid repeating over and over the same parameters in many methods.

Upvotes: -1

Udit Mishra
Udit Mishra

Reputation: 140

You can always get the user id from the session inside servlet and pass that to your data layer, there is no point using session directly in the data layer. You extract your objects and pass the buck to the next layer. Using HTTP specific objects in the data layer is actually the bad practice.

Upvotes: 0

Related Questions