3.2.11. Changements EJB 2.x

3.2.11.1. Mise à jour de l'application qui utilise EJB 2.x

JBoss EAP 6 a été construit sur des standards ouverts et est conforme à la spécification Java Enterprise Edition 6. Malgré que le serveur d'applications fournit un support pour EJB 2.x, il ne prend plus en charge les fonctionnalités qui vont au-delà de la spécification. Gardez à l'esprit que la spécification Java EE 7 a note que EJB 2.x est facultatif, donc il est fortement recommandé que vous réécriviez le code de votre application aux spécifications EJB 3.x.
Si vous souhaitez migrer votre code EJB 2.x, vous devrez, dans la plupart des cas, effectuer des modifications pour exécuter dans JBoss EAP 6. Cette section décrit certains des changements que vous aurez sans doute besoin d'exécuter dans JBoss EAP 6.
Changements de configuration requis pour exécuter EJB 2.x dans JBoss EAP6

Démarrer le serveur avec tous les profils complets
Les beans CMP EJB 2.x (Container Managed Persistence ) nécessitent Java Enterprise Edition 6 Full Profile. Ce profil contient des éléments de configuration nécessaires à l'exécution de CMP EJB.
Cette configuration contient le module d'extension de org.jboss.as.cmp :
<extensions>
    ...
    <extension module="org.jboss.as.cmp"/>
    ...
</extensions>
Il contient également le sous-système cmp :
<profiles>
    ...
    <subsystem xmlns="urn:jboss:domain:cmp:1.1"/>
    ...
</profiles>
.
Pour démarrer un serveur autonome JBoss EAP 6 avec un profil complet, passer l'argument -c standalone-full.xml ou -c standalone-full-ha.xml sur la ligne de commande quand vous démarrez le serveur.
La configuration du conteneur n'est plus prise en charge
Dans les versions précédentes de JBoss EAP, il était possible de configurer différents conteneurs pour l'entité CMP ou les autres beans et de les utiliser en définissant des références dans le fichier de descripteur de déploiement d'application jboss.xml . Ainsi, il y avait différentes configurations pour SLSB en session beans en général.
In JBoss EAP 6.x, it is possible to use EJB 2 Entity beans with a standard container. However, the different container configurations are no longer supported. The recommended approach is to migrate the EJB2 Stateful Session Beans (SFSB), Stateless Session Beans (SLSB), Message Driven Beans (MDB) to EJB 3, and for the Container-Managed Persistence (CMP) and Bean-Managed Persistence (BMP) Entity Beans to use the Java Persistence API (JPA) according to the EJB 3 specification.
La configuration de conteneur par défaut de JBoss EAP contient un certain nombre de changements pour les beans EJB 2 CMP :
  • Par défaut, le verrouillage pessimistique est actif. Cela peut résulter en blocages.
  • Le code de détection de blocages qui se trouvait au niveau CMP dans JBoss EAP 5.x ne se trouve plus dans JBoss EAP 6.
Dans JBoss EAP 5.x, il était également possible de personnaliser la mise en cache, le pooling, les commit-options et la pile d'intercepteur. Dans JBoss EAP 6, ce n'est plus possible. Il y a qu'une seule implémentation, qui est semblable à la politique d' Instance par transaction avec commit-option C. Si vous migrez une application qui utilise la configuration de conteneur de l'entité bean cmp2.x jdbc2 pm, qui utilise le gestionnaire de perssistance basé JDBC compatible avec CMP2.x, il y aura un impact sur les performances. Ce conteneur a été optimisé pour les performances. Il est recommandé de migrer ces entités dans EJB 3 avant la migration de l'application.
Configuration d'intercepteur côté serveur
JBoss EAP 6 prend en charge l' Interceptor Java EE standard qui utilise des annotations @Interceptors et @AroundInvoke. Cependant, cela ne permet pas les manupulations en dehors de Sécurity ou Transaction.
Dans les versions précédentes de JBoss EAP, il était possible de modifier la pile de l'intercepteur pour avoir des intercepteurs personnalisés pour chaque invocation d'EJB. Cela a été souvent utilisé pour implémenter la sécurité personnalisée ou essayer à nouveau des mécanismes avant les contrôles de sécurité, de contrôles de transaction ou de création. JBoss EAP 6.1 introduit des intercepteurs de conteneur pour fournir des fonctionnalités similaires. Pour plus d'informations sur les intercepteurs de conteneur, voir le chapitre du Guide de développement intitulé Container Interceptors dans le Development Guide pour JBoss EAP.
Une autre approche procure un contrôle plus soutenu, pendant, ou après la phase de validation d'une transaction tout en respectant la spécification Java EE. Il s'agit de la méthode qui utilise le Registre de synchronisation de transactions pour ajouter un listener.
La ressource peut être extraite par l'une des méthodes suivantes :
  • Utiliser InitialContext
    TransactionSynchronizationRegistry tsr = (TransactionSynchronizationRegistry) 
    		new InitialContext().lookup("java:jboss/TransactionSynchronizationRegistry");
    tsr.registerInterposedSynchronization(new MyTxCallback());
    
  • Utiliser l'injection
    @Resource(mappedName = "java:comp/TransactionSynchronizationRegistry")
    TransactionSynchronizationRegistry tsr;
    ...
    tsr.registerInterposedSynchronization(new MyTxCallback());
    
La routine de callback doit implémenter l'interface javax.transaction.Synchronization. Utiliser la méthode beforeCompletion{} pour effectuer une vérification avant que la transaction soit validée ou ou restaurée. Si une exception RuntimeException est levée par cette méthode, la transaction sera annulée et le client sera informé par une exception EJBTransactionRolledbackException. Dans le cas d'une Transaction XA, toutes les ressources seront annulées suivant les termes du contrat XA. Il est également possible d'activer la logique métier pour qu'elle dépende de l'état de la transaction, à l'aide de la méthode afterCompletion(int txStatus). Si une exception RuntimeException est levée par cette méthode, la transactions demeurera dans son ancien état, soit validée, soit restaurée, et le client n'en sera pas informé. Seul le gestionnaire de transactions affichera un avertissement dans les fichiers journaux du serveur.
Configuration côté client pour les intercepteurs côté client
Dans les versions précédentes de JBoss EAP 6, il était possible de configurer les intercepteurs de client dans la configuration serveur et de ne fournir que les classes de l'API client.
Dans JBoss EAP 6, ce n'est plus possible parce que le client Proxy n'est plus créé côté serveur et est transmis au client après la recherche. Maintenant, le proxy est généré côté client. Cette optimisation permet d'éviter un appel de serveur pour les téléchargements de recherche et de classe,
Configuration de Bean Pool
La configuration de Bean Pool n'est pas recommandée dans JBoss EAP 6. Comme elle est limitée à la configuration de l'élément < stricte-max-pool >, des blocages ou autres problèmes peuvent se produire si le pool est trop petit pour charger toutes les entités du résultats. Les beans n'ont pas de grandes méthodes de cycle de vie pendant l'initialisation, donc créer l'instance et le conteneur environnant n'est pas plus lent que d'utiliser une instance d'entité bean regroupée.
Remplacer le fichier de descripteur de déploiement jboss.xml
Le descripteur de déploiement jboss-ejb3.xml remplace le fichier de descripteur de déploiement jboss.xml. Ce fichier de remplacement est là pour améliorer les fonctionnalités fournies par le descripteur de déploiement ejb-jar.xml de Java Enterprise Edition (EE) . Le nouveau fichier est incompatible avec jboss.xml, et jboss.xml est maintenant ignoré dans les déploiements.
Ainsi, dans les anciennes versions deJBoss EAP, si vous définissiez un <resource-ref> dans le fichier ejb-jar.xml, file, vous aviez besoin d'une définition de ressource correspondante de nom JNDI dans le fichier jboss.xml. XDoclet génère ces fichiers de descripteur de déploiement automatiquement. Dans JBoss EAP 6, l'information de mappage de JNDI est maintenant définie dans le fichier jboss-ejb3.xml. Assumez que la source de données soit définie dans le code source Java comme suit :
DataSource ds1 = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/Resource1");
DataSource ds2 = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/Resource2");
Le ejb-jar.xml définit les références de ressource suivantes :
<resource-ref >
    <res-ref-name>jdbc/Resource1</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
<resource-ref >
    <res-ref-name>java:comp/env/jdbc/Resource2</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
Le fichier jboss-ejb3.jxml mappe les noms JNDI avec les références en utilisant la syntaxe XML suivante.
<resource-ref>
    <res-ref-name>jdbc/Resource1</res-ref-name>
    <jndi-name>java:jboss/datasources/ExampleDS</jndi-name>
</resource-ref>
<resource-ref>
    <res-ref-name>java:comp/env/jdbc/Resource2</res-ref-name>
    <jndi-name>java:jboss/datasources/ExampleDS</jndi-name>
</resource-ref>
Some of the configuration options that were available in the JBoss EAP 5.x jboss.xml file were not implemented in JBoss EAP 6. The following list describes some of the commonly used attributes in the jboss.xml file and whether there is an alternate way to achieve them in JBoss EAP 6.
  • L'élément method-attribute était utilisé pour configurer les méthodes de beans de sessions et des entités individuelles.
    • Les options de configuration read-only et idempotent n'ont pas été transférées dans JBoss EAP 6.
    • The transaction-timeout option is now configured in the jboss-ejb3.xml file.
  • L'attribut missing-method-permission-exclude-mode modifie le comportement des méthodes sans implémenter de métadonnées explicites sur un bean sécurisé. Dans JBoss EAP6, l'abscence d'une annotation @RolesAllowed est actuellement traitée de la même façon que @PermitAll
Configuration de mappage de type de source de données
Dans les versions précédentes de JBoss EAP 6, il était possible de configurer les mappages de types de sources de données dans le fichier de configuration de déploiement de source de données *-ds.xml.
Dans JBoss EAP 6, cela doit se faire dans le fichier de descripteur de déploiement jbosscmp-jdbc.xml.
<defaults>  
    <datasource-mapping>mySQL</datasource-mapping>  
    <create-table>true</create-table>  
    ....  
</defaults>
Dans les versions précédentes de JBoss EAP, on pouvait personnaliser le mappage dans le fichier standardjbosscmp-jdbc.xml. Ce fichier n'est plus disponible et le mappage est maintenant effectué dans le fichier de descripteur de déploiement jbosscmp-jdbc.xml.
Additional Container-Managed Persistence (CMP) and Container-Managed Relationship (CMR) Changes

Changements de Collection et d'Itérateur de CMR (Container Managed Relationship)
Dans les versions précédentes de JBoss EAP, il était possible pour certains conteneurs, comme cmp2.x jdbc2 pm d'itérer des collections CMR, de supprimer ou d'ajouter des relations. Parce que la configuration du conteneur n'est pas pris en charge, ce n'est plus possible dans JBoss EAP 6. Pour plus d'informations sur la façon d'obtenir cette même fonctionnalité dans le code d'application, voir EJB2.1 Finder for CMP entities with relations (CMR) returns duplicates in EAP6 dans la section Solutions de base de connaissances de support du Portail clients.
Entrées doubles de CMR (Container Managed Relationship) dans Finders
In previous versions of JBoss EAP, it was possible to select different CMP containers which used different persistence strategies. The cmp2.x jdbc2 pm container in JBoss EAP 5.x used optimized SQL-92 to generate optimized LEFT OUTER JOIN syntax for finders. Because JBoss EAP 6.x only supports the standard container for CMP and CMR, the implementation does not contain these optimizations. The finder should include the keyword DISTINCT in the SELECT statement to avoid cartesian product in the result set. For more information , see EJB2.1 Finder for CMP entities with relations (CMR) returns duplicates in EAP6 in the Support Knowledgebase Solutions section of the Customer Portal.
Changement de valeur de suppression cascade pour les entity beans CMP
La valeur par défaut de suppression de cascade est passée à false. Cela peut entraîner à des erreurs de suppression dans JBoss EAP 6. Si les relations de l'entité sont marquées cascade-delete, vous devez définir explicitement le batch-cascade-delete à true dans le fichier jbosscmp-jdbc.xml. Pour plus d'informations, consultez cascade delete fail for EJB2 CMP Entities after migration to EAP6 dans la section Solutions de base de connaissances de Support du Portail clients.
Mappeurs CMP personnalisés pour champs personnalisés
Si vous utilisez des classes de mappage de clients comme JDBCParameterSetter, JDBCResultSetReader et Mapper dans votre application JBoss EAP 5.x, vous verrez sans doute java.lang.ClassNotFoundException quand vous déployez votre application dans JBoss EAP 6. C'est parce que les noms de packages des interfaces sont passés de org.jboss.ejb.plugins.cmp.jdbc.Mapper à org.jboss.as.cmp.jdbc.Mapper. Pour plus d'informations , voir How to use Field mapping for custom classes in an EJB2 CMP application in EAP6 dans la section Solutions de base de connaissance de Support du Portail clients.
Génération de clés primaires par les entity-commands
Si votre application JBoss EAP 5 utilise des entity-commands pour générer des clés primaires, comme Sequence ou Auto-increment, vous apercevrez sans doute une exception ClassNotFoundException pour la classe JDBCOracleSequenceCreateCommand quand vous migrez votre application dans JBoss EAP 6. C'est parce que le package de classes a été changé de org.jboss.ejb.plugins.cmp.jdbc à org.jboss.as.cmp.jdbc.keygen. Si vous utilisez cette classe dans votre application JBoss EAP 6, vous devrez aussi ajouter une dépendance au module EAP_HOME/modules/system/layers/base/org/jboss/as/cmp.
Changements dans les applications

Modifier le code pour utiliser les nouvelles règles d'espace-noms JNDI.
Comme avec EJB 3.0, vous devrez utiliser le préfixe JNDI complet avec EJB 2.x. Pour davantage d'informations sur les nouvelles règles d'espace-nom JNDI et pour obtenir des exemples de code, voir Section 3.1.8.1, « Mise à jour des noms d'espace-noms JNDI d'application  ».
Exemples qui montrent comment mettre à jour les espace-noms JNDI d'anciennes versions : Section 3.1.8.5, « Exemples d'espace noms JNDI de versions antérieures et la façon dont ils sont spécifiés dans JBoss EAP 6 ».
Modifier le descripteur de fichier jboss-web.xml
Modifier le <jndi-name> pour chaque <ejb-ref> afin d'utiliser le nouveau format de recherche complet JNDI.
Utiliser XDoclet pour mapper un nom JNDI d'interfaces locales internes
Dans EJB 2, il était commun d'utiliser le modèle de Locator pour chercher les Beans. Si vous utilisiez ce modèle dans votre application au lieu de modifier le code d'application, vous pourriez utiliser XDoclet pour créer une mappe des nouveaux noms JNDI.
Une annotation XDoclet typique ressemble à ceci :
@ejb.bean name="UserAttribute" display-name="UserAttribute" local-jndi-name="ejb21/UserAttributeEntity" view-type="local" type="CMP" cmp-version="2.x" primkey-field="id"
Le nom JNDI ejb21/UserAttributeEntity de l'exemple ci-dessus n'est plus valide dans JBoss EAP 6. Vous pouvez mapper ce nom à un nom JNDI valide par le sous-système naming dans la configuration de serveur et grâce à un correctif XDoclet.
Vous pouvez créer des mappeurs personnalisés, comme indiqué dans le paragraphe ci-dessus intitulé CMP Customized Mappers for Custom Fields ou bien, vous pouvez modifier le code comme indiqué dans la procédure ci-dessous.

Procédure 3.24. Modifier le code XDoclet généré et Utiliser le sous-système de nommage

  1. Extraire le modèle XDoclet lookup.xdt qui se trouve dans ejb-module.jar et modifier le lookup() dans lookupHome comme suit :
    private static Object lookupHome(java.util.Hashtable environment, String jndiName, Class narrowTo) throws javax.naming.NamingException {  
        // Obtain initial context  
        javax.naming.InitialContext initialContext = new javax.naming.InitialContext(environment);  
        try { 
            // Replace the existing lookup      
            // Object objRef = initialContext.lookup(jndiName);  
            // This is the new mapped lookup
            Object objRef;  
            try {  
                // try JBoss EAP mapping  
                objRef = initialContext.lookup("global/"+jndiName);  
            } catch(java.lang.Exception e) {  
                objRef = initialContext.lookup(jndiName);  
            }  
            // only narrow if necessary  
            if (java.rmi.Remote.class.isAssignableFrom(narrowTo))  
                return javax.rmi.PortableRemoteObject.narrow(objRef, narrowTo); 
            else  
                return objRef;  
        } finally {  
            initialContext.close();  
        }  
    }
  2. Exécuter Ant, en définissant l'attribut de modèle pour qu'il puisse utiliser le lookup.xdt modifié pour la tâche ejbdoclet.
  3. Modifier le sous-système naming dans le fichier de configuration du serveur pour mapper l'ancien nom JNDI en nouveau nom JNDI valide.
    <subsystem xmlns="urn:jboss:domain:naming:1.2">  
        <bindings>  
            <lookup name="java:global/ejb21/UserAttributeEntity" lookup="java:global/ejb2CMP/ejb/UserAttribute!de.wfink.ejb21.cmp.cmr.UserAttributeLocalHome"/>  
        </bindings>  
        <remote-naming/>  
    </subsystem>
Liste des fichiers obsolètes

Les fichiers suivants ne sont plus pris en charge dans JBoss EAP 6.

jboss.xml
Le fichier de descripteur de déploiement jboss.xml n'est plus pris en charge et sera ignoré s'il est inclus dans l'archive déployée.
standardjbosscmp-jdbc.xml
Le fichier de configuration standardjbosscmp-jdbc.xml n'est plus pris en charge. Cette information de configuration est maintenant incluse dans le module org.jboss.as.cmp et n'est plus personnalisable.
standardjboss.xml
Le fichier de configuration standardjboss.xml n'est plus pris en charge. Cette information de configuration est maintenant incluse dans le ficher standalone.xml quand on exécute un serveur autonome ou le fichier domain.xml dans un domaine géré.