7 Replies Latest reply on Apr 20, 2004 4:03 AM by dannyyates

    JNDI problems mail services tests

    kabirkhan

      Hi,

      I am working on unit tests for the mail services. They run JBoss 3.2.4RC1 "embedded", by calling the following from their setup() method:

       //Start JBoss
       ServerImpl impl = new ServerImpl();
       System.out.println("got the server impl");
       Properties prop = new Properties();
       prop.setProperty(ServerConfig.HOME_DIR,(new File(".")).getAbsolutePath());
       prop.setProperty(ServerConfig.ROOT_DEPLOYMENT_FILENAME,"src/META-INF/depends-service.xml");
       prop.setProperty(ServerConfig.SERVER_CONFIG_URL,"file:"+(new File(".")).getAbsolutePath());
       System.out.println("done setting up properties");
       impl.init(prop);
       System.out.println("impl.init is finished");
       impl.start();
       System.out.println("impl.start done");
       alreadyrun = true;
       System.out.println("done configureMBeanServerFactory");
      
       //Start MBeans
       MBeanServer mbserver = JBMailJMXUtil.locateJBoss();
       ObjectName oname = new ObjectName("jboss.mail:type=MailServices,name=UserRepository");
       StaticUserRepository sur = new StaticUserRepository();
       sur.addUser("acoliver","test");
       sur.addUser("test","testpw");
       sur.addUser("jboss","jbosspw");
       mbserver.registerMBean(sur, oname);
      
       //Start other MBeans here
      
      


      Until now we have been running JNDI with a mock context for JNDI, but since JBoss is actually being started, I am trying to use the existing NamingService, but have run into problems.

      I have set up the jndi.properties file to be:
      java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
      java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
      


      I stepped through the org.jboss.naming.NamingService.startService() method. The first bit loads up the properties from the jndi.properties file and sets them in System.properties, as expected there is no java.naming.provider.url there. Also, when I do a System.getProperty("java.naming.provider.url") at any stage nothing is returned.

      However, once the first InitialContext is created and it's environment got, java.naming.provider.url is there! (i.e. it is in env below, but System.getProperty("java.naming.provider.url") still returns nothing)
      Code:

       InitialContext iniCtx = new InitialContext();
       Hashtable env = iniCtx.getEnvironment();
      




      I followed this through, and new InitialContext()
      calls javax.naming.InitialContext.init() //This initialises the environment for the InitialContext
      which calls javax.naming.internal.ResourceManager.getInitialEnvironment() //"produces" the environment for the InitialContext
      which calls javax.naming.internal.VersionHelper.getJndiProperties()

      VersionHelper.getProperties() looks like this
      
       String[] getJndiProperties() {
       if (getSystemPropsFailed) {
       return null; // after one failure, don't bother trying again
       }
       Properties sysProps = (Properties) AccessController.doPrivileged(
       new PrivilegedAction() {
       public Object run() {
       try {
       return System.getProperties();
       } catch (SecurityException e) {
       getSystemPropsFailed = true;
       return null;
       }
       }
       }
       );
       if (sysProps == null) {
       return null;
       }
       String[] jProps = new String[PROPS.length];
       for (int i = 0; i < PROPS.length; i++) {
       jProps
       = sysProps.getProperty(PROPS
      );
       }
       return jProps;
       }
      
       String getJndiProperty(final int i) {
       return (String) AccessController.doPrivileged(
       new PrivilegedAction() {
       public Object run() {
       try {
       return System.getProperty(PROPS
      );
       } catch (SecurityException e) {
       return null;
       }
       }
       }
       );
       }
      
      


      In this funky looking code (in which to be honest I don't understand the special AccessController/PrivilegedAction bits) java.naming.provider.url and jnp://localhost:1099 are returned. I'm wondering
      a) Why doesn't this appear in JBoss itself when starting that without the java.naming.provider.url in the jndi.properties
      b) What the AccessController stuff does special to magically create the java.naming.provider.url=jnp://localhost:1099
      c) If I change the test target in the ant build file to run only one of the tests, and make that test call ResourceManager.getInitialEnvironment(null).get(Context.PROVIDER_URL) BEFORE I have done anything to start the embbeddd JBoss it still returns a URL.

      I'd like to not have java.naming.provider.url=jnp://localhost:1099, in order to run the naming service "in-jvm" since I am experiencing other problems if I set the Port and RmiPort > -1. If needed I can describe in more detail what they are.

      Any ideas?

      Cheers,

      Kab

        • 1. Re: JNDI problems mail services tests

          Please re-state what your problem is.
          All I see is there is no provider url, which is to be expected since you
          are not using any network connection to access jndi.

          If you are trying to get the host name you should use the system property
          jboss.bind.address

          Why are you registering mbeans yourself instead of using a
          jbossmail-service.xml or whatever you want to call it?

          Regards,
          Adrian

          • 2. Re: JNDI problems mail services tests
            kabirkhan

            I want to run the naming service in the in-jvm mode. No provider url is specified in jndi properties, so a normal System.getProperty() for the provider url does not return anything (as desired). The problem is that the "privileged" ResourceManager/VersionHelper stuff mentioned below gets jnp://localhost:1099 for the provider url despite this not being specified anywhere that I can see. So my question is where could this value come from when it is got using "priviledged access"?

            Re "Why are you registering mbeans yourself instead of using a
            jbossmail-service.xml or whatever you want to call it?"
            It's just the way the mail service is set up at present. We register the mail service MBeans required for each test. All other normal JBoss MBeans depended on are set up in a depends-service.xml. (I suppose that we could have registered mail service MBeans in the xml file as well, but these MBeans sometimes need different parameters for the individual tests so we register them manually and stop and start the server for each test)

            • 3. Re: JNDI problems mail services tests

              You have a jndi.properties somewhere.

              Try Thread.currentThread().getContextClassLoader().getResources("jndi.properties");

              On XML vs programmatic, you can do that just as easily redeployng xml files.

              Regards,
              Adrian

              • 4. Re: JNDI problems mail services tests
                kabirkhan

                Thanks Adrian,

                The line of code you suggested showed we had an additional jndi.properties file hidden away in a jar file on the classpath!

                Now when I try to do

                InitialContext ctx = new InitialContext();
                ctx.bind("test/xyz", "xyz");


                I get the following error:
                javax.naming.NameNotFoundException: test not bound
                at org.jnp.server.NamingServer.getBinding(NamingServer.java:495)
                at org.jnp.server.NamingServer.getBinding(NamingServer.java:503)
                at org.jnp.server.NamingServer.getObject(NamingServer.java:509)
                at org.jnp.server.NamingServer.bind(NamingServer.java:90)
                at org.jnp.interfaces.NamingContext.bind(NamingContext.java:488)
                at org.jnp.interfaces.NamingContext.bind(NamingContext.java:459)
                at javax.naming.InitialContext.bind(InitialContext.java:355)
                at org.jboss.mail.maillistener.TestJMSMailListener.setUp(TestJMSMailListener.java:72)
                at org.jboss.mail.maillistener.TestJMSMailListener.main(TestJMSMailListener.java:58)

                I can get around this by creating the "test" subcontext myself:

                InitialContext ctx = new InitialContext();
                Context sctx = ctx.createSubcontext("test");
                sctx.bind("xyz", "xyz");


                Should it be possible to call ctx.bind("test/xyz", "xyz"); as done in my first example, or is the second example "the way to do it"?

                Cheers,

                Kab

                • 5. Re: JNDI problems mail services tests

                  What happens if you try:

                  ctx.bind("test","test");
                  ctx.bind("test/xyz", "xyz");

                  I'm honestly not sure if JNDI supports adding leaves with non-existing parents. In theory, it could add it, but I know an OpenLDAP store won't let you do it.

                  Steve

                  • 6. Re: JNDI problems mail services tests
                    kabirkhan

                    Had a look, and it seems the way I did it is what is normally done. I had just assumed
                    ctx.bind("test/xyz", "xyz")
                    would create the subcontexts needed. At least now I know that is not the case!

                    • 7. Re: JNDI problems mail services tests
                      dannyyates

                      It never ceases to amaze me the amount of things people seem to "guess" and "try" and then when it doesn't work they spend ages asking on mailing lists and waiting for replies.

                      I spent 24 seconds (I timed it) going to the J2SE online documentation and looking for javax.naming.InitialContext.bind(). There are 2 sentances in the documentation, so it's pretty much impossible to miss the one which reads "All intermediate contexts and the target context [...] must already exist".

                      In fact, it's taken me longer to type this reply than to find the answer to the question. A waste of everybody's time, no?