7 Replies Latest reply on Jan 19, 2012 7:32 PM by sfcoy

    NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")

    willreichert

      I am working with the SPECjEnterprise benchmarking application on JBoss as 7.1.0.CR1-SNAPSHOT and have encountered a strange behaviour with the JNDI lookup.  The SPEC application is experiencing the following exception when trying to lookup the datasource.

       

      22:33:38,653 FINE  [org.spec.jent.loader.DatabaseHelper] (http-localhost.localdomain-127.0.0.1-8080-6) Lookup of data source jdbc/SPECjOrderDS for loading SPECjEnterprise database failed.: javax.naming.NameNotFoundException: jdbc/SPECjOrderDS -- service jboss.naming.context.java.jdbc.SPECjOrderDS
              at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:92)
              at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:177)
              at org.jboss.as.naming.InitialContext.lookup(InitialContext.java:87)
              at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:213)
              at javax.naming.InitialContext.lookup(InitialContext.java:411) [:1.7.0_b147-icedtea]
              at org.spec.jent.loader.DatabaseHelper.getConnection(DatabaseHelper.java:63) [specj.jar:]
              at org.spec.jent.loader.Load.getConnection(Load.java:133) [specj.jar:]
              at org.spec.jent.loader.Load.getConnection(Load.java:122) [specj.jar:]
              at org.spec.jent.loader.Load.loadSequence(Load.java:163) [specj.jar:]
              at org.spec.jent.loader.LoadOrders.loadSequences(LoadOrders.java:124) [specj.jar:]
              at org.spec.jent.loader.LoadTracker.start(LoadTracker.java:52) [specj.jar:]
              at org.spec.jent.loader.LoaderServlet.doGet(LoaderServlet.java:121) [classes:]
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:734) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:]
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:]
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.6.Final.jar:]
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.6.Final.jar:]
              at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.6.Final.jar:]
              at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.6.Final.jar:]
              at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.0.CR1-SNAPSHOT.jar:]
              at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:151) [jboss-as-web-7.1.0.CR1-SNAPSHOT.jar:]
              at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.6.Final.jar:]
              at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.6.Final.jar:]
              at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.6.Final.jar:]
              at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [jbossweb-7.0.6.Final.jar:]
              at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:897) [jbossweb-7.0.6.Final.jar:]
              at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:626) [jbossweb-7.0.6.Final.jar:]
              at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:2033) [jbossweb-7.0.6.Final.jar:]
              at java.lang.Thread.run(Thread.java:722) [:1.7.0_b147-icedtea]
      
      

       

      From my understanding this means the code is calling ctx.lookup("jdbc/SPECjOrderDS") but the call is going to java:jdbc/SPECjOrderDS instead of java:comp/env/jdbc/SPECjOrderDS. The DatabaseHelper class is in specj.jar however the LoaderServlet is in specj.war. The application is deployed as spec.ear with with the following content.

       

       

      jar -tf specj.ear 
        META-INF/
        META-INF/application.xml
        META-INF/MANIFEST.MF
        specj.war
        supplier.war
        specj.jar
        lib/
        lib/generated-ws-buyer.jar
      

       

      specj.war's web.xml has the following resource references

       

        <resource-ref> 
          <res-ref-name>jdbc/SPECjOrderDS</res-ref-name> 
          <jndi-name>java:jboss/jdbc/SPECjOrderDS</jndi-name> 
        </resource-ref>
        <resource-ref> 
          <res-ref-name>java:jdbc/SPECjOrderDS</res-ref-name> 
          <jndi-name>java:jboss/jdbc/SPECjOrderDS</jndi-name> 
        </resource-ref>
      
      

       

      I realize the ideal situation would be to just change the code to call lookup("java:jboss/jdbc/SPECjOrderDS") however it would be better and easier to find a solution that focuses on configuration changes.

      I also thought all calls to lookup() from a Servlet but without a fully qualified context default to java:comp/env, is that incorrect?

       

      Thanks to everyone who can take a look and help me better understand the situation.

        • 1. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
          jaikiran

          I'll have to look at the code with the exact lookup string being used to understand better. Can you please post that relevant part?

           

          Will Reichert wrote:

           

           

          specj.war's web.xml has the following resource references

           

            <resource-ref> 
              <res-ref-name>jdbc/SPECjOrderDS</res-ref-name> 
              <jndi-name>java:jboss/jdbc/SPECjOrderDS</jndi-name> 
            </resource-ref>
            <resource-ref> 
              <res-ref-name>java:jdbc/SPECjOrderDS</res-ref-name> 
              <jndi-name>java:jboss/jdbc/SPECjOrderDS</jndi-name> 
            </resource-ref>
          
          

           

          Although, I don't know the application, I'm guessing that the second resource-ref is probably not required. It's probably there because someone might have been unsure about what JNDI name to use during lookup.

           

           

          Will Reichert wrote:

           

          I realize the ideal situation would be to just change the code to call lookup("java:jboss/jdbc/SPECjOrderDS")

          Actually, that's not an ideal change Infact not even recommended. One of the reasons why the ENC (environment naming context) is available for components is to make sure that the code doesn't have to change when the application is deployed on some other container which has its own JNDI naming scheme (like JBoss AS). So the ENC allows you to map the application specific resource jndi names to logical jndi names (which won't change across application servers because those logical jndi names are defined by your application) via the deployment descriptors (or sometimes in annotations). So the ideal code would do a java:comp/env/<somejndiname> namespace lookup in the component and let the deployment descriptors map that logical jndi name to the real (container specific) jndi name.

           

           

          Will Reichert wrote:

           

          I also thought all calls to lookup() from a Servlet but without a fully qualified context default to java:comp/env, is that incorrect?

           

           

          No, the lookup() doesn't default it to any component specific namespace.

          • 2. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
            jaikiran

            jaikiran pai wrote:

             

            Will Reichert wrote:

             

            I also thought all calls to lookup() from a Servlet but without a fully qualified context default to java:comp/env, is that incorrect?

             

             

            No, the lookup() doesn't default it to any component specific namespace.

            Actually, let me rephrase that a bit. The EE spec says nothing about redirecting unqualified namespace jndi lookup (like: "jdbc/foo") to java:comp/env namespace. However, sometime back, for AS7 we kind of decided that unqualified lookups would default to java:comp/env in AS7 because we don't support unqualified (sometimes known as global) jndi name lookups. But I'm not sure if it has been implemented. Even if it was, I wouldn't expect a portable spec testing code (like the application you are using) to rely on this behaviour. So the correct lookup would have to use java:comp/env

            • 3. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
              willreichert

              Thanks for the help and clarification. I restarted the server and then couldn't get the exception to occur again so now I'm on the next challenge in getting the spec application up and running.  Thank you again for the help

              • 4. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
                willreichert

                It seems this problem is occuring again with a build of the latest code from master. The JNDI lookup is performed with the following code in DatabaseHelper.java:

                 

                            try {
                                logger.log(Level.FINE, "Looking up data source " + name + " for loading SPECjEnterprise database.");
                                dataSource = (DataSource) (new InitialContext()).lookup(name);
                                return getConnection(dataSource);
                            } catch (NamingException e) {
                                logger.log(Level.FINE, "Lookup of data source " + name + " for loading SPECjEnterprise database failed.", e);
                            }
                

                 

                I removed the extra resource-ref definition in web.xml and created a sample application that would let me perform the lookup based on a servlet parameter:

                 

                String jndi = request.getParameter("jndi");
                DataSource dataSource = null;
                response.getWriter().println("Executed Loader "+new Date());
                response.getWriter().println("getting Connection for "+jndi);
                try {
                     dataSource = (DataSource) (new InitialContext()).lookup(jndi);
                     response.getWriter().println("connection created! "+jndi);
                } catch (NamingException e) {
                     response.getWriter().println("Exception!!!");
                     e.printStackTrace(response.getWriter());
                }
                

                 

                The servlet showed that performing the lookup on jdbc/SPECjOrderLoaderDS would not work but if I passed in java:comp/env/jdbc/SPECjOrderLoaderDS then the lookup succeeded. Does this mean that unqualified JNDI lookups are not mapping to the same context as the definitions in web.xml?

                • 5. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
                  jaikiran

                  Will Reichert wrote:

                   

                  The servlet showed that performing the lookup on jdbc/SPECjOrderLoaderDS would not work but if I passed in java:comp/env/jdbc/SPECjOrderLoaderDS then the lookup succeeded. Does this mean that unqualified JNDI lookups are not mapping to the same context as the definitions in web.xml?

                  Yeah, for a portable application, the spec mandates the use of the namespace. So in this case, a portable application must use java:comp/env/jdbc/SPECjOrderLoaderDS.

                  • 6. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
                    willreichert

                    Oh, I didn't realize the spec requried a namespace, I thought it would default to comp/env if there was not an explicit namespace. Do you happen to have a link to the spec handy? I will need to try and argue for a chance to the SpecJ application if it needs to include java:comp/env before all local lookups. Does that apply to all JNDI lookup (I assume so) so looking up jms/Queue would not match the following?

                     

                       <resource-ref>
                         <res-ref-name>jms/Queue</res-ref-name>
                         <jndi-name>java:jboss/jms/Queue</jndi-name>
                       </resource-ref>
                    

                     

                    Did previous versions of JBoss or builds of 7.1 assume java:comp/env for lookups without a namespace? I ask becuase the issue disappeared for a while and returned with the latest form master.

                     

                    As a side to this, I know it was common for developers to write applications that assumed JNDI lookup would default to the java:comp/env namespace so we may want to consider an error message that explians why the JNDI failed. I was failry confused about the failing JNDI because I had what I thought was the appropriate configuration in web.xml. Perhaps the error message could detail that the lookup for "jndiName" did not have an explicit namespace (e.g. java:comp/env/)?

                    • 7. Re: NameNotFoundException for ctx.lookup("jdbc/SPECjOrderDS")
                      sfcoy

                      The JEE6 spec can be found at Java™ Platform, Enterprise Edition (Java EE) Specification, v6. See chapter 5.

                       

                      All JNDI names in deployment descriptors such as res-ref-name, ejb-ref-name and env-entry-name have always been in the java:comp/env context (the so called environment naming context or ENC). The old J2EE 1.3 and 1.4 specs contain much the same language on this (1.2 was before my time!). The JEE5 spec updated the text to include the requirements for injection. JEE6 updated this again to include all the new namespaces such as java:app, java:module, etc.

                       

                      What commonly happens is that many developers have no notion of the ENC whatsoever and they match up these names with those in the old (pre JEE6) global namespace. Fixing this was always a first port of call when migrating an application from another vendor to JBoss because up until relatively recently JDBC datasources for example were required to be in the java: namespace on JBoss.