gmustudent
gmustudent

Reputation: 2209

JNDI lookup in a servlet's init parameter a good idea?

I am currently building a Java EE web application and found this article that has given me some great pointers on how to build a better application. The first tip is "Use the HttpServlet init() method for caching data". This sounds like a genius idea, but now that I've implemented my own version of it I'm scared about thread safety, and keeping connections open.

  1. Is this idea, and the way that I've implemented it thread safe to make sure that each thread has it's own db connection?
  2. I understand that this requires a servlet reboot anytime I want to alter the JNDI lookup and I am okay with that but are there any other drawbacks to not just doing the JNDI lookup in the JDBC method?
  3. Is the way that I have used the destroy method to close the context variables a smart idea or would this not work with an abundance of threads or any other hindrance?

Here's some code to give you an idea on how I have implemented this idea. I'd just like some guidance on my first implementation before I go implementing this on my 40 other servlets. Thank you so much for reading. Oh and I can add the dao method too if that would help.

Servlet Notes: Within the init I just call a bean that does all of the JNDI fluff to make this easier to add to multiple servlets. Then in the servelt I send the datasource to the dao method to be used. I also thought it'd be smart to add a load on startup so that I could see if the JNDI worked right off the bat when I start the server.

@WebServlet(name="GetBoardPostCommenters", urlPatterns={"/getBoardPostCommenters"}, loadOnStartup = 1)
public class GetBoardPostCommenters extends HttpServlet
{
    private InstrideJndi jndi = null;
    private static final long serialVersionUID = 1L;

    public void init(ServletConfig servletConfig) throws ServletException
    {
        super.init(servletConfig);
        jndi = new InstrideJndi("GetBoardPostCommenters");
    }

    public void destroy()
    {
        jndi.closeConnection();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        BoardPost boardPost;

        boardPost = new BoardPost();
        boardPost.setId(Long.parseLong(request.getParameter("boardPostId")));
        boardPost = BoardPostCommentLikeDAO.getBoardPostCommenters(boardPost, jndi.getDataSource());

        request.setAttribute("likerCommenterList", boardPost.getCommenterList());
        request.getRequestDispatcher("WEB-INF/util/likerCommenterList.jsp").forward(request, response);
    }
}

Bean Notes: The controller get the name of the servlet that called this method to help with debugging. And the close connection does what I would normally do in the finally of a dao method.

public class InstrideJndi
{
    private DataSource dataSource = null;
    private Context initialContext = null;
    private Context environmentContext = null;

    public InstrideJndi(String className)
    {
        try
        {
            this.initialContext = new InitialContext();
            this.environmentContext = (Context) initialContext.lookup("java:/comp/env");
            this.dataSource = (DataSource) environmentContext.lookup("jdbc/instride");
        }
        catch(NamingException error)
        {
            System.out.println("Error With JNDI Lookup -  " + className + " - " + error.getMessage());
            error.printStackTrace();
        }
    }

    public DataSource getDataSource()
    {
        return this.dataSource;
    }

    public void closeConnection()
    {
        if (initialContext != null) try{initialContext.close();} catch(NamingException ignore) {}
        if (environmentContext != null) try{environmentContext.close();} catch(NamingException ignore) {}
    }
}

Upvotes: 0

Views: 4876

Answers (1)

Scott Heaberlin
Scott Heaberlin

Reputation: 3424

Each thread does not have it's own DataSource reference here. Your servlet will be one instance across many request threads each invoking doGet(). In contrast, init() only gets called at web module startup, prior to the servlet instance servicing requests.

Another tip - it's fairly common to retrieve container managed resources in one lookup.

this.dataSource = new InitialContext().lookup("java:/comp/env/jdbc/instride");

I could be wrong, but I typically never close() these types of InitialContext instances, unless I'm specifically expecting it to be a network operation (ldap, resource lookup from remote application server, etc).

Upvotes: 2

Related Questions