EJB 3.0 en quelques mots

Malgré plusieurs points positifs, la complexité de l'architecture Enterprise JavaBeans freine l'adoption de J2EE. L'architecture EJB est probablement le seul composant J2EE qui a échoué si lamentablement dans la réalisation de la promesse de J2EE d'une productivité accrue des développeurs et d'une facilité de développement. EJB 3.0 tente une nouvelle fois de tenir cette promesse en réduisant la complexité d'EJB pour les développeurs. EJB 3.0 réduit le nombre d'artefacts de programmation que les développeurs doivent fournir, élimine ou minimise les méthodes de rappel nécessaires à implémenter et réduit la complexité du modèle de programmation du bean entité et du modèle de mappage O / R.

Dans cet article, je couvre d'abord les changements les plus significatifs dans EJB 3.0. Il est important d'avoir les bases en place avant de plonger dans la piscine EJB 3.0. Ensuite, je donne une vue de haut niveau du projet EJB 3.0, puis j'entre dans les détails de la spécification proposée, en faisant attention à tous les changements un par un: impact sur les types de beans entreprise, modèle de mappage O / R, entité- modèle de relation, EJB QL (EJB Query Language), etc.

Contexte

Les deux changements les plus importants dans la spécification EJB 3.0 proposée sont l'utilisation de la fonction d'annotation de programme introduite dans Java 5 et le nouveau modèle de mappage O / R basé sur Hibernate.

Fonction de métadonnées dans Java 5

Java 5 (précédemment appelé J2SE 1.5 ou Tiger) a introduit une nouvelle fonction d'annotation de programme dans le langage. Avec cette fonction, vous pouvez définir des annotations personnalisées, puis annoter des champs, des méthodes, des classes, etc., avec ces annotations. Les annotations n'affectent pas directement la sémantique du programme, mais les outils (au moment de la compilation ou à l'exécution) peuvent inspecter ces annotations pour générer des constructions supplémentaires (comme un descripteur de déploiement) ou appliquer le comportement d'exécution souhaité (comme la nature avec état d'un composant EJB). Les annotations peuvent être inspectées via l'analyse des sources (par exemple, des compilateurs ou des outils IDE) ou en utilisant les API de réflexion supplémentaires ajoutées dans Java 5. Les annotations peuvent être définies pour être disponibles uniquement au niveau du code source, au niveau de la classe compilée ou à l'exécution . Toutes les annotations proposées dans le projet de début EJB 3.0 ont RetentionPolicydeRUNTIME. Cela augmente légèrement l'empreinte mémoire de la classe, mais rend la vie du fournisseur de conteneur et du fournisseur d'outils beaucoup plus facile.

Reportez-vous aux ressources pour en savoir plus sur ce sujet.

Hiberner

Hibernate est un framework de mappage O / R open source populaire pour les environnements Java, destiné à protéger les développeurs des tâches de programmation les plus courantes liées à la persistance des données. Il dispose également d'un langage Hibernate Query Language (HQL) spécifique, dont les empreintes peuvent être vues dans le nouvel EJB QL. Hibernate offre des fonctionnalités pour la récupération et la mise à jour des données, la mise en commun des connexions, la gestion des transactions, la gestion des relations avec les entités déclaratives et les requêtes déclaratives et programmatiques.

Vue à vol d'oiseau

Les modifications apportées à la spécification EJB 3.0 proposée peuvent être divisées en deux catégories:

  • Un modèle de programmation EJB basé sur des annotations, en plus du modèle EJB 2.1 de définition du comportement d'une application via des descripteurs de déploiement et plusieurs interfaces.
  • Le nouveau modèle de persistance pour les beans entité. EJB QL a également beaucoup changé.

Il existe également plusieurs effets secondaires à ces propositions, comme un nouveau modèle de programmation client, l'utilisation d'interfaces métier et un cycle de vie de bean entité. Veuillez noter que le modèle de programmation EJB 2.1 (avec descripteurs de déploiement et interfaces home / remote) est toujours valide. Le nouveau modèle simplifié ne remplace pas entièrement le modèle EJB 2.1.

Annotations EJB

L'un des objectifs importants du groupe d'experts est de réduire le nombre d'artefacts qu'un fournisseur de haricots doit fournir, et le groupe a fait un travail assez soigné pour atteindre cet objectif. Dans le monde EJB 3.0, toutes sortes de beans entreprise ne sont que de simples objets Java (POJO) avec les annotations appropriées. Les annotations peuvent être utilisées pour définir l'interface métier du bean, les informations de mappage O / R, les références de ressources et à peu près tout ce qui a été défini via des descripteurs de déploiement ou des interfaces dans EJB 2.1. Les descripteurs de déploiement ne sont plus nécessaires; l'interface d'accueil a disparu, et vous n'avez pas nécessairement à implémenter une interface métier (le conteneur peut la générer pour vous).

Par exemple, vous déclarez un bean session sans état en utilisant l' @Statelessannotation sur la classe Java. Pour les beans avec état, l' @Removeannotation est marquée sur une méthode particulière pour indiquer que l'instance de bean doit être supprimée après la fin d'un appel à la méthode marquée.

Pour réduire la quantité d'informations que vous devez spécifier pour un composant, le groupe d'experts a adopté une approche de configuration par exception , ce qui signifie que vous fournissez des valeurs par défaut intuitives pour toutes les annotations afin que la plupart des informations courantes puissent être déduites.

Le nouveau modèle de persistance

Les nouveaux beans entité ne sont également que des POJO avec quelques annotations et ne sont pas des entités persistantes par naissance. Une instance d'entité devient persistante une fois qu'elle est associée à un EntityManageret fait partie d'un contexte de persistance . Un contexte de persistance est vaguement synonyme de contexte de transaction; en termes stricts, il coexiste implicitement avec la portée d'une transaction.

Les relations d'entité sont également définies par des annotations. En outre, le mappage O / R est également effectué via des annotations et la prise en charge de plusieurs opérations spécifiques à la base de données est fournie. Avec EJB 2.1, les développeurs ont utilisé leurs propres modèles de conception ou utilisé des techniques non portables (par exemple, des stratégies de génération de clé automatique).

Creuser profondément

Il est maintenant temps d'entrer dans les détails des propositions faites dans le premier projet de l'EJB 3.0. Commençons par les quatre types de beans entreprise, puis passons aux propositions génériques pour l'ensemble du modèle de programmation EJB.

Beans session sans état:

Un bean session sans état (SLSB), écrit à la manière EJB 3.0, n'est qu'un simple fichier Java avec une annotation au niveau de la classe @Stateless. La classe bean peut implémenter l' javax.ejb.SessionBeaninterface, mais n'est pas obligée (et ne le fera généralement pas).

Un SLSB n'a plus d'interface home - en fait, aucun type d'EJB ne l'exige. La classe bean peut implémenter ou non une interface métier. S'il n'implémente aucune interface métier, une interface métier sera générée en utilisant toutes les méthodes publiques. Si seules certaines méthodes doivent être exposées dans l'interface métier, toutes ces méthodes peuvent être marquées de l' @BusinessMethodannotation. Par défaut, toutes les interfaces générées sont locales, mais l' @Remoteannotation peut être utilisée pour indiquer qu'une interface distante doit être générée.

Les quelques lignes de code suivantes suffisent pour définir un HelloWorldbean. Avec EJB 2.1, le même bean aurait nécessité au moins deux interfaces, une classe d'implémentation avec plusieurs implémentations de méthode vides et un descripteur de déploiement.

import javax.ejb. *; / ** * Un bean session sans état demandant qu'une interface métier distante * soit générée pour lui. * / @Stateless @Remote classe publique HelloWorldBean {chaîne publique sayHello () {return "Hello World !!!"; }}

Reportez-vous aux ressources pour le code source complet qui accompagne cet article.

Beans session avec état

L'histoire des beans session avec état (SFSB) est à peu près la même pour SLSB, à l'exception de quelques points spécifiques à SFSB:

  • Un SFSB doit avoir un moyen de s'initialiser (fourni par la ejbCreate()méthode dans EJB 2.1 et versions antérieures). La spécification EJB 3.0 suggère que de telles méthodes d'initialisation soient fournies sous forme de méthodes personnalisées et exposées via l'interface métier du bean. Il incombe désormais au client d'appeler les méthodes d'initialisation appropriées avant d'utiliser le bean. Le groupe d'experts débat encore de la nécessité de fournir une annotation qui marque une méthode particulière d'initialisation.
  • Le fournisseur de bean peut marquer n'importe quelle méthode SFSB avec l' @Removeannotation pour indiquer que l'instance de bean doit être supprimée après l'appel de la méthode annotée. Encore une fois, le groupe d'experts discute encore de la nécessité d'une installation pour indiquer que le haricot ne doit pas être retiré si la méthode ne se termine pas normalement.

Voici mon avis sur les deux questions en suspens:

  • Une annotation pour la méthode d'initialisation doit-elle exister? Mon vote est oui - avec l'hypothèse que le conteneur garantira qu'au moins une des méthodes d'initialisation est appelée avant toute autre méthode métier. Cela protège non seulement contre les erreurs de programmation accidentelles, mais rend également le conteneur plus confiant quant à la réutilisation des instances SFSB. Pour plus de clarté, permettez-moi de mentionner ici qu'aucune méthode d' initialisation désignée (comme ejbCreate) n'est à l'étude; le groupe d'experts envisage uniquement d'avoir une méthode de marque d'annotation comme méthode d'initialisation.
  • Doit-il être configurable que l'arrêt anormal de la @Removeméthode ne supprime pas l'instance du bean? Encore une fois, mon vote est oui. Cela ne fera que donner un meilleur contrôle au fournisseur de bean et aux programmeurs clients. Une seule question reste: qu'arrive-t-il aux beans marqués comme non supprimés lors d'un appel infructueux à la méthode remove et que la méthode remove d'une instance particulière ne se termine jamais avec succès? Il n'existe aucun moyen de supprimer ces instances par programme, mais elles seront supprimées à l'expiration de la session.

Reportez-vous au code source pour un exemple de SFSB.

Beans pilotés par message

Message-driven beans (MDBs) are the only kind of bean that must implement a business interface. This interface's type indicates the type of messaging system that the bean supports. For JMS (Java Message Service)-based MDBs, this interface is javax.jms.MessageListener. Note that the MDB business interface is not truly a business interface, it is just a messaging interface.

Entity beans

Entity beans are marked with the @Entity annotation, and all properties/fields in the entity bean class not marked with the @Transient annotation are considered persistent. Entity bean persistent fields are exposed through JavaBean-style properties or just as public/protected Java class fields.

Entity beans can use helper classes for representing entity bean state, but instances of these classes don't have a persistent identity. Instead, their existence is tied strongly to the owning entity bean instance; also these objects are not shareable across entities.

Refer to the source code for some example entity beans.

Entity relationships

EJB 3.0 supports both unidirectional and bidirectional relationships between entity beans, which can be one-to-one, one-to-many, many-to-one, or many-to-many relationships. However, the two sides of a bidirectional relationship are distinguished as the owning side and the inverse side. The owning side is responsible for propagating relationship changes to the database. For many-to-many associations, the owning side must be explicitly specified. Actually it's the reverse side that is specified by the isInverse=true annotation member on the reverse side's ManyToMany annotation; from that, the owning side is deduced. Now, didn't the expert group say it was making EJB easier?

O/R mapping

The O/R mapping model has also significantly changed from the abstract-persistence-schema-based approach to a Hibernate-inspired one. Though the expert group is still discussing the model, and a clear picture will emerge only with the next draft, this draft features clear indications of the overall approach.

For one, the O/R mapping will be specified in the entity bean class itself by annotations. Also, the approach is to refer to concrete tables and columns instead of the abstract persistence schema. The O/R mapping model has intrinsic support for native SQL; that is, support at a deeper level, not just the ability to run native SQL queries. For example, the column definitions annotation (@Column) has a member columnDefinition that can be something like columnDefinition="BLOB NOT NULL".

Client programming model

An EJB client can acquire a reference to the bean's business interface using the injection mechanism (@Inject annotation). Using the newly introduced @javax.ejb.EJBContext.lookup() method is another approach. But the specification is not clear as to how a standalone Java client acquires reference to a bean instance since the standalone Java clients run in a J2EE client container and lack access to the @javax.ejb.EJBContext object. There is yet another mechanism—a newly introduced universal context object: @javax.ejb.Context(). But, again, the spec does not say how this object can be used in a client container.

EJB QL

Queries can be defined through the @NamedQuery annotation. Two members of this annotation are name and queryString. Once defined, this query can be accessed using the EntityManager.createNamedQuery(name) method. You can also create a regular JDBC-style (Java Database Connectivity) query by calling EntityManager.createQuery(ejbqlString) or a native query using EntityManager.createNativeQuery(nativeSqlString).

EJB QL queries can have both positional as well as named parameters. The javax.ejb.Query interface provides methods for setting these parameters, executing updates, listing results, etc.

Here is one example of how an EJB QL query can be created and executed:

.. .. @NamedQuery (name = "findAllCustomersWithName", queryString = "SELECT c FROM Customer c WHERE c.name LIKE: custName") .. .. @Inject public EntityManager em; clients = em.createNamedQuery ("findAllCustomersWithName") .setParameter ("custName", "Smith") .listResults ();

La liste suivante répertorie certaines des nombreuses améliorations apportées à la QL elle-même: