4 Replies Latest reply on Sep 2, 2004 3:26 AM by twwwt

    How to access HA Singleton MBean clusterwide via EJB

    twwwt

      Hello!

      I'm trying to access a HA Singleton MBean from session EJBs but experiencing a problem which really makes me ill. First the EJB looks up the RMIAdaptor:

      Properties properties = new Properties();
      properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
      properties.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
      properties.put(Context.PROVIDER_URL, "jnp://localhost:1100");
      try
      {
       Context context = new InitialContext(properties);
       Object o = context.lookup("jmx/invoker/RMIAdaptor");
       mbeanServer = new RMIConnectorImpl((RMIAdaptor) o);
      }
      catch (NamingException e)
      {
       handleException(e);
      }
      



      Then I test wheter the singleton service is registered before invoking methodes on the service:

      ObjectName name = new ObjectName("myDomain:service=MyService");
      Boolean ok = mbeanServer.isRegistered(name);
      if (ok)
      {
       Object result = mbeanServer.invoke(...);
      }
      


      The problem is on the nodes which are currently not master. As expected "isRegistered()" returns false and I can't invoke the MBean. On the node which is master everything works fine.
      And now, most incomprehensible to me is that nearly the same code put in a simple test class works really ok:

      String port = "1100";
      String[] clusterMembers = {"192.168.2.10", "192.168.2.25", "192.168.2.30"};
      ObjectName name = new ObjectName("myDomain:service=MyService");
      RemoteMBeanServer server = null;
      int i = 0;
      while (i < hosts.length)
      {
       properties.put(Context.PROVIDER_URL, "jnp://" + hosts + port);
       Context context = new InitialContext(properties);
       Object o = context.lookup("jmx/invoker/RMIAdaptor");
       server = new RMIConnectorImpl((RMIAdaptor) o);
       if (server.isRegistered(name))
       {
       System.out.println(i + " " + clusterMembers + " " + server.isRegistered(name));
       System.out.println(server.getAttribute(name, "MasterNode").toString());
       }
       i++;
      }
      


      For every loop the isRegistered() returns true and "MasterNode" is also true. The conclusion to me is that for the EJB I get somthing like a "local" RMIAdaptor with the HA singleton service available only on the master node. For the test class, started in another VM, I always get something like a "global" RMIAdaptor with the HA singleton service available.
      Is that correct? Or do I completely mixed something up.

      And most importantly: What is the "safe" way to access HA singleton MBean from EJBs.

      (Please note that all the nodes really build ONE cluster, i.e. they find each other and I can see messages on the console telling me that too.)

      Thanks a lot for your answers.

      Oh, I forgot to say that I use V3.2.6RC1.

      Thorsten

        • 1. Re: How to access HA Singleton MBean clusterwide via EJB

          Thorsten;

          Try this: When a the HASingleton starts (which will only happen on the master node) create an HA RMI Stub and bind it into HA-JNDI.

          That way, all your cluster nodes can look up the stub in one place and invocations against it will go against the correct node.

          When another node takes over, it will overwrite its own HA RMI stub into HA-JNDI.

          //Nicholas

          • 2. Re: How to access HA Singleton MBean clusterwide via EJB
            twwwt

            Thanks Nicholas for your Answer. But what do you exactly mean by "Stub"? Yesterdy I tryed to bind the service itself into JNDI with no success.

            Excerpt from MBeans startSingleton():

            Name n = context.getNameParser("").parse("service/mbean/MyService");
            NonSerializableFactory.rebind(n, this, true);
            


            A lookup on the client (EJB) returned a javax.naming.Reference. So I tryed

            MyService s = (MyService) PortableRemoteObject.narrow(o, MyService.class);
            


            which results in ClassCastException.

            • 3. Re: How to access HA Singleton MBean clusterwide via EJB

              Thorsten;

              Try this:

              1. When your HASingleton starts, look up the jmx/invoker/RMIAdaptor in JNDI and bind it to a new name under HA-JNDI.
              2. All your local EJBs can then look up that adaptor in HA-JNDI and invoke calls against it.
              3. Calls made to that adpator will be invoked aganst the running instance of the HASingleton.
              4. Be sure to implement a retry which re-looks up the adaptor in HA-JNDI in case there is a failover going at the exact time that an instance of the EJB makes the invocation call.

              //Nicholas

              • 4. Re: How to access HA Singleton MBean clusterwide via EJB
                twwwt

                It seems that JBoss gys recocnized this functional gap at last and published a interim solution, see:

                http://www.jboss.org/wiki/Wiki.jsp?page=JBossHASingletonRemoteAccess

                Thorsten