In this tutorial we will show how you can perform EJB to EJB invocations between two WildFly server instances.
Calling EJB which are located on a remote EJB server is done differentely depending if the remote client is a standalone client or if the client is located on another instance of WildFly.
Java Standalone clients will use a file name wildfly-config.xml which defines the host name where EJBs are deployed along with other settings such as application username and password. You can read more on this tutorial which describes step by step how to configure your standalone clients.
Java EE / Jakarta EE clients located on another application server will need another procedure and another file named jboss-ejb-client.xml which is used by the Remote clients. In order to complete this procedure you will need to configure an application user on the WildFly “server” (which exposes the EJBs) and configure an outbound remote connection on the WildFly “client” which points to the “server” machine.
So at first thing we will do is creating an application user on Application Server:
$ ./add-user.sh 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 : user1234 Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file. - The password should be different from the username - The password should not be one of the following restricted values {root, admin, administrator} - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s) 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)[ ]: About to add user 'user1234' for realm 'ApplicationRealm' Is this correct yes/no? yes Added user 'user1234' to file '/home/francesco/jboss/wildfly-15.0.0-SNAPSHOT/standalone/configuration/application-users.properties' Added user 'user1234' to file '/home/francesco/jboss/wildfly-15.0.0-SNAPSHOT/domain/configuration/application-users.properties' Added user 'user1234' with groups to file '/home/francesco/jboss/wildfly-15.0.0-SNAPSHOT/standalone/configuration/application-roles.properties' Added user 'user1234' with groups to file '/home/francesco/jboss/wildfly-15.0.0-SNAPSHOT/domain/configuration/application-roles.properties' Is this new user going to be used for one AS process to connect to another AS process? e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls. yes/no? yes To represent the user add the following to the server-identities definition <secret value="cGFzc3dvcmQxMjM0" />
WildFly “client” configuration:
Create a security realm which contains the password secret generated with the add-user.sh script:
<management> . . . . . . <security-realm name="ejb-security-realm"> <server-identities> <secret value="cGFzc3dvcmQxMjM0"/> </server-identities> </security-realm> </management>
Now configure the outbound socket connection toward the “remote” WildFly server. This will be done in two points of your configuration:
1) Into the remoting subsystem:
<subsystem xmlns="urn:jboss:domain:remoting:4.0"> <endpoint worker="default"/> <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/> <outbound-connections> <remote-outbound-connection name="remote-connection-war-ejb" outbound-socket-binding-ref="remote-war-1" username="user1234" security-realm="ejb-security-realm" protocol="http-remoting"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> </properties> </remote-outbound-connection> </outbound-connections> </subsystem>
2) Into the socket-binding-group, where you need to specify the host name and port where you are going to connect (we assume that the target server is running on localhost with a port offset of 100):
<socket-binding-group name="full-sockets" default-interface="public"> <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/> <socket-binding name="http" port="${jboss.http.port:8080}"/> <socket-binding name="https" port="${jboss.https.port:8443}"/> <socket-binding name="iiop" interface="unsecure" port="3528"/> <socket-binding name="iiop-ssl" interface="unsecure" port="3529"/> <socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-status-manager" port="4713"/> <outbound-socket-binding name="mail-smtp"> <remote-destination host="localhost" port="25"/> </outbound-socket-binding> <outbound-socket-binding name="remote-ejb"> <remote-destination host="localhost" port="8180"/> </outbound-socket-binding> </socket-binding-group>
Application changes:
In terms of application code, you need to include the file jboss-ejb-client.xml into your client application which describes the outbound-connection to use for the EJB calls. Please note that this file needs to be placed into the META-INF folder of your EAR file or the WEB-INF of your Web application.
Example:
webclient.war WEB-INF jboss-ejb-client.xml
Here is the content of the file jboss-ejb-client.xml
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2"> <client-context> <ejb-receivers> <!-- this is the connection to access the app-one --> <remoting-ejb-receiver outbound-connection-ref="remote-connection-war-ejb" /> </ejb-receivers> <!-- if there is a cluster behind the outbound connection the cluster element must be defined --> <clusters> <!-- cluster of remote-ejb-connection-1 --> <cluster name="ejb" security-realm="ejb-security-realm" username="user1234"> <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>
Please notice that if you are starting both WildFly servers on the same machine you need to specify a port offset for one of the two servers and a jboss.node.name unique name. Example:.
Server1
$ standalone.sh -Djboss.node.name=nodeA
Server2
$ standalone.sh -Djboss.socket.binding.port-offset=100 -Djboss.node.name=nodeB
If you need an example of EJB to EJB communication in a clustered environment, we suggest having a look at this tutorial: EJB to EJB communication in a cluster (JBoss AS 7 – WildFly)
JBoss AS 7 “server” configuration
If you are running a JBoss AS 7 server, the steps are almost the same, just the protocol to be used is remoting instead of Http+remoting.
So at first thing we will do is creating an application user on the JBoss AS 7 server:
./add-user.sh 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. Realm (ApplicationRealm) : Username : user1234 Password : password1234 Re-enter Password : password1234 What roles do you want this user to belong to? (Please enter a comma separated list, or leave blank for none) : About to add user 'user1234' for realm 'ApplicationRealm' Is this correct yes/no? yes Added user 'ejb' to file '/jboss-as-7.1.1.Final/standalone/configuration/application-users.properties' Added user 'ejb' to file '/jboss-as-7.1.1.Final/domain/configuration/application-users.properties' Added user 'ejb' with roles to file '/jboss-as-7.1.1.Final/standalone/configuration/application-roles.properties' Added user 'ejb' with roles to file '/jboss-as-7.1.1.Final/domain/configuration/application-roles.properties'
Next step, you need to generate a base64 encoded string (“secret”) for your password. If you are using a JBoss AS 7.1.2 release (e.g. 7.1.2 Alpha) you get it printed on the console automatically. For the 7.1.1 release you can use an online utility such as http://www.base64encode.org/.
In our example the base64 encoded password is cGFzc3dvcmQxMjM0ed
JBoss AS 7 “client” configuration:
Create a security realm which contains the password generated into the secret element:
<management> . . . . . . <security-realm name="ejb-security-realm"> <server-identities> <secret value="cGFzc3dvcmQxMjM0"/> </server-identities> </security-realm> </management>
Now configure the outbound socket connection toward the “remote” JBoss AS 7 server. This will be done in two points of your configuration:
1) Into the remoting subsystem:
<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-connection" outbound-socket-binding-ref="remote-ejb" username="user1234" 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> 2) Into the
socketbinding group
, where you need to specify the host name and port where you are going to connect (Replace 192.168.0.1 with the IP Address of the JBoss AS 7 "server")
<socket-binding-group name="standard-sockets" default-interface="public"> . . . . <outbound-socket-binding name="remote-ejb"> <remote-destination host="192.168.0.1" port="4447"/> </outbound-socket-binding> </socket-binding-group>
Application changes:
In terms of application code, you need to include the file jboss-ejb-client.xml into your client application which describes the outbound-connection to use for the EJB calls. Please note that this file needs to be placed into the META-INF folder of your EAR file or the WEB-INF of your Web application.
Example:
webclient.war WEB-INF jboss-ejb-client.xml
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2"> <client-context > <ejb-receivers exclude-local-receiver="true"> <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection" /> </ejb-receivers> </client-context> </jboss-ejb-client>
That’s all.
Please notice that if you are starting both JBoss AS 7 servers on the same machine you need to specify a port offset for one of the two servers and a jboss.node.name unique name
Ex.
Server1
standalone.bat -Djboss.node.name=nodeA
Server2
standalone.bat -Djboss.socket.binding.port-offset=150 -Djboss.node.name=nodeB
If you need an example of EJB to EJB communication in a clustered environment, we suggest having a look at this tutorial: EJB to EJB communication in a cluster