@Resource error: "Naming binding already exists for foo.NewServlet/userName in namespace"

Viewed 572

I am looking at using the "@Resource String ..." injection available in servlet 3.0+ containers for providing configuration parameters easily to servlets. I would like for the defaults to work and fail if the key is not present in JNDI (indicating a configuration error)

I have toyed with a simple servlet in Netbeans 8.2 with Glassfish 4.1.1 where I would like to have the userName field, and the setFullName(String fullName) set:

package foo;

import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "NewServlet", urlPatterns = {"/NewServlet"})
public class NewServlet extends HttpServlet {

    @Resource(description="user name")
    String userName;

    private String fullname;

    @Resource()   
    public void setFullName(String fullName){
        this.fullname = fullName;
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            /* TODO output your page here. You may use following sample code. */
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet NewServlet</title>");            
            out.println("</head>");
            out.println("<body>");
            out.println("Full name = " + fullname);
            out.println("<h1>Servlet NewServlet at " + request.getContextPath() + "</h1>");
            out.println("Username = " + userName);
            out.println("</body>");
            out.println("</html>");


        }
    }
// Autogenerated stuff omitted
}

Without "web.xml" the fields are just null (and no failure). I have then played around with "web.xml" to see how I could define this. The "java:comp/env/foo:NewServlet/fullName" name is what Glassfish 4.1.1 appears to create as the name for the fullName setter.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
     version="3.0">
    <env-entry >
        <env-entry-name>java:comp/env/foo.NewServlet/fullName</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>!BAR!</env-entry-value> 
    </env-entry>
    <env-entry >
        <env-entry-name>java:comp/env/foo.NewServlet/userName</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>!USERNAME!</env-entry-value>  
    </env-entry>
</web-app>

This then fails with

Severe:   Exception while deploying the app [WebApplication4] : Naming binding already exists for foo.NewServlet/userName in namespace {java:module/env/foo.NewServlet/userName=Env-Prop: java:comp/env/foo.NewServlet/userName@Non-Injectable Resource@java.lang.String@!USERNAME!@@, java:module/env/foo.NewServlet/fullName=Env-Prop: java:comp/env/foo.NewServlet/fullName@Non-Injectable Resource@java.lang.String@!BAR!@@}

There is nothing else but these two files in the project. Apparently I am misunderstanding something basic, but reading the Java EE tutorial and searching for suggestions did not help me. I would really like two things:

  1. Either not providing any hints to the @Resource-tag using the container generated defaults or just a key like "our.application.fullName".
  2. Fail loudly if anything is wrong, including the key-value not being present.

Suggestions? A good answer will give a 500 point bounty.

1 Answers
Related