12 Replies Latest reply on Apr 11, 2002 9:58 AM by Radu Mateescu

    JNDI lookup ?

    Nitin Newbie

      Here is the problem :

      I am using a class which invokes a bean using jndi
      java://comp/env/ejb/account/Account , when I am using this within bean container then this gets invoked , the code
      is written in x class which is getting called when bean is invoked .

      public class x {

      public static void getJndi() {
      InitialContext inc=new InitialContext();
      String classname=inc.lookup("java://comp/env/ejb/account/Account");
      Class.forName(classname).newInstance();
      }

      }

      this gets invoked when x.getJndi() is called within bean , bean can access because , for InitialContext - If you use the class to retrieve the EJB in the same container, you can simply pass null or ignore them.
      like InitialContext inc=new InitialContext();


      But how I invoke this getJndi() method without using ejb container,as specified in java documentation if "All parameters are the environment values for creating the initial context, which include the initial context factory, provider URL, user ID, and password then context can be invoked even from simple java code" , but In my case I don't have IntialContext with parameters ? so please could anybody gives me solution , by which I can invoke getJndi even from normal class.

        • 1. Re: JNDI lookup ?
          Radu Mateescu Newbie

          try the following code:

          Properties h = new Properties();
          h.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
          h.put(Context.PROVIDER_URL, "localhost:1099");
          h.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
          try {
          jndiContext = new InitialContext(h);
          }
          catch(Exception exc) {}

          • 2. Re: JNDI lookup ?
            David Jencks Master

            You can access java:/comp/env when called from an ejb because you are in the same thread as the ejb and the thread context classloader is that of the ejb. I would not assume this would be portable across app servers. However, the java: namespace can only be accessed from in-vm, and the comp/env context is private to the ejb it is set up for. So you should expect not to be able to access any java: bindings from another vm nor any java:/comp/env from anywhere other than the ejb they are set up for.

            Use the global ejb binding name.

            • 3. Re: JNDI lookup ?
              Nitin Newbie

              Thanks davidjencks ,

              I tried with global binding name , still I am not able to access jndi , error I get is - account not bound

              Here is the code :
              import java.io.IOException;
              import java.io.PrintWriter;
              import java.util.Enumeration;
              import javax.servlet.*;
              import javax.servlet.http.*;
              import javax.naming.*;
              import java.util.*;

              public class test1 extends HttpServlet {
              public void doGet(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException
              {
              PrintWriter out = response.getWriter();
              out.println("TESTING..................");
              out.println("\nInside doGet method");
              System.out.println("TESTING..................");
              System.out.println("\nInside doGet method");
              try {
              Hashtable env=new Hashtable();
              env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
              env.put(Context.PROVIDER_URL,"t3://localhost:7001");
              jndiContext = new InitialContext(env);
              Hashtable hash = jndiContext.getEnvironment();
              jndiContext.bind("java:/comp/env/ejb/account/Account",(Object)"");
              } catch (NamingException e) {
              System.out.println("Could not create JNDI " +
              "context: " + e.toString());
              System.exit(1);
              }
              getDAO();
              }



              public AccountDAO getDAO() throws AccountDAOSysException {

              AccountDAO acctDao = null;
              try {

              InitialContext ic = new InitialContext();
              String home = (String) ic.lookup ("java://comp/env/ejb/account/Account");

              } catch (NamingException ne) {
              } catch (Exception se) {
              System.out.println("se"+se);
              }
              return acctDao;
              }

              Please let me know , if I am doing wrong ?
              please send me comments,suggestions!!

              -- Thanks In Advance

              • 4. Re: JNDI lookup ?
                Radu Mateescu Newbie

                In doGet, you bind a jndi object to weblogic context
                In getDao, you try to retrieve that object from your default context which is not necessarily the context where you added the reference.
                Besides, as David said, the "java:" namespace is reserved for internal VM (i.e. you can't access it from outside that VM). Try to bind a name without "java://comp/env" in the beginning and use the same context for bind and lookup (in getDao, instead of new InitialContext(), use the code from doGet. or, easier, initialize the jndiContext in init() method of your servlet and use it everywhere)

                • 5. Re: JNDI lookup ?
                  Nitin Newbie

                  Thanks All,

                  Here is the problem , the code which I had given is simulating same enviornment in servlet , actual problem is , I have a getDAO method in class AccountX which has InitialContext without parameters , I am trying to do reflection on AccountX class , without ejb container so I am getting exception "account not bound" , so I need solution which says do some initial settings required and then do reflection on AccountX and invoke method getDAO which has InitialContext without parameters.

                  -- Thanks In Advance.

                  • 6. Re: JNDI lookup ?
                    Radu Mateescu Newbie

                    a Context is a set of name-to-object bindings
                    Most application servers implements a jndi repository. If you want to connect to that repository, you need to specify some properties (that hashtable transmitted as parameter to InitialContext). It is possible to use the no-parameter contructor of InitialContext, but you need to specify those properties in a property file called jndi.properties, which has to be in your classpath. For more informations, check the JavaDoc for InitialContext at http://java.sun.com/j2se/1.3/docs/api/javax/naming/InitialContext.html

                    So, if you want to connect to jndi without hard-coding those properties in your class, create a file called jndi.properties and add it to your classpath. From an application server you can create an initial context without parameters because the jndi.properties is already in the apps classpath.
                    Radu

                    • 7. Re: JNDI lookup ?
                      Nitin Newbie

                      Thanks for suggestions - I tried and got following error

                      Error on Execution
                      ====================

                      TESTING.................. Inside doGet method
                      Error: 500
                      Location: /test/servlet/testingAccount
                      Internal Servlet Error:

                      com.snstech.account.exceptions.AccountException: AccountX.getDAO: NamingException while getting DAO type :
                      env not bound
                      at com.snstech.account.dao.AccountX.getDAO(AccountX.java:32)
                      at testingAccount.doGet(testingAccount.java:24)
                      at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
                      at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
                      at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:405)
                      at org.apache.tomcat.core.Handler.service(Handler.java:287)
                      at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)
                      at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:812)
                      at org.apache.tomcat.core.ContextManager.service(ContextManager.java:758)
                      at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:213)
                      at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)
                      at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:501)
                      at java.lang.Thread.run(Thread.java:484)


                      Execution Path
                      =================

                      1) Created testingAccount.java
                      2) Set classpath for jndi.properties in run.bat.


                      testingAccount.java
                      ====================

                      import javax.naming.NamingException;
                      import javax.naming.InitialContext;
                      import com.snstech.account.dao.*;


                      import com.snstech.account.exceptions.AccountException;
                      import java.io.IOException;
                      import java.io.PrintWriter;
                      import java.util.Enumeration;
                      import javax.servlet.*;
                      import javax.servlet.http.*;
                      import javax.naming.*;
                      import java.util.*;

                      public class testingAccount extends HttpServlet {
                      public void doGet(HttpServletRequest request, HttpServletResponse response)
                      throws ServletException, IOException
                      {
                      PrintWriter out = response.getWriter();
                      out.println("TESTING..................");
                      out.println("\nInside doGet method");
                      System.out.println("TESTING..................");
                      System.out.println("\nInside doGet method");
                      com.snstech.account.dao.AccountX.getDAO();
                      }

                      }


                      com/snstech/account/dao/AccountX.java
                      =====================================


                      package com.snstech.account.dao;

                      import javax.naming.NamingException;
                      import javax.naming.InitialContext;

                      import com.sun.j2ee.blueprints.customer.util.JNDINames;
                      import com.snstech.account.exceptions.AccountException;

                      public class AccountX {
                      public static Account getDAO() throws AccountException {
                      String static final JNDI_NAME="java:comp/env/ejb/account/Account";
                      Account acctDao = null;
                      try {
                      InitialContext ic = new InitialContext();
                      String className = (String) ic.lookup(JNDI_NAME);
                      acctDao = (Account) Class.forName(className).newInstance();
                      } catch (NamingException ne) {
                      throw new AccountException("AccountX.getDAO: NamingException while getting DAO type : \n" + ne.getMessage());
                      } catch (Exception se) {
                      throw new AccountException("AccountX.getDAO: Exception while getting DAO type : \n" + se.getMessage());
                      }
                      return acctDao;
                      }
                      }


                      setting jndi properties
                      ==========================

                      set classpath=%classpath%;D:\JBoss\jboss\admin\client\jndi.properties

                      Still hunting in the bush!!! Please help!!!

                      -- Thanks In Advance

                      • 8. Re: JNDI lookup ?
                        Radu Mateescu Newbie

                        you are looking for java:comp/env/ejb/account/Account but this component is accessible only within the same VM as the application server, from an EJB for instance. All objects registered under "java:" namespace are NOT accessible from outside. Try to access another component from the global namespace (something which does not start with "java:")

                        • 9. Re: JNDI lookup ?
                          Radu Mateescu Newbie

                          can I also see your jndi.properties?

                          • 10. Re: JNDI lookup ?
                            Radu Mateescu Newbie

                            and one more thing related to how an initial context builds its environment (see the link to JavaDoc from above): If there are multiple parameters with the same name (like URL of jndi repository), the first one is considered, respecting the following order:

                            1: takes the properties transmitted as parameters
                            2: uses the System properties
                            3: takes the application property file (that jndi.properties)

                            If you use Tomcat (you didn't specify), the instruction InitialContext initialContext = new InitialContext() has the following effect:
                            instead of reading your jndi.properties as expected, it will take first the information from System properties (see the order above). Well, the Tomcat stores all its jndi parameters in the System.properties. Obviously, you are connected to the tomcat context instead of the JBoss context. If you really want to connect to jboss context, do the following:
                            1. specify the JBoss jndi in your code (priority no 1 in the list above) as follows:

                            h.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
                            h.put(Context.PROVIDER_URL, "JBOss_computer:1099");
                            h.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");

                            2. forget about "java:" namespace. You won't be able to access it from outside jboss VM

                            I think you tried only the first

                            • 11. Re: JNDI lookup ?
                              Nitin Newbie

                              Thanks .. Thanks alot , here is jndi.properties file
                              which is in JBoss not in Tomcat .

                              jndi.properties
                              ===============
                              java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
                              java.naming.provider.url=localhost:1099
                              java.naming.factory.url.pkgs=org.jboss.naming

                              Can I get "java:" namespace using some initial properties settings in the code.

                              --- Thanks In advance.

                              • 12. Re: JNDI lookup ?
                                Radu Mateescu Newbie

                                I'm afraid you can't access "java:" namespace from outside jboss VM. Specifying those initial settings in the code will give them priority over another jndi settings, like system properties and jndi.properties. If you want to connect to JBoss repository, you have to "beat" the Tomcat repository settings which are stored in system properties. You have 2 choices : either change the system properties to connect to JBoss or add those initial settings in the code. You cannot rely in this case on jndi.properties, because it is "weaker" then how tomcat stores its jndi parameters.
                                If you really nead to access a "java:" namespace in jboss, you have to create the context and make the lookup from the same VM (from an EJB). I don't know what happens when jboss and tomcat run in the same VM