This tutorial covers an advanced clustering scenario where you have an EJB client on a JBoss AS 7/WildFly server that is communicating with another EJB that is running on a cluster of servers.
The purpose of this trail is to demonstrate that the EJB client can get a view of the cluster topology on first lookup and this view is updated dynamically as the cluster topology changes. Here is a picture which shows our scenario:
Configuration on the EJB server side
The EJB server is running on a cluster of JBoss AS 7/WildFly nodes. All you have to do is creating an application user so that the call can be routed from a the remote client:
What type of user do you wish to add? a) Management User (mgmt-users.properties) b) Application User (application-users.properties) (a): b Enter the details of the new user to add. Using realm 'ApplicationRealm' as discovered from the existing property files. Username : ejbserver Password : Re-enter Password : What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[ ]: . . . To represent the user add the following to the server-identities definition <secret value="UGFzc3dvcmQxIQ==" />
Configuration on the EJB client side
The configuration has to be done on the JBoss/WildFly server is more complex as we have to define a set of outbound connections to your remote servers;
<subsystem xmlns="urn:jboss:domain:remoting:1.1"> <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/> <outbound-connections> <remote-outbound-connection name="remote-ejb-connection1" outbound-socket-binding-ref="remote-connection-1" username="ejbserver" security-realm="ejb-security-realm"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> </properties> </remote-outbound-connection> <remote-outbound-connection name="remote-ejb-connection2" outbound-socket-binding-ref="remote-connection-2" username="ejbserver" security-realm="ejb-security-realm"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> </properties> </remote-outbound-connection> </outbound-connections> </subsystem> . . . . . <outbound-socket-binding name="remote-connection-1"> <remote-destination host="192.168.10.1" port="8080"/> </outbound-socket-binding> <outbound-socket-binding name="remote-connection-2"> <remote-destination host="192.168.10.2" port="8080"/> </outbound-socket-binding>
If you are using JBoss AS/ EAP 6 you have to reference the default remoting port 4547, adding the offset if included.
Now complete your configuration by including in the security-realm section the password with the secret we have just created on the server:
<security-realms> <security-realm name="ejb-security-realm"> <server-identities> <secret value="UGFzc3dvcmQxIQ=="/> </server-identities> </security-realm> . . . </security-realms>
Packaging your application on the client side
The EJB client application needs to be include into the META-INF folder the file jboss-ejb-client.xml which contains a reference to the outbound connections:
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2"> <client-context> <ejb-receivers> <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection1" /> <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection2" /> </ejb-receivers> <clusters> <cluster name="ejb"> <connection-creation-options> <property name="org.xnio.Options.SSL_ENABLED" value="false" /> <property name="org.xnio.Options.SASL_POLICY_NOANONYMOUS" value="false" /> </connection-creation-options> </cluster> </clusters> </client-context> </jboss-ejb-client>
The other key element here is the cluster reference which is pointing to the "ejb" cluster view running on the remote EJB.This allows to collect the cluster view by the EJB proxy client. Now deploy the EJB client and server applications.
Mind it if you are using Jboss AS 7 /EAP 6 you need to enable the ejb cluster channel by either adding the @Clustered annotation on your EJBs or including the jboss-ejb.xml file:
<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: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> <session> <ejb-name>ClusteredEJB</ejb-name> <ejb-class>com.sample.ClusteredEJB</ejb-class> </session> </enterprise-beans> <assembly-descriptor> <c:clustering> <ejb-name>ClusteredEJB</ejb-name> <c:clustered>true</c:clustered> </c:clustering> </assembly-descriptor> </jboss:ejb-jar>
As you can see from the following snapshot, the EJB client is balancing the load between the two servers in a cluster:
Now let's vary the composition of the cluster by shutting down server-two and adding a new node named server-three:
As you can see, now the balancing is adjusted dynamically by the proxy sitting on the client side: