1

If suppose I am initializing datasources in ServletContextListener#contextInitialized() as:

package com.myapp.listeners;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;

public class MyAppListener implements ServletContextListener {
    @Override
    public void contextDestroyed(ServletContextEvent event) {
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        try{
            InitialContext initialContext = new InitialContext();

            DataSource dataSource = (DataSource) initialContext.lookup("jdbc/myDB");

            event.getServletContext().setAttribute("datasource", dataSource);
        }catch(NamingException ne){
            // TODO WHAT TO DO HERE?
        }
    }
}

So, what to if initializing data source fails? How can I prevent Tomcat from deploying this application, because without datasource I have no meaning of application deployed.

nullptr
  • 3,320
  • 7
  • 35
  • 68
  • 1
    Might be worth reading this : http://stackoverflow.com/questions/4031275/prefered-way-to-handle-java-exceptions-in-servletcontextlistener – DaveH Oct 28 '14 at 16:05

1 Answers1

4

The data source should be available from JNDI lookup, not like this. I would suggest you to wrapper this code in a method instead of retrieving it from ServletContext.

To the question: what to if initializing data source fails? How can I prevent Tomcat from deploying this application?

Throw a custom RuntimeException in contextInitialized and the application won't be deployed.


To retrieve a connection from your datasource:

//no need to extend from this class
public final class ConnectionProvider {
    private static final String DEFAULT_DS = "jdbc/myDB";
    //no need to initialize this class
    private ConnectionProvider() {
    }
    //retrieve the connection
    public static Connection getConnection() {
        Connection con = null;
        try {
            InitialContext initialContext = new InitialContext();
            DataSource dataSource = (DataSource) initialContext.lookup(DEFAULT_DS);
            con = dataSource.getConnection();
        } catch (Exception e) {
            //handle exception
            //basic handling, you should at least use a logger
            e.printStackTrace();
        }
        return con;
    }
}

And then call this static method in your Service classes (not in Servlets, not in Dao).

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Isn't I am doing JNDI lookup for data source? Can you please explain it in more detail, how can I retrieve from wrapper code? – nullptr Oct 28 '14 at 16:34
  • Isn't that costly to do naming lookup for data source for every database connection needs? Can't we initialize data source once and use it forever for new DB connections? – nullptr Oct 28 '14 at 16:41
  • @Meraman that's not costly. If by costly you mean 0.005 ms in your app, then yes it has high costs and I can take the risk. – Luiggi Mendoza Oct 28 '14 at 16:42
  • What if its not within milliseconds, what to do if DB is remote server on Internet, with say 100 ms round-trip time? Why dont we initialize data source once, and use it for all connection needs? Why are we looking up data source for every connection? – nullptr Oct 28 '14 at 16:47
  • @Meraman I guess you're misunderstanding this. The app server initializes the `DataSource` and enables you the access to this through JNDI. You can think of JNDI as a small cache for your application, where the lookup is the key of this big `Map` in memory. Calling `initialContext.lookup("jdbc/myDB")` several times won't start several DataSources, it will retrieve 1 and if it's not initialized it will create one and provide it for you. The time you talk about it's not the real time. And if your database is far from your web app then you should think on another architecture – Luiggi Mendoza Oct 28 '14 at 16:54
  • No I don't think it will be cached. But what is reason to lookup up it for every connection need? – nullptr Oct 28 '14 at 17:32
  • @Meraman yes, it is. And the datasource by default will open as many connections as it needs until it gets to the max number of connections allowed (if you don't declare this value, the datasource will use a default one, which is vendor specific) and will cache these connections for future usage. – Luiggi Mendoza Oct 28 '14 at 17:34
  • If I am not wrong, is it like Tomcat server creating and binding data source, and my application is looking up that resource? – nullptr Oct 28 '14 at 18:06
  • @Meraman yes, that's basically what happens behind the scenes. – Luiggi Mendoza Oct 28 '14 at 19:10