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

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

1. Vue d'ensemble

LesEnterprise Java Beans (EJB) sont la partie centrale desJava EE specification, 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 queJBoss WildFly ouOracle GlassFish.

Les EJB fournissent un modèle de programmation robuste qui facilite la mise en œuvre de modules logiciels de niveau entreprise, car il incombe au serveur d’application de gérer les problèmes non liés à la logique d’entreprise, tels que le traitement 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 des EJB, alors n'hésitez pas à les consulter surhere ethere.

Dans ce didacticiel, nous allons montrer comment implémenter un module EJB de base sur WildFly et appeler un EJB à partir d'un client distant via unJNDI.

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 par le biais de classes n'implémentant aucune interface (interfaces non visuelles).

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 même fichier EAR ou WAR, tandis que des interfaces de gestion distantes sont requises pour accéder au bean à partir d'un environnement différent, c'est-à-dire une machine virtuelle Java 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'unString donné 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 de l'annotation@Remote. Ceci est obligatoire, selon lesEJB 3.x specification, car le bean va être accédé 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 classeTextProcessorBean 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 conserver l'état de l'instance sur différentes requêtes. Leur homologue, les beans avec état, préservent leur état conversationnel, et comme ils sont plus chers à créer pour le serveur d'applications.

Comme dans ce cas, la classe ci-dessus n’a pas d’état d’instance, elle peut être rendue sans état. Dans le cas où il aurait un état, l’utiliser dans différentes requêtes 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 entréeString et en renvoie la version majuscule.

2.3. Dépendances Maven

Ensuite, nous devons ajouter l'artefact Mavenjavaee-api 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 de base, 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. La plus simple consiste à exécuter les phases de construction du cycle de vie Mavenclean – install:

mvn clean install

Cette commande installe le module EJB en tant queejbmodule-1.0.jar ( ou tout identifiant d'artefact arbitraire spécifié dans le fichierpom.xml), dans notre référentiel local. Pour plus d'informations sur l'installation d'un JAR local avec Maven, consultezthis 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 APITextProcessorBean.

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 proxyTextProcessorBean. Après cela, il appelle la méthodeprocessText() du proxy.

3.1. Dépendances 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'artefactjavaee-api, l'inclusion dewildfly-ejb-client-bom ne l'est pas. The artifact is required for performing remote EJB invocations on WildFly.

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

3.2. Classe de client EJB

Étant donné que le client EJB appelle un proxy deTextProcessorBean, nous serons très pragmatiques et nommerons la classe clientTextApplication:

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 fait la classeTextApplication __ est de récupérer le proxy du bean et d'appeler sa méthodeprocessText() avec un exemple de chaîne.

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

Notez que la recherche est effectuée à l’aide de 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é.

Il convient également de noter qu’il est possible de rechercher le proxy du bean sans recourir du tout à l’espace de noms «ejb». Cependant,we’d be missing all the additional benefits of lazy network connections, thus making the client a lot less performant.

3.3. Configuration du contexte EJB

Le client doit savoir avec quel hôte et quel port établir une connexion pour effectuer la recherche du bean. Dans cette mesure,the client requires setting up the proprietary WildFly EJB context, which is defined with the jboss-ejb-client.properties file est placé dans son chemin de classe, généralement sous le dossiersrc/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

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 distantes, l'hôte par défaut, le port et les informations d'identification de l'utilisateur. Dans ce cas, la connexion n’est pas cryptée, mais peut-être le cas lorsque SSL est activé.

La dernière chose à prendre en compte est queif the connection requires authentication, it’s necessary to add a user to WildFly via the https://docs.jboss.org/author/display/WFLY8/add-user+utility?sscc=t[_add-user.sh/add-user.bat utility].

4. Conclusion

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

Comme d'habitude, tous les exemples inclus dans cet article sont disponibles sur GitHubhere ethere.