This article will discuss how to enable clustering for Enterprise Java Beans (EJB) with WildFly application server or JBoss EAP.
WildFly application Server
In order to enable clustering for WildFly versions 8/9/10 you needed to annotate your Stateful Session Beans with the @org.jboss.ejb3.annotation.Clustered :
import org.jboss.ejb3.annotation.Clustered; import javax.ejb.Stateful; @Stateful @Clustered public class MyStatefulBean { ... }
As an alternative, you could include the <clustered> element in your jboss-ejb3.xml.
Since WildFly 11, 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 is to start with an HA profile:
$ ./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:13.0"> <cache-container name="ejb" default-cache="dist" marshaller="PROTOSTREAM" aliases="sfsb" modules="org.wildfly.clustering.ejb.infinispan"> <transport lock-timeout="60000"/> <replicated-cache name="client-mappings"> <expiration interval="0"/> </replicated-cache> <distributed-cache name="dist"> <locking isolation="REPEATABLE_READ"/> <transaction mode="BATCH"/> <expiration interval="0"/> <file-store/> </distributed-cache> </cache-container> <!-- ... --> </subsystem>
The default cache strategy for EJB is distributed 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 Class 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:
- Use the @org.jboss.ejb3.annotation.Clustered annotation at EJB level
- 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>