Fix NameNotFoundException: Reference Not Declared

J2EE 1.4 and earlier versions require all resource and ejb references be declared in the standard deployment descriptors, such as ejb-jar.xml, web.xml, and application-client.xml. These elements -- resource-ref, ejb-ref, ejb-local-ref -- register entries in the current component's private environment context. These declarations are needed, even when the reference name is the same as the global JNDI of the target resource or EJB.

For example, HelloServlet looks up the default DataSource in JavaEE SDK 5, whose global JNDI name is jdbc/__default:

public class HelloServlet extends HttpServlet {
protected void processRequest(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = null;
try {
out = response.getWriter();
Context ic = new InitialContext();
DataSource dataSource = (DataSource) ic.lookup("java:comp/env/jdbc/__default");
Connection connection = dataSource.getConnection();
out.println("Successfully looked up the default datasource: " + dataSource +
", and got the connection: " + connection);
} catch (NamingException e) {
throw new ServletException(e);
} catch (SQLException e) {
throw new ServletException(e);
Any portable applications must also declare a resource-ref in web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
Without this resource-ref element in web.xml, the app fails with this error in JavaEE SDK 5/Glassfish/Sun Java System Application Server:

javax.naming.NameNotFoundException: No object bound to name java:comp/env/jdbc/__default
at com.sun.enterprise.naming.NamingManagerImpl.lookup(NamingManagerImpl.java:751)
at com.sun.enterprise.naming.java.javaURLContext.lookup(javaURLContext.java:156)
at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:307)
at javax.naming.InitialContext.lookup(InitialContext.java:351)
at com.foo.servlet.HelloServlet.processRequest(HelloServlet.java:30)
We are not done yet. We also need to map the resource reference name (jdbc/__default) to the global JNDI name of the target resource (jdbc/__default). This step is appserver-dependent, usually editing an appserver-specific deployment plan file. For example, sun-ejb-jar.xml, sun-web.xml, sun-application-client.xml, or jboss.xml. The following shows how this is mapped in sun-web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="">
<class-loader delegate="true"/>
When the local reference name and the global JNDI name are the same, some application servers may also have some default mapping rules to eliminate this step. For instance, in JavaEE SDK 5 and Sun Java System Application Server 9, this step is not needed when the two names are the same.

JavaEE 5 has introduced a series of annotations to greatly simplify configurations, such as @EJB, @EJBs, @Resource and @Resources. Using resource injections, applications no longer need to use ejb-ref, ejb-local-ref, nor resource-ref, and they may get rid of standard deployment descriptors altogether. But some sort of mapping mechanisms (default mapping rules, or appserver-specific deployment plans) are still needed.

More info on how to inject/lookup resources in JavaEE 5 and EJB 3, please refer to 5 Ways to Get Resources in EJB 3

All posts in this series for NameNotFoundException:

Fix NameNotFoundException: Incorrect Lookup Name

Fix NameNotFoundException: Reference Not Declared

Fix NameNotFoundException: Wrong Mapping in Deployment Plan