Introduction à la recherche EJB JNDI sur le serveur d'applications WildFly

1. Vue d'ensemble

Les Enterprise Java Beans (EJB) sont la partie centrale de la spécification Java EE, visant à simplifier le développement d'applications distribuées au niveau de l'entreprise. Le cycle de vie des EJB est géré par un serveur d'applications, tel que JBoss WildFly ou Oracle GlassFish.

Les EJB fournissent un modèle de programmation robuste qui facilite la mise en œuvre de modules logiciels au niveau de l'entreprise, car il appartient au serveur d'applications de gérer les problèmes liés à la logique non métier tels que la gestion des transactions, la gestion du cycle de vie des composants ou l'injection de dépendances.

De plus, nous avons déjà publié deux articles couvrant les concepts de base d'EJB, alors n'hésitez pas à les consulter ici et ici.

Dans ce tutoriel, nous montrerons comment implémenter un module EJB de base sur WildFly et appeler un EJB à partir d'un client distant via un JNDI.

2. Implémentation du module EJB

La logique métier est implémentée par une ou plusieurs interfaces métier locales / distantes (également appelées vues locales / distantes) ou directement via des classes qui n'implémentent aucune interface (interfaces sans vue).

Il convient de noter que les interfaces métier locales sont utilisées lorsque le bean va être accédé à partir de clients qui résident dans le même environnement, c'est-à-dire le même fichier EAR ou WAR, alors que les interfaces métier distantes sont requises lorsque le bean sera accessible depuis un environnement différent , c'est-à-dire une JVM ou un serveur d'applications différent.

Créons un module EJB de base, qui sera composé d'un seul bean. La logique métier du bean sera simple, limitée à la conversion d'une chaîne donnée en sa version majuscule.

2.1. Définition d'une interface professionnelle distante

Définissons d'abord une seule interface métier distante, décorée avec l' annotation @Remote . Ceci est obligatoire, selon la spécification EJB 3.x, car le bean sera accessible depuis un client distant:

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

2.2. Définition d'un bean sans état

Ensuite, réalisons la logique métier en implémentant l'interface distante susmentionnée:

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

La classe TextProcessorBean est une classe Java simple, décorée de l' annotation @Stateless .

Les beans sans état, par définition, ne conservent aucun état conversationnel avec leurs clients, même lorsqu'ils peuvent maintenir l'état de l'instance sur différentes requêtes. Leur homologue, les beans avec état, préservent leur état conversationnel et, par exemple, ils sont plus coûteux à créer pour le serveur d'applications.

Comme dans ce cas, la classe ci-dessus n'a aucun état d'instance, elle peut être rendue sans état. Dans le cas où il a un état, son utilisation dans différentes demandes client n'aurait aucun sens.

Le comportement du bean est déterministe, c'est-à-dire qu'il n'a pas d'effets secondaires, comme un bean bien conçu devrait l'être: il prend juste une String d' entrée et en renvoie la version majuscule.

2.3. Dépendances de Maven

Ensuite, nous devons ajouter l' artefact javaee-api Maven au module, qui fournit toutes les API de spécification Java EE 7, y compris celles requises pour les EJB:

 javax javaee-api 7.0 provided 

À ce stade, nous avons réussi à créer un module EJB basique mais fonctionnel. Pour le rendre disponible à tous les clients potentiels, nous devons ajouter l'artefact dans notre référentiel Maven local en tant que fichier JAR.

2.4. Installation du module EJB dans le référentiel local

Il existe plusieurs méthodes pour y parvenir. Le plus simple consiste à exécuter les phases de nettoyage du cycle de vie Maven - installer :

mvn clean install

Cette commande installe le module EJB en tant que ejbmodule-1.0.jar ( ou tout identifiant d'artefact arbitraire spécifié dans le fichier pom.xml ), dans notre référentiel local. Pour plus d'informations sur l'installation d'un JAR local avec Maven, consultez cet article.

En supposant que le module EJB a été correctement installé dans notre référentiel local, l'étape suivante consiste à développer une application client distante qui utilise notre API TextProcessorBean .

3. Client EJB distant

Nous allons garder la logique métier du client EJB distant extrêmement simple: d'abord, il effectue une recherche JNDI pour obtenir un proxy TextProcessorBean . Après cela, il appelle la méthode processText () du proxy .

3.1. Dépendances de Maven

Nous devons inclure les artefacts Maven suivants pour que le client EJB fonctionne comme prévu:

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

Bien qu'il soit assez évident pourquoi nous incluons l' artefact javaee-api , l'inclusion de wildfly-ejb-client-bom ne l'est pas. L'artefact est requis pour exécuter des appels EJB distants sur WildFly.

Enfin, nous devons rendre le module EJB précédent disponible pour le client, c'est pourquoi nous avons également ajouté la dépendance ejbmodule .

3.2. Classe de client EJB

Étant donné que le client EJB appelle un proxy de TextProcessorBean , nous serons très pragmatiques et nommerons 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); } } }

En termes simples, tout ce que TextApplicationla classe récupère le proxy du bean et appelle sa méthode processText () avec un exemple de chaîne.

La recherche réelle est effectuée par la classe imbriquée EJBFactory , qui crée d'abord une instance JNDI InitialContext , puis transmet les paramètres JNDI requis au constructeur et l'utilise finalement pour rechercher le proxy du bean.

Notez que la recherche est effectuée en utilisant l'espace de noms propriétaire «ejb:» de WildFly. Cela optimise le processus de recherche, car le client diffère la connexion au serveur jusqu'à ce que le proxy soit explicitement appelé.

It’s worth noting as well that it's possible to lookup the bean proxy without resorting to the “ejb” namespace at all. However, we'd be missing all the additional benefits of lazy network connections, thus making the client a lot less performant.

3.3. Setting Up the EJB Context

The client should know what host and port to establish a connection with to perform the bean lookup. To this extent, the client requires setting up the proprietary WildFly EJB context, which is defined with the jboss-ejb-client.properties file placed in its classpath, usually under the src/main/resources folder:

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

Le fichier est assez explicite, car il fournit tous les paramètres requis pour établir une connexion à WildFly, y compris le nombre par défaut de connexions à distance, l'hôte et le port par défaut et les informations d'identification de l'utilisateur. Dans ce cas, la connexion n'est pas chiffrée, mais cela peut l'être lorsque SSL est activé.

La dernière chose à prendre en compte est que si la connexion nécessite une authentification, il est nécessaire d'ajouter un utilisateur à WildFly via l' utilitaire add-user.sh/add-user.bat .

4. Conclusion

Effectuer des recherches EJB sur WildFly est simple, tant que nous respectons strictement le processus décrit.

Comme d'habitude, tous les exemples inclus dans cet article sont disponibles sur GitHub ici et ici.