Introduzione alla ricerca JNDI EJB su WildFly Application Server

1. Panoramica

Gli Enterprise Java Beans (EJB) sono la parte centrale della specifica Java EE, volta a semplificare lo sviluppo di applicazioni distribuite a livello aziendale. Il ciclo di vita degli EJB è gestito da un server delle applicazioni, come JBoss WildFly o Oracle GlassFish.

Gli EJB forniscono un solido modello di programmazione che facilita l'implementazione di moduli software di livello aziendale, poiché spetta al server delle applicazioni gestire problemi non correlati alla logica aziendale come la gestione delle transazioni, la gestione del ciclo di vita dei componenti o l'inserimento delle dipendenze.

Inoltre, abbiamo già pubblicato due articoli che trattano i concetti di base di EJB, quindi sentiti libero di controllarli qui e qui.

In questo tutorial, mostreremo come implementare un modulo EJB di base su WildFly e chiamare un EJB da un client remoto tramite un JNDI.

2. Implementazione del modulo EJB

La logica aziendale viene implementata da una o più interfacce aziendali locali / remote (note anche come visualizzazioni locali / remote) o direttamente tramite classi che non implementano alcuna interfaccia (interfacce non di visualizzazione).

Vale la pena notare che le interfacce aziendali locali vengono utilizzate quando si accederà al bean da client che risiedono nello stesso ambiente, ovvero lo stesso file EAR o WAR, mentre le interfacce aziendali remote sono necessarie quando si accederà al bean da un ambiente diverso , ovvero una JVM o un application server differente.

Creiamo un modulo EJB di base, che sarà composto da un solo bean. La logica di business del bean sarà semplice, limitata alla conversione di una data stringa nella sua versione maiuscola.

2.1. Definizione di un'interfaccia aziendale remota

Definiamo prima una singola interfaccia aziendale remota, decorata con l' annotazione @Remote . Questo è obbligatorio, secondo la specifica EJB 3.x, poiché si accederà al bean da un client remoto:

@Remote public interface TextProcessorRemote { String processText(String text); }

2.2. Definizione di un fagiolo senza stato

Successivamente, realizziamo la logica aziendale implementando la suddetta interfaccia remota:

@Stateless public class TextProcessorBean implements TextProcessorRemote { public String processText(String text) { return text.toUpperCase(); } }

La classe TextProcessorBean è una semplice classe Java, decorata con l' annotazione @Stateless .

I bean senza stato, per definizione, non mantengono alcuno stato di conversazione con i loro client, anche quando possono mantenere lo stato dell'istanza su richieste diverse. La loro controparte, i bean stateful, preservano il loro stato di conversazione e, ad esempio, sono più costosi da creare per il server delle applicazioni.

Poiché in questo caso la classe precedente non ha alcuno stato di istanza, può essere resa senza stato. Nel caso in cui abbia uno stato, utilizzarlo su diverse richieste client non avrebbe affatto senso.

Il comportamento del bean è deterministico, cioè non ha effetti collaterali, come dovrebbe essere un bean ben progettato: prende solo una stringa di input e ne restituisce la versione maiuscola.

2.3. Dipendenze di Maven

Successivamente, è necessario aggiungere l' artefatto Maven javaee-api al modulo, che fornisce tutte le API della specifica Java EE 7, comprese quelle richieste per gli EJB:

 javax javaee-api 7.0 provided 

A questo punto, siamo riusciti a creare un modulo EJB di base ma funzionale. Per renderlo disponibile a tutti i potenziali clienti, dobbiamo aggiungere l'artefatto nel nostro repository Maven locale come file JAR.

2.4. Installazione del modulo EJB nel repository locale

Esistono diversi metodi per ottenere questo risultato. Il più semplice consiste nell'eseguire il ciclo di vita di Maven clean - installa le fasi di compilazione:

mvn clean install

Questo comando installa il modulo EJB come ejbmodule-1.0.jar ( o qualsiasi ID artefatto arbitrario specificato nel file pom.xml ), nel nostro repository locale. Per ulteriori informazioni su come installare un JAR locale con Maven, consulta questo articolo.

Supponendo che il modulo EJB sia stato installato correttamente nel nostro repository locale, il passo successivo è sviluppare un'applicazione client remota che utilizzi la nostra API TextProcessorBean .

3. Client EJB remoto

Manterremo la logica di business del client EJB remoto estremamente semplice: in primo luogo, esegue una ricerca JNDI per ottenere un proxy TextProcessorBean . Successivamente, richiama il metodo processText () del proxy .

3.1. Dipendenze di Maven

È necessario includere i seguenti artefatti Maven affinché il client EJB funzioni come previsto:

 javax javaee-api 7.0 provided   org.wildfly wildfly-ejb-client-bom 10.1.0.Final   com.beldung.ejbmodule ejbmodule 1.0 

Sebbene sia abbastanza ovvio il motivo per cui includiamo l' artefatto javaee-api , l'inclusione di wildfly-ejb-client-bom non lo è. L'artefatto è richiesto per eseguire chiamate EJB remote su WildFly.

Ultimo ma non meno importante, dobbiamo rendere disponibile al client il precedente modulo EJB, ecco perché abbiamo aggiunto anche la dipendenza ejbmodule .

3.2. Classe client EJB

Considerando che il client EJB chiama un proxy di TextProcessorBean , saremo molto pragmatici e denomineremo la classe client TextApplication :

public class TextApplication { public static void main(String[] args) throws NamingException { TextProcessorRemote textProcessor = EJBFactory .createTextProcessorBeanFromJNDI("ejb:"); System.out.print(textProcessor.processText("sample text")); } private static class EJBFactory { private static TextProcessorRemote createTextProcessorBeanFromJNDI (String namespace) throws NamingException { return lookupTextProcessorBean(namespace); } private static TextProcessorRemote lookupTextProcessorBean (String namespace) throws NamingException { Context ctx = createInitialContext(); String appName = ""; String moduleName = "EJBModule"; String distinctName = ""; String beanName = TextProcessorBean.class.getSimpleName(); String viewClassName = TextProcessorRemote.class.getName(); return (TextProcessorRemote) ctx.lookup(namespace + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName); } private static Context createInitialContext() throws NamingException { Properties jndiProperties = new Properties(); jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory"); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); jndiProperties.put(Context.PROVIDER_URL, "http-remoting://localhost:8080"); jndiProperties.put("jboss.naming.client.ejb.context", true); return new InitialContext(jndiProperties); } } }

In poche parole, tutto ciò che TextApplicationla classe sta recuperando il bean proxy e chiama il suo metodo processText () con una stringa di esempio.

La ricerca effettiva viene eseguita dalla classe nidificata EJBFactory , che prima crea un'istanza JNDI InitialContext , quindi passa i parametri JNDI richiesti al costruttore e infine la utilizza per cercare il proxy del bean.

Si noti che la ricerca viene eseguita utilizzando lo spazio dei nomi "ejb:" proprietario di WildFly. Ciò ottimizza il processo di ricerca, poiché il client rinvia la connessione al server finché il proxy non viene richiamato esplicitamente.

Vale anche la pena notare che è possibile cercare il proxy del bean senza ricorrere affatto allo spazio dei nomi "ejb". Tuttavia, mancheremmo tutti i vantaggi aggiuntivi delle connessioni di rete pigre, rendendo così il client molto meno performante .

3.3. Configurazione del contesto EJB

Il client dovrebbe sapere con quale host e porta stabilire una connessione per eseguire la ricerca del bean. A tal fine, il client richiede l'impostazione del contesto EJB WildFly proprietario, che è definito con il file jboss-ejb-client.properties inserito nel suo classpath, di solito sotto la cartella src / main / resources :

endpoint.name=client-endpoint remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default remote.connection.default.host=127.0.0.1 remote.connection.default.port=8080 remote.connection.default.connect.options.org.xnio.Options .SASL_POLICY_NOANONYMOUS=false remote.connection.default.username=myusername remote.connection.default.password=mypassword

Il file è abbastanza autoesplicativo, in quanto fornisce tutti i parametri necessari per stabilire una connessione a WildFly, incluso il numero predefinito di connessioni remote, l'host e la porta predefiniti e le credenziali dell'utente. In questo caso, la connessione non è crittografata, ma può esserlo quando SSL è abilitato.

L'ultima cosa da tenere in considerazione è che se la connessione richiede l'autenticazione, è necessario aggiungere un utente a WildFly tramite l' utility add-user.sh/add-user.bat .

4. Conclusione

L'esecuzione di ricerche EJB su WildFly è semplice, a condizione che ci atteniamo rigorosamente al processo descritto.

Come al solito, tutti gli esempi inclusi in questo articolo sono disponibili su GitHub qui e qui.