2

In the following Connector/J reference for JDBC/MySQL it suggests we cache the instances of InitialContext and Datasource. Would just making it a private static instance solve the caching? Shouldn't one have to be concerned with thread-safety (if at all)? What is the best 'place' to cache this for a web-app (Restlet + glassfish/Java EE + mysql)??

There is a GenericDAO class that is the root of the data-access classes, so to speak. So would just having static instances actually solve the problem? It would force some of the methods to be static which we don't want. Suggestions??

Thanks!

public void doSomething() throws Exception {
/*
* Create a JNDI Initial context to be able to
* lookup the DataSource
**
In production-level code, this should be cached as
* an instance or static variable, as it can
* be quite expensive to create a JNDI context.
**
Note: This code only works when you are using servlets
* or EJBs in a Java EE application server. If you are
* using connection pooling in standalone Java code, you
* will have to create/configure datasources using whatever
* mechanisms your particular connection pooling library
* provides.
*/
InitialContext ctx = new InitialContext();
/*
* Lookup the DataSource, which will be backed by a pool
* that the application server provides. DataSource instances
* are also a good candidate for caching as an instance
* variable, as JNDI lookups can be expensive as well.
*/
DataSource ds =
(DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");

/*
*Remaining code here...
*/
    }
Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
PhD
  • 11,202
  • 14
  • 64
  • 112
  • I have no idea about the Restlet part, but in a normal Servlet environment you'd use `ServletContextListener` for this. [Example here](http://stackoverflow.com/questions/4491596/get-database-connection-from-a-connection-pool/4492111#4492111). That might give new insights if you know Servlets well. – BalusC Feb 19 '11 at 02:25
  • @BalusC: Seems that would work...I'll post the confirmation once I implement it! It's been a while since I worked on coding web-apps - I totally forgot about the ServletContext! Thanks a ton. – PhD Feb 19 '11 at 03:26
  • Since InitialContexts are not thread-safe ( http://docs.oracle.com/javase/7/docs/api/javax/naming/InitialContext.html ), I guess caching must be done carefully. I'm not sure DataSources have the same problem (it seems that they don't) – marcus Feb 20 '13 at 00:51

2 Answers2

4

If you're using JAX-RS, then you can use @Context annotation.

E.g.

@Context
private ServletContext context;

@GET
@Path("whatevers")
public List<Whatever> getWhatevers() {
    DataSource dataSource = Config.getInstance(context).getDataSource();
    // ...
}

However, if the @Resource annotation is also supported on your Restlet environment, you could make use of it as good.

@Resource(mappedName="jdbc/MySQLDB")
private DataSource dataSource

This is in turn technically better to be placed in an EJB which you in turn inject by @EJB in your webservice.

@Stateless
public class WhateverDAO {

    @Resource(mappedName="jdbc/MySQLDB")
    private DataSource dataSource

    public List<Whatever> list() {
        // ...
    }

}

with

@EJB
private WhateverDAO whateverDAO;

@GET
@Path("whatevers")
public List<Whatever> getWhatevers() {
    return whateverDAO.list();
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
2

Following up on BalusC's link, I can confirm that we could do the same thing when using Restlet. However, as per the code in the example to get the config instance you are passing in the ServletContext as an argument. Restlet is like 'another' framework that uses Servlets as an adapter to configure itself. So it'll be tricky to pass the ServletContext as an argument from somewhere else in the code (Restlet uses it's own Context object which is conceptually similar to ServletContext)

For my case a static method returning the cached datasource seems to be 'clean enough' but there could be other design/organization approaches.

Community
  • 1
  • 1
PhD
  • 11,202
  • 14
  • 64
  • 112
  • For what is worth, on standard JAX-RS API, you can just inject the `ServletContext` in the webservice class by `@Context` annotation. – BalusC Mar 31 '11 at 20:05
  • @BalusC: Now that's interesting...I was aware of this annotation but didn't know how to use it. Googling was not of much help either. Any suggestions/links? – PhD Mar 31 '11 at 20:10