In questo articolo, descrivo come effettuare una lookup da un client JBoss verso un servizio EJB (Enterprise Java Bean) remoto, esposto su una macchina differente dal client stesso.
Queste sono le tecnologie utilizzate in questo tutorial:
Il nostro EJB remoto di test è il seguente:
@Stateless @Remote(TestService.class) @TransactionManagement(TransactionManagementType.BEAN) public class TestServiceBean implements TestService { public methodTest(){ //code implementation here } }
Il precedente EJB remoto verrà esposto su un application server installato su una macchina differente (che chiamerò destination server). Di seguito, divido le attività di configurazione in due: configurazione destination server e configurazione client server.
Configurazione destination server
Sull’application server su cui è deployato l’EJB remoto, occorre semplicemente creare un utente applicativo, per mettere in sicurezza la chiamata remota (security realm). Utilizziamo lo script add-user.sh (o .bat, se siete su Windows), presente in ${JBOSS_HOME}/bin, per creare l’utente ejb (con password test):
Dopo aver creato l’utente su JBoss, basta startare l’AS e deployare il servizio remoto.
Configurazione client server
Il grosso della configurazione va fatta sul client che deve richiamare l’EJB remoto.
Nel file di configurazione di JBoss, standalone.xml (o domain.xml), occorre eseguire quanto segue:
- creare il security realm sul client server
<management> <security-realms> ... <security-realm name="ejb-security-realm"> <server-identities> <secret value="dGVzdA=="/> </server-identities> </security-realm> </security-realms>
Dove in secret c’è la password (test) codifica in BASE-64.
- creare l’outbound-socket-binding sul client server
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> ... <outbound-socket-binding name="remote-ejb"> <remote-destination host="127.0.01" port="4447"/> </outbound-socket-binding> </socket-binding-group>
Dove al posto dell’indirizzo IP 127.0.0.1 potete inserire quello della macchina remota del destination server (la porta di default del remoting è la 4447, a meno che non l’abbiate cambiata).
- creare un remote-outbound-connection che usa l’outbound-socket-binding
<subsystem xmlns="urn:jboss:domain:remoting:1.1"> .... <outbound-connections> <remote-outbound-connection name="remote-ejb-connection" outbound-socket-binding-ref="remote-ejb" security-realm="ejb-security-realm" username="ejb"> <properties> <property name="SASL_POLICY_NOANONYMOUS" value="false"/> <property name="SSL_ENABLED" value="false"/> </properties> </remote-outbound-connection> </outbound-connections> </subsystem>
Dove in corrispondenza dell’attributo username c’è l’utente di test che abbiamo creato sul destination server.
Lato configurazione del client server abbiamo terminato.
Di seguito, si riportano gli interventi da fare sull’applicazione client (client application), per poter richiamare il servizio remoto:
- inserire nel classpath dell’applicazione client il file jboss-ejb-client.xml
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0"> <client-context> <ejb-receivers> <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection"/> </ejb-receivers> </client-context> </jboss-ejb-client>
Infine, per effettuare la lookup remota in modo programmatico, ecco un esempio di una classe client di test:
import javax.naming.Context; import java.util.Hashtable; import javax.naming.InitialContext; ... public void invokeOnBean() { 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 final TestService bean = (TestService) context.lookup("ejb:" + "myapp" + "/" + "myejb" + "/" + "" + "/" + "TestService" + "!" + it.francescoficetola.ejb.TestService.class.getName()); // invoke on the bean final String greeting = bean.test(); } catch (Exception e) { throw new RuntimeException(e); } }
Nota. Quando si deploya l’EJB remoto, il JNDI name viene automaticamente registrato dall’application server. Ad esempio, per gli EJB stateless, il JNDI name è come questo:
ejb:jboss-as-ejb-remote-app/TestServiceBean!it.francescoficetola.ejb.TestService
Come si riporta in questo articolo (EJB invocations from a remote client using JNDI), ecco la regola per la generazione del JNDI name:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
Poiché in app-name e module-name mi venivano registrati anche i numeri di versione dei moduli applicativi (dopo aver buildato con Maven), ho effettuato un override dei loro valori in questo modo:
- per settare l’app-name, ho inserito l’application-name nel file application.xml dell’EAR in cui è deployato l’EJB remoto:
<application-name>myapp</application-name>
- per settare il module-name, occorre inserire nel classpath del modulo EJB (nella directory META-INF) il file ejb-jar.xml:
<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"> <module-name>myejb</module-name> </ejb-jar>
Riferimenti:

This work by Francesco Ficetola is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at www.francescoficetola.it.
Permissions beyond the scope of this license may be available at http://www.francescoficetola.it/2015/02/09/jbossejb-ejb-remoti-come-effettuare-la-lookup-da-client-jboss/.