6 Replies Latest reply on Jun 28, 2011 3:05 PM by wdfink

    Clustered EJB on AS 5.1

    vdeminico

      Hi,

      I have a problem executing a @Clustered ejb on a cluster. Cluster has two nodes executing on different machines and it's correctly configured (log says that there are two members). I use Jboss 5.1.0GA AS.

       

      Code for clustered ejb 3.0 is:

       

       

      import javax.ejb.Stateless;

       

       

      import org.apache.log4j.Logger;

      import org.jboss.ejb3.annotation.Clustered;

       

       

      /**

      * Session Bean implementation class TimsocialClusteredProva

      */

      @Stateless(name="clusteredEjb")

      @Clustered

      public class TimsocialClusteredProva implements TimsocialClusteredProvaRemote {

                private static Logger log = Logger.getLogger(TimsocialClusteredProva.class);

          /**

           * Default constructor.

           */

          public TimsocialClusteredProva() {

              // TODO Auto-generated constructor stub

          }

       

       

                public String sayHello(String nome) {

                          log.info("Param: " + nome);

                          return "Hello " + nome;

                }

       

       

      }

       

       

      and remote interface is:

       

       

      import javax.ejb.Remote;

       

       

      @Remote

      public interface TimsocialClusteredProvaRemote {

                public String sayHello(String nome);

      }

       

       

       

      The client is a servlet deployed into the same ear:

       

       

          protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

                    String ejbName = null;

                    String jndiService = request.getParameter("jndi");

                    TimsocialClusteredProvaRemote clusteredEjb=null;

                          try {

                                    Properties properties = new Properties();

                        properties.put("java.naming.factory.initial",

                            "org.jnp.interfaces.NamingContextFactory");

                        properties.put("java.naming.factory.url.pkgs",

                            "org.jboss.naming");

                        properties.put("java.naming.provider.url", jndiService);

                       

                        Context ctx = new InitialContext(properties);

                       

                                    ejbName = "timsocial-ear-0.0.1-SNAPSHOT/clusteredEjb/remote";

                                    log.debug("Fetching remote ejb: " + ejbName);

                                    clusteredEjb = (TimsocialClusteredProvaRemote) ctx

                                                        .lookup(ejbName);

                          } catch (NamingException e) {

                                    log.error("Error in lookup ejb with jndi-name: " + ejbName, e);

                          }

       

                    for (int i=0;i<100;i++) {

                              log.info(clusteredEjb.sayHello(i + "Valerio "));

                    }

          }

       

       

      I invoke servlet with "jndi" parameter setted to HA-JNDI or local JNDI... but the result is always the same: all invocations are executing on a single server (the one local to servlet).

       

      When EJB is deployed, this message is displayed into AS console log:

       

       

      2011-06-28 10:59:52,515 DEBUG [org.jboss.ha.framework.server.HATarget] (AsynchKeyChangeHandler Thread) replicantsChanged 'jboss.j2ee:ear=timsocial-ear-0.0.1-SNAPSHOT.ear,jar=timsocial-ejb-0.0.1-SNAPSHOT.jar,name=clusteredEjb,service=EJB3socketDefaultPartition' to 1 (intra-view id: 1554486437)

       

      What is wrong????

       

      Thanks.

      Valerio.

        • 1. Re: Clustered EJB on AS 5.1
          wdfink

          How do you get the initial context? Every time new without cache the reference to the SLSB?

          In this case the call will be hit the server from which the JNDI context is, the second will be loadbalanced.

           

          Also I'm not sure whether calls to the same application are routed to a remote instance! This will make no sense because the remote call is more expensive and (as you are on a running server ) the local server is alive.

          • 2. Re: Clustered EJB on AS 5.1
            vdeminico

            Thanks for your reply...

            I cache the initial context and 

             

            This is my ServiceLocator code:

             

            public class ServiceLocator {
                      private static Context ctx = null;
              
                      public static Context getServiceLocator() throws NamingException {
                                if (ctx==null) {
                                          Properties properties = new Properties();
                              properties.put("java.naming.factory.initial",
                                  "org.jnp.interfaces.NamingContextFactory");
                              properties.put("java.naming.factory.url.pkgs",
                                  "org.jboss.naming");
                              properties.put("java.naming.provider.url", "10.188.47.201:1099,10.188.47.202:1099");
                              
                              ctx = new InitialContext(properties);
                                }
                                return ctx;
                      }
            
            
            }
            
            

             

            and every time I do a lookup to the Context to retrieve the proxy. It should be loadbalanced...

            I agree with you... maybe JBoss understand that ejb is local and so it doesn't invoke remote one. But I need this (strange) behaviour because there's a shared jboss cache where these ejbs asynchronously write data and another application component reads...

            Is there a method to clusterize this ejb??????? (avoiding to change architecture......)

             

            Thanks,

            Valerio.

            • 3. Re: Clustered EJB on AS 5.1
              wolfc

              The (Clustered)IsLocalInterceptor will always prefer the local EJB. You can remove then from ejb3-interceptors-aop.xml if you want to.

              • 4. Re: Clustered EJB on AS 5.1
                wdfink

                Ok,

                as Carlo noting you might be able to remove the 'isLocalInterceptor'.

                But I did not understand the necessity exactly.

                I suppose that you try to update the cache on the other node, but I strongly recommend to use an architecture without such.

                Because I've seen such implementations and have always trouble with the non deterministic behaviour. If you have two nodes it might work for the moment. But you must aware for each JBoss update/config change or application change. And from my experience this will be forgotten or ignored and the application becaome unmaintainable.

                1 of 1 people found this helpful
                • 5. Re: Clustered EJB on AS 5.1
                  vdeminico

                  Thanks for your replies...

                  I have strong performance requirements and the necessity to execute concurrently on all nodes the clustered ejb (they connect externally and aggregates data, writing them into the jboss cache). Clustered ejbs are executed asynchronously, invoked by a MDB. Data are fetched from jboss cache on demand. The requirement is to have fresh and up-to-date data to return (and the refresh is done by cluster ejbs).

                   

                  Maybe I could use an architecture with a clustered jms. The question is: what about MDBs deployed on different cluster nodes? When I send a message to the JMS clustered queue, which MDB take it????? I suppose the local one.........

                   

                  Valerio.

                  • 6. Re: Clustered EJB on AS 5.1
                    wdfink

                    Each cache will have the drawback of being asynchronous.

                    It doesn't matter whether you use JBoss cache or MDB.

                    Also if I think about your 'clustered MDB' idea, if it is done by a topic and a MDB on each node which watch this it will be still async. There is a delay between your update method is finished and other calls use the data at different instance (I have a similar problem).

                     

                    My solution is to use a transactional update to RDBMS ( use Oracle) and the update use XA-Transaction (depend on different EA integration).

                    If the call is finished it it ensured that the DB is commited, all other cluster instances (EJBs) use the database directly.

                    Also the internal mechanism of cache refreshing or invalidation is slow in case of frequent updates.

                     

                    I only use caches if I'm sure that the data is readonly in 99%.