createMarin
crée bien un
Marin
, plutôt que de retourner -1 systématiquement (ça sera plus utile !).
findMarinById(long)
et
getAllMarins()
, qui retournent respectivement le marin dont on a donné la clé primaire, et la liste de tous les marins en base.
entityMananger.persist()
, dans une transaction que nous avons gérée manuellement.
Dans un serveur d'applications, les choses ne se déroulent pas tout à fait de la même manière.
Tout d'abord, comme nous l'avons entrevu sur notre unité de persistance, les transactions ne sont plus gérées par notre code, mais par le serveur directement. Dans son comportement par défaut, lorsque nous entrons dans une méthode d'un EJB (on appelle ces méthodes des
business methods
, ou méthode métier), le serveur d'application a ouvert une transaction pour nous. Lorsque l'on quitte cette méthode, le serveur tente de valider cette transaction, sans que nous n'ayons rien à faire. Si cette validation échoue, alors une exception est générée.
De plus, l'
entity manager
que l'on utilise est fourni par le serveur d'applications, en tant que dépendance injectée. Ce mécanisme d'injection de dépendances nous permet de nous affranchir complètement de la création de nombre d'objets techniques. Voyons ces deux points sur l'exemple de notre EJB.
Exemple 62. Injection de l' entity manager dans un EJB
@Stateless(mappedName="MarinService") @Remote(MarinService.class) public class MarinServiceImpl implements MarinService { // création et injection d'un entity manager associé à // l'unité de persistance nommée cours-ear-pu @PersistenceContext(unitName="cours-ear-pu") private EntityManager em ; @Override public long createMarin(String nom) { Marin marin = new Marin() ; marin.setNom(nom) ; em.persist(marin) ; return marin.getId() ; } }
EntityManager
avec
@PersistenceContext
. Cette annotation prend en attribut le nom de l'unité de persistance à laquelle cet
entity manager
est attaché. Ce nom doit donc être le même que celui que l'on a défini dans notre fichier
persistence.xml
.
À chaque fois que notre méthode
createMarin(String)
sera appelée, le serveur d'applications créera un nouvel
entity manager
, que nous pourrons utiliser directement.
On voit aussi que le code de gestion de la transaction a disparu : cette gestion est prise en charge par le serveur d'applications. En fait, appeler la méthode
entityManager.getTransaction()
jettera même une exception : lorsque nous sommes dans ce contexte, il n'est pas autorisé de tenter d'accéder à cette transaction.
Ce mécanisme d'injection de dépendances est apparu en JEE5, et il est massivement utilisé en JEE6. Il peut paraître un peu choquant au premier abord : nulle part on n'initialise cette variable
em
dans notre code, ce n'est qu'au moment de son utilisation qu'elle est initialisée par le serveur d'applications.
MarinService
, il nous faut créer son implémentation dans
MarinServiceImpl
.
Exemple 63. Ajout de la méthode
findMarinById(long)
@Override
public Marin findMarinById(long id) {
Marin marin = em.find(Marin.class, id) ;
return marin ;
}
Marin
.
Exemple 64. Création d'une requête nommée sur la classe
Marin
@NamedQueries({ @NamedQuery( name="Marin.findAll", query="select marin from Marin marin") }) @Entity public class Marin implements Serializable { // reste de la classe }
findAllMarins()
de notre EJB.
Exemple 65. Utilisation d'une requête nommée dans un EJB
@Override public List<Marin> findAllMarins() { Query query = em.createNamedQuery("Marin.findAll") ; List<Marin> marins = query.getResultList() ; return marins ; }
Exemple 66. Code de l'application cliente
public static void main(String... args) throws NamingException { // connexion à l'annuaire de notre serveur d'application // ne pas oublier le fichier jndi.properties ! InitialContext context = new InitialContext() ; // requête sur l'annuaire : récupération d'une référence sur notre EJB MarinService marinService = (MarinService)context.lookup("MarinService") ; // utilisation de cet EJB long id = marinService.createMarin("Surcouf") ; System.out.println("Id = " + id) ; Marin marin = marinService.findMarinById(id) ; System.out.println("Marin = " + marin) ; List<Marin>marins = marinService.findAllMarins() ; for (Marin m : marins) { System.out.println("Marin = " + m) ; } }
main()
a quitté. Or la base ne se réinitialise qu'au démarrage de notre unité de persistance, qui est maintenant attachée à l'application entreprise. Donc, si l'on lance notre client plusieurs fois de suite, on verra autant de marins "Surcouf" créés en base.
Notons enfin, que Netbeans a une bonne capacité à rafraîchir en temps réel l'application entreprise déployée, que le simple fait de modifier la classe
Marin
, ou notre EJB, peut entraîner immédiatement le redéploiement de cette application.