How to make all your EJB clusterable in JBoss/WildFly

Let’s see how you can turn all your EJBs to be clusterable in different application server versions.

WildFly application Server

When running WildFly, the above options are deprecated. Once you deploy an EJB, it is automatically set to be clustered and the JGroups “ejb” channel is activated.

So, this is all you need to enable clustering of EJBs in WildFly:

$ ./standalone.sh -c standalone-ha.xml

The most evident outcome is that your Stateful Session Beans will be HA. Session state is maintained in Infinispan, through the “ejb” cache container:

<subsystem xmlns="urn:jboss:domain:infinispan:8.0">
             <cache-container name="ejb" aliases="sfsb" default-cache="dist" module="org.wildfly.clustering.ejb.infinispan">
                <transport lock-timeout="60000"/>
                <distributed-cache name="dist">
                    <locking isolation="REPEATABLE_READ"/>
                    <transaction mode="BATCH"/>
                    <file-store/>
                </distributed-cache>
            </cache-container>
 </subsystem>

The default cache strategy for EJB is distributed mode which allows Infinispan to scale the cluster linearly. Distributed mode uses a consistent hash algorithm to determine where in a cluster a new node should be placed. The more copies that are kept, the more impact on performance, but the less likely you are to lose data in a server failure.

Disabling clustering for EJBs

If the default behaviour is not acceptable, you can still disable this behaviour at different levels:

At EJB level:

@javax.ejb.Stateful(passivationCapable=false)
public class NoHASFSB {
....
}

Or you can do it through the jboss-ejb3.xml descriptor:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd" version="3.2">
   <enterprise-beans>
      <session>
         <ejb-name>NoHASFSB</ejb-name>
         <ejb-class>com.sample.NoHASFSB</ejb-class>
         <session-type>Stateful</session-type>
         <passivation-capable>false</passivation-capable>
      </session>
   </enterprise-beans>
</ejb-jar>

JBoss AS 7 / EAP 6

Out of the box you have two options to make an EJB as clusterable:

  1. Use the @org.jboss.ejb3.annotation.Clustered annotation at EJB level
  2. Specify in your jboss-ejb3.xml that your Bean is clustered:
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
                  xmlns="http://java.sun.com/xml/ns/javaee"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:s="urn:security"
                  xmlns:c="urn:clustering:1.0"
                  xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
                     http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
                  version="3.1"
                  impl-version="2.0">
    <enterprise-beans>
    </enterprise-beans>
      <assembly-descriptor>
      <c:clustering>
          <ejb-name>DemoEJB</ejb-name>
          <c:clustered>true</c:clustered>
      </c:clustering>
      </assembly-descriptor>
</jboss:ejb-jar>

Interestingly enough, the <ejb-name> section allows using the “*” wildcard patterns so can easily mark all your EJBs to be clustered with just one XML block:

<c:clustering>
          <ejb-name>*</ejb-name>
          <c:clustered>true</c:clustered>
</c:clustering>