480 likes | 597 Views
Java EE - Rappels -. Pierre-Johan CHARTRE pierre-johan.chartre@logica.com. J2EE Layers. Rappel des différentes couches. Définition : JAVABEAN. Classe Java respectant certaines conventions :
E N D
Java EE - Rappels - Pierre-Johan CHARTRE pierre-johan.chartre@logica.com
J2EE Layers • Rappel des différentes couches
Définition : JAVABEAN • Classe Java respectant certaines conventions : • la classe doit être "Serializable" pour pouvoir sauvegarder et restaurer l'état d'instances de cette classe • la classe doit posséder un constructeur sans argument (constructeur par défaut) • les propriétés privés de la classe doivent être accessibles publiquement via des méthodes accesseurs construit avec get ou set suivi du nom de la propriété avec la première lettre transformée en majuscule • Le respect de ces conventions rend possible l'utilisation, la réutilisation, le remplacement et la connexion de JavaBeans par des outils de développement. 3
Définition : POJO • Plain Old Java Object • Nom « marketing » désignant un simple objet Java ! • Terme inventé en 2000 pour opposer : • les EJB version 1.x & 2.x qui étaient de véritable usines à gaz : • objets Java complexes dont les nombreuses contraintes techniques contraignent fortement leur utilisation • Créations d’un ensembles interfaces, nécessité d’étendre des classe du framework et de redéfinir tout un ensemble de méthodes … • aux simples Objets Javas classiques • Martin fowler says :The term was coined while Rebecca Parsons, Josh MacKenzie and I were preparing for a talk at a conference in September 2000. In the talk we were pointing out the many benefits of encoding business logic into regular java objectsrather than using Entity Beans. We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it's caught on very nicely. 4
Dans ce cours, nous nous concentrerons sur les EJB 3.0 venant de Java EE 5. • Il existe 3 types d’EJBs : • les EJB Entity (entité) utilisés dans la couche d’accès aux données • les EJB Session utilisés dans la couche métier • les EJB MDB (Message Driven Bean) utilisés dans la couche d’intégration. Ils sont utilisés conjointement à des MOMs (Message Oriented Middleware) • On peut distinguer : • les EJBs pré Java EE 5 (EJB 1.x & 2.x) • Objets java fortement contraints (pas sexy) • Les EJBs depuis Java EE 5 (EJB 3.x) • Ce sont des POJOs annotés (sexy) EJB 3.0
Serveurs d’Application Un AS (conteneur lourd) implémente les spécifications de Sun prend en charge la gestion de nombreux services : La concurrence des accès La gestion des transactions La persistance des données Les objets distribués La réception de messages asynchrones Un service de nommage La sécurité La gestion du cycle de vie des EJBs …
Java EE - PersistencE layer = JPA - Pierre-Johan CHARTRE pierre-johan.chartre@logica.com
SGBD versus Application • BDD : • données persistante • monde « relationnel » • Application • données en mémoire durée de vie limité au temps d’exécution de l’application soit en Java l’exécution de la JVM • monde « objet » Contexte
Contexte Schéma Tables colonnes Une ligne = un tuple Relations entre table 1-1 1-n n-m Interrogation via SQL (Structured Query Language) Opération CRUD Create Read Update Delete Objets Metadonnées : Fichiers de configuration Annotations en Java SGBD Application
Problèmes à résoudre : • i : Représentation des éléments du SGBD au sein de l’application (en mémoire) • ii : « Dialogue » avec le SGBD depuis l’application • Connexion au SGBD • Envoi de requêtes au SGBD • Exploitation des données envoyées par la base Problématique
i : Représentation des éléments du SGBD • Objet <> Table • Propriété Objet <> Colonne Table • Mapping de Type • Instance Objet <> Tuple Table • Ces liens sont définis par des métadonnées • Fichier de configuration .xml • Annotation Java Une approche répandue d’ORM
ii : Dialogue avec le SGBD depuis l’application • Design pattern DAO (Data Access Object) • Se connecte à la SGBD pour mettre en œuvre les opérations CRUD • Create • entiteDAO.create( EntiteBean ) • Read • entiteDAO.findByCriteria ( EntiteBean ) : List <EntiteBean> • entiteDAO.findById( cle ) : EntiteBean • Update : • entiteDAO.update( EntiteBean ) • Delete : • entiteDAO.delete ( EntiteBean ) • Manipule des objets représentant des données de la base, ici nommés EntiteBean Une approche répandue d’ORM
JPA 1.0 • Mécanisme de persistance des EJBsEntity • EJB 3 de Java EE 5 • Comporte • Représentation élément SGBD (i) • EJB « Entity » • POJO annoté (de type JavaBean) • Objet permettant opération CRUD (ii) • EntityManager • Fichier de configuration • persistence.xml JPA (Java Persistence Api)
import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Customer { @Id private Long id; private String firstName; private String lastName; // getters et setters // Constructeurs } • Par défaut • Nom entité = Nom classe • @Table( • name = « » • schema = « » …) • Nom propriété = Nom colonne • @Column( • name= « », • nullable = true/false, • lenght = 100 …) JPA : EJBs Entité
@Entity @Table (name = “t_category”) public class Category { (…) @OneToMany(mappedBy= “category”) private List <Product> products; (…) } @Entity @Table (name = “t_products”) public class Product { (…) @ManyToOne @JoinColumn(name = “category_fk”) private Category category; (…) } JPA : Relations bidirectionnelle 1-n
Problème du chargement des entités liées à une entités (par des relations 1-1, 1-n, n-m) • On peut les charger au plus tôt • Eagerloading • Illustration • Quand je charge une instance de Category, tous les Product associés sont chargés et figurent dans la liste products • Problème de chargement récursif • On peut les charger au plus tard • Lazyloading • Illustration • Quand je charge une instance de Category, tous les Product associés ne sont pas chargés • Ce n’est que lorsque que je demande pour la première fois d’accéder aux produits (Category.getProducts()) que la liste productsest chargée • Plus de problème de chargement récursif • Comportement par défaut pour les relations 1-n et n-m Relations : Eager vs Lazyloading
JPA : EntityManager Customer c = new Customer(); c.setId(123); c.setFirstName(“dupond”); em.persist(c); Customer c; c = em.find(Customer.class, 123); Create Read Update Delete Customer c; c = em.find(Customer.class, 123); c.setFirstName(“durand”); em.merge(c); Customer c; c = em.find(Customer.class, 123); em.remove(c); em est l’EntityManager
Queryquery = em.createQuery("select p from Customer p wherep.firstName=‘Durand'"); Customer customer = (Customer) query.getSingleResult(); if (customer != null) {(…)} JPA : JPQL • JPA Query Langage : Langage de requêtage de haut niveau Queryquery = em.createQuery("select p.firstNamefrom Customer p where p.id > 2"); List noms = query.getResultList(); for (Object nom : noms) {(…)} Queryquery = em.createQuery("select p.firstNamefrom Customer p where p.id > :id"); query.setParameter("id", 1); List noms = query.getResultList(); for (Object nom : noms) {(…)} em est l’EntityManager
EntityTransaction transaction = em.getTransaction(); transaction.begin(); // do databasestuff // Everything ok, commit transaction.commit(); // Somethingwentwrong (Exception thrown or something) transaction.rollback(); JPA : Transactions em est l’EntityManager
<?xml version="1.0" encoding="UTF-8"?> <persistencexmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="TestPU"> <provider>oracle.toplink.essentials.PersistenceProvider</provider> <class>com.isima.test.jpa.Category</class> <class>com.isima.test.jpa.Product</class> <class>com.isima.test.jpa.Customer</class> <properties> <propertyname="toplink.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/> <propertyname="toplink.jdbc.url« value="jdbc:derby:C:/Program Files/Java/jdk1.6.0/db/MaBaseDeTest"/> <propertyname="toplink.jdbc.user" value="APP"/> <propertyname="toplink.jdbc.password" value=""/> <propertyname="toplink.logging.level" value="INFO"/> </properties> </persistence-unit> </persistence> JPA : Fichier persistence.xml
import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class MainTest { public staticvoid main(String[] argv) { EntityManagerFactoryemf = Persistence.createEntityManagerFactory("TestPU"); EntityManagerem = emf.createEntityManager(); (…) em.close(); emf.close(); } } Obtention de l’EntityManager (#1)
Entités JPA -> Obtention d’une BDD • Génération de DDL pour générer la base • BDD pré existante -> Entités JPA • Génération des EJBsEntity à partir schéma BDD • Stratégie mixte JPA : Stratégie de génération
Pour fonctionner, JPA à besoin : • D’une librairie implémentant sa spécification • .jar(s) de TopLink, OpenJPA… • Du driver JDBC associé à la base accédée • JPA et les EJBs Entités peuvent s’exécuter : • au sein d’un serveur d’application • dans une application java SE en ajoutant les librairies appropriés • c’est le seul type d’EJB de Java EE 5 dans ce cas Environnement d’exécution
Sous Java • Hibernate • EJB Entity 1.x & 2.x (JAVA Entreprise < 5.0) • Sous Dotnet • ADO.Net Autres Frameworks Similaires
Java EE - BUSINESS layer = EJB - Pierre-Johan CHARTRE pierre-johan.chartre@logica.com
Le but de la couche métier est de contenir et exposer la logique applicative. • Cette couche repose : • sur la couche d’accès aux données fournissant une représentation objet des données • Par exemple, des EJB Entity 3.0 avec JPA • Cette couche peut être invoquée : • par une ou plusieurs couches IHM • Client léger/riche (voir suite du cours) • Client lourd • par une couche d’intégration au SI de l’entreprise Couche métier
La couche métier peut être construite uniquement à partir de simples Objets Java (POJOs). • Java EE fournit également les EJB Session : • ils peuvent être appelés localement (dans la même JVM) ou à distance (depuis une autre JVM). • ils permettent de facilement exposer des traitements métiers aux couches supérieures. Ils sont souvent utilisés comme Façade (Pattern Gof). • ils sont hébergés au sein du conteneur d’EJB d’un serveur d’application. • Depuis Java EE 5.0 (EJB 3.0), ce sont des POJOs annotés Approches possibles avec java ee 5
Un EJB Session peut implémenter : • Une interface locale définissant les méthodes qui peuvent être appelées par un autre EJB s'exécutant dans la même JVM que le conteneur. • Une interface distante définissant les méthodes qui peuvent être appelées par un client en dehors de la JVM du conteneur. EJB Session : les 2 types d’interfaces
import java.util.List; import javax.ejb.Local; @Local public interface CustomerLocal { voidcreate(Customer customer); Customer find(Object id); List<Customer> findAll(); void update(Customer customer); voidremove(Customer customer); } EJB Session : Interface Locale
import java.util.List; import javax.ejb.Remote; @Remote public interface CustomerRemote { voidcreate(Customer customer); Customer find(Object id); List<Customer> findAll(); void update(Customer customer); voidremove(Customer customer); } EJB Session : Interface Distante
Un EJB Session peut être de 2 types distincts. • EJB Session Stateless : • ne conserve pas d’état entre 2 appels • peut être utilisé par plusieurs clients • annoté @Stateless • EJB Session Statefull : • conserve son état entre 2 appels • est dédié à un client • annoté @Stateful EJB Session : gestion de l’état de l’ejb
@Stateless public class CustomerFacadeimplementsCustomerLocal, CustomerRemote { @PersistenceContext privateEntityManagerem; public voidcreate(Customer customer) { em.persist(customer); } public Customer find(Object id) { return em.find(com.isima.test.jpa.Customer.class, id); } public List<Customer> findAll() { return em.createQuery("select object(o) from Customer as o").getResultList(); } public void update(Customer customer) { em.merge(customer); } public voidremove(Customer customer) { em.remove(em.merge(customer)); } } EJB SESSION : IMPLÉMENTATION STATELESS
import javax.naming.InitialContext; public class TestService { public staticvoid main(String[] args) throws Exception { // Récupération via JNDI de l’EJBSession InitialContextctx = new InitialContext(); CustomerRemote c = (CustomerRemote) ctx.lookup("CustomerFacade/remote"); List<Customer> customers = c.findAll(); } } EJB SESSION STATELESS : Invocation#1 Old School
EJB SESSION STATELESS : Invocation#2 Injection de dépendance public class TestService { @EJBprivate CustomerLocalcustomerLogic; ( … ) public void update() {customerLogic.update( getSelectedCustomer() ); } ( … ) } 36
Les EJBs Session ne peuvent s’exécuter qu’au sein du conteneur d’EJB d’un serveur d’application. Environnement d’exécution
Java EE - Integration layer= EJB + MDB + WS - Pierre-Johan CHARTRE pierre-johan.chartre@logica.com
INVOCATION DISTANTE D’EJB • Principes : • Intégration entre 2 composants Java (JVMs) • Invocation à vocation synchrone • Basé sur : • Annuaire JNDI pour identification EJB • RMI pour transport (Appel d’objet distant en Java) • Performant • Pas « firewall friendly » 39
INVOCATION DISTANTE D’EJB#1 - Principe (1) Obtention de l’objet via JNDI (le service de nommage de J2EE). Accès via un « remote stub », un proxy (pattern GOF) généré automatiquement qui a connaissance de l’interface de l’objet à invoquer et masque les détails du transit sur le réseau. (2) Le « remote stub » retransmet l’appel de méthode au travers du réseau via RMI (sauf cas de l’invocation en local). (3) Le client ne connaît que l’interface de l’objet qu’il interroge, ce qui est traduit par le fait qu’il s’adresse à ce que l’on nomme l’interfaceIBusiness. Cette interface est l’interface métier proposée par l’EJB. L’appel sera en réalité traité par l’implémentation de l’interface métier, l’ « EJB object » (4) Celui-ci fourni un niveau d’indirection entre l’objet auquel les clients s’adressent et le bean lui-même géré par le conteneur lourd. Ceci permet au conteneur lourd d’introduire des services (la gestion de la concurrence des accès, la sécurité, la gestion du cycle de vie du bean …) lors de l’accès au bean (5) 41
INVOCATION DISTANTE D’EJB#2 – Le coté « client » • Un client peut être : • une application de type « client lourd » distante • Scénario de type Client/Serveur avec « client lourd » • N Front-end en client lourd (Swing/Swt par exemple) dans une JVM spécifique • 1 Back-end sur un AS • Intégration via JNDI (over RMI) • Une application de type « client léger » • Scénario « client léger » • N Front-end en client léger (Navigateur) sans JVM • 1 Back-end sur un AS contenant : • Des composants webs : Servlets/JSPs, JSF • Invocation des POJOs ou EJBs en local dans l’AS • Intégration entre le navigateur et l’AS en http/https 42
INVOCATION DISTANTE D’EJB#2 – Le coté « client » • Principe du proxy (Stub) pour une gestion transparente de l'appel distant • Sérialisation & Désérialisation • RMI (RemoteMethod Invocation) • Dans le cas particulier d’un client local, au sein de la même JVM • Il existe également un proxy mais particulier car dépourvu des accès réseau. Ce proxy permet au conteneur d'assurer certains services tout en garantissant de bonne performance (pas d’appels réseau inutiles) 43
Services Web • Principe : • Invocation de service à vocation synchrone • Permet l’intégration d’application hétérogène • Java, Dotnet … • « firewall friendly » : • XML, SOAP • HTTP/HTTPS • Verbeux donc moins performant • Voir cours intégration pour détail 44
MOM • Message Oriented Middleware • Principe : • Invocation de service à vocation asynchrone • Permet intégration application hétérogène • « Bus d’intégration », « Enterprise Service Bus » • Doit s’entendre sur : • Format message • Type de publication • En Java : • API JMS • Utilisation des EJBs MDB 45
Keywords Lazyloading EntityManager @Entity @Stateless @MessageDrivenBean EJB @Column JPQL @Table @RolesAllowed CRUD persistence.xml J2EE @Local JPA @Remote @EmbededId @ManyToMany @Id @ManyToOne @OneToMany DOA @OneToOne @OneToMany @Stateful @Embedable ORM @TransactionnalAttribute CriteriaBuilder