Discussions

EJB design: Following a users call throughout the code

  1. Following a users call throughout the code (2 messages)

    I want to develop a J2EE application with a web tier. Each user gets an ID when starting up the application.

    My question is, how do I maintain this ID throughout the application, withouth having to pass it along to each function I'm calling?

    I can set the userID as an parameter in the HTTP-session, but how do I obtain the ID deeper down in the code? (In the beans or deeper down in the EJB:s.)

    The ID would primarily be used for logging.


    Any answers will be greatly appreciated!
  2. There are three possible approaches.

    1. Keep passing Id, across the code. with drilldown approach.
    2. User cache system, put all active IDs in cache and access them. (This is ok with u have 10 users working at one time, the arrangement will fail once you have 25,000 users working at a time.)

    3. Have a LoginStatus database table with composite primary key

        Running number + User ID + User ID alloted for session.

       have a flag which will mark it as a currently active user or signedout

    Define a entity bean for this table and once u populate the user ID in session, populate it in table too.

    The problem remains same as you need to have userID passed upto some level atleast upto session facade level so as to later retrive itz status at deep down point.

    Hope this helps
    Regards
    Chetan
  3. Here are some options:

    1) Use the J2EE security model to authenticate the user. Most J2EE components have a mechanism to retrieve the user ID:

    Servlets/JSP: HttpServletRequest.getRemoteUser()
    EJB: EJBContext.getCallerPrinciple()

    Unfortunately, this will not help you with your Java Beans.



    2) Use a java.lang.ThreadLocal variable. ThreadLocal variables allow to associate variables with the thread of execution, which a handy way to pass data around. ThreadLocal variables are untyped global variables, so you probably want to encapsulate them carefully.


    public class LocalUser {
      private static final ThreadLocal threadLocal = new ThreadLocal();

      public static UserIdentity getInstance() {
        UserIdentity identity = (UserIdentity) threadLocal.get();
      }

      public static void init(UserIdentity identity) {
        threadLocal.set(identity);
      }

      public static void release() {
        threadLocal.set(null);
      }

      // Instance variables and instance methods with the rest of the logic
    }


    In your servlets:


    UserIdentity identity = (UserIdentity) session.get("UserIdentity");
    LocalUser.init(identity);
    // Call JavaBeans ...
    LocalUser.release();


    In your JavaBeans:


    UserIdentity identity = LocalUser.getInstance();


    This approach has its limitations:

    1) It is really only effective if you have some sort of Front Controller servlet that all user requests pass through. Otherwise the identity management code must be copied into many locations and becomes hard to maintain.

    2) The ThreadLocal variables probably will not propogate into your EJB layer, which does its own thread management. Since the thread executing the EJB may be a different thread from the one executing the servlet, the ThreadLocal variable might not cross into the EJB layer.