2 Replies Latest reply: May 16, 2012 7:25 AM by Arnold Johansson RSS

selectNode() of a ClusterNodeSelector isn't executed

Arnold Johansson Apprentice

Hi Jaikiran and community!

 

This is in continued reference to my late question in

https://community.jboss.org/message/734538

Problem

The selectNode() method of an implemented ClusterNodeSelector isn't called despite its constructor being found and executed.

Platform

JBoss AS 7.1.2.Final

Setup

  • An EAR (sample-jee.ear) deployed on two separate AS instances. This EAR contains clustered EJB:s (by anotation).
  • An EAR (sample-jee-client.ear) deployed on a separate AS instance. This EAR contains a Servlet that calls an EJB in the cluster.

Reproduce problem

To reproduce the behavior perform the following steps...

 

1. Download the sample project from

https://github.com/swesource/sample-jee

 

2. Run 'mvn install' to build the project (from its root directory)

 

3. Create a user 'admin' with password 'admin2'.

For this example it's been created both for Management and Application realms.

 

4. Copy the attached standalone-xml to JBOSS_HOME/standalone/configuration/

It is a standard standalone-xml equiped with the needed server-klient--to--server communication setup.

 

5. Start the following three AS 7.1.2.Final servers as instructed

 

node1

$JBOSS_HOME/bin/standalone.sh -Djboss.socket.binding.port-offset=0 --server-config standalone-ha.xml -Djboss.node.name=node1

 

 

node2

$JBOSS_HOME/bin/standalone.sh -Djboss.socket.binding.port-offset=500 --server-config standalone-ha.xml -Djboss.node.name=node2

 

 

client1

$JBOSS_HOME/bin/standalone.sh -Djboss.socket.binding.port-offset=1000 --server-config standalone.xml -Djboss.node.name=client1

 

 

6. Deploy the EAR of the sample-jee-server-ear project (sample-jee/sample-jee-server-ear/target/sample-jee-server.ear) in node1 and node2

This will create a set of clustered EJB:s

 

7. Deploy the EAR of the sample-jee-client-project (sample-jee/sample-jee-client-ear/target/sample-jee-client.ear) in client1

 

8. From a browser use the URL:

http://localhost:9080/sample-jee-client/SlsbClientServlet

 

9. Look at the console output of client1.

I get an output saying that the constructor is executed...

 

***** RoundRobinClusterNodeSelector created

 

...but no more messages are displayed from the selector as (successful) calls are being made.

 

It should show lines starting with:

 

***** RoundRobinClusterNodeSelector::selectNode

 

Additional information

All things work fine (clustering, communication, failover etc) except for the invocation of my implemented ClusterNodeSelector.selectNode()-method.

But the strange thing is that the constructor of my ClusterNodeSelector is called but not the selectNode()-method!

-So the class is (probably?) configured and instantiated correctly?


The selector class is located in

 

sample-jee/sample-jee-client-util/src/main/java/com/swesource/sample/jee/jbossas7/clustering/RoundRobinClusterNodeSelector.java

 

 

and it is configured in

 

sample-jee/sample-jee-client-ear/src/main/application/META-INF/jboss-ejb-client.xml

 

 

 

Kind Regards

/Arnold

  • 1. Re: selectNode() of a ClusterNodeSelector isn't executed
    jaikiran pai Master

    I had a look at your code and your web client servlet looks up the bean proxy on each invocation https://github.com/swesource/sample-jee/blob/master/sample-jee-client-web/src/main/java/com/swesource/sample/jee/web/SlsbClientServlet.java#L48 which means that any cluster topology information affinity for that proxy is lost during the next invocation. So I changed the servlet code to do the lookup only once in the init() of the servlet:

     

     

    @WebServlet(value = "/SlsbClientServlet")
    public class SlsbClientServlet extends HttpServlet {
        
        private ServerSlsbRemote beanProxy;
        
        @Override
        public void init() throws javax.servlet.ServletException {
            try {
                final Hashtable props = new Hashtable();
                // setup the ejb: namespace URL factory
                props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
                // create the InitialContext
                final Context context = new javax.naming.InitialContext(props);
    
                // Lookup the SlsbOne bean using the ejb: namespace syntax which is explained here
                // https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
                
                // For remote ejbs (other container)
                String path = "ejb:sample-jee-server/sample-jee-server-ejb-1.0-SNAPSHOT//ServerSlsbBean!com.swesource.sample.jee.ServerSlsbRemote";
                this.beanProxy = (ServerSlsbRemote) context.lookup(path);
    
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            invokeOnBean();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String greeting = invokeOnBean();
            PrintWriter pw = response.getWriter();
            pw.write("SlsbClientServlet -> ServerSlsbBean.sayHello (in remote EAR) -> SlsbClientServlet -> [" + greeting + "]\n");
            //String callResponse = invokeOnRelayBean();
            //pw.write("SlsbClientServlet -> SlsbRelayBean.called (in remote EAR) -> SlsbOneBean.sayHello (in remote EAR) -> SlsbClientServlet -> [" + callResponse + "]\n");
            pw.flush();
            pw.close();
        }
    
        private String invokeOnBean() {
            try {
                // invoke on the bean
                final String greeting = this.beanProxy.sayHello();
                System.out.println("SlsbClientServlet: Received greeting: " + greeting);
                return greeting;
    
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    

     

    That'll allow the proxy to hold on to the cluster weak affinity associated with the bean and that should let the EJB client API know that it has to allow the cluster node selector to select a node from the cluster.

  • 2. Re: selectNode() of a ClusterNodeSelector isn't executed
    Arnold Johansson Apprentice

    Brilliant! Now I (finally) understand better how affinity is tied in.

    The solution has been verified. I will update my sample project on github asap.

    Many thanks!