Programmation Web Avancée 4 : Plan Programmation Web Avancée Spring MVC, Injection de Dépendances MVC Web et Spring MVC Projets Rappel : MVC Web en Pratique Injection de Dépendances Introduction à la persistance en Java Java Persistence API (JPA) 4 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Programmation Web Avancée 4 : Plan MVC Web et Spring MVC MVC avec Spring dans ce cours Modèle JavaBeans (objets Java) persistance avec JPA et Repositories de Spring Data Projets Rappel : MVC Web en Pratique Contrôleur description de route : annotations Java méthodes Java, avec injection de paramètres classe Model pour le ViewModel Injection de Dépendances Introduction à la persistance en Java Vue Java Persistence API (JPA) templates Thymeleaf accès automatique au ViewModel 5 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 6 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Interaction Client Serveur et MVC Programmation Web Avancée 4 : Plan MVC Web et Spring MVC Projets 0 GET ...?q=jean%20dujardin Router (contrôleur) Injection de Dépendances contenu HTML 1 7 Contrôleur Légende: - 0, 1 : requête HTTP - 2 : interogation du modèle - 3/4 : communication avec la base de donnée ou l'ORM - 5 : envoi du ViewModel (modèle de vue) - 6 : vue rendue (HTML, JSON, ...) - 7 : réponse HTTP 2 Rappel : MVC Web en Pratique Introduction à la persistance en Java 6 5 Vue Java Persistence API (JPA) 4 Repository Services (modèle) DB 3 7 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 8 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Les Projets But faire une application web avec génération de page en coté serveur avec serveur REST + client ReactJS Organisation équipes de 3 personnes composition des équipes pour lundi (10 oct.) soutenances le 2 décembre Conseils choisir/proposer son sujet commencer tout de suite (partie que serveur) utiliser git Git : installer git avant vendredi (pour windows, voir le lien sur le guide DSC) Détails sur le site, projets 9 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Programmation Web Avancée 4 : Plan MVC Web et Spring MVC Projets 10 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Previously in PWA (+ astuces) Un modèle « beurk » des équipes avec des co-équipiers sous forme d'objets Java dans une variable « globale » Un/des contrôleur(s) Rappel : MVC Web en Pratique Injection de Dépendances Introduction à la persistance en Java Java Persistence API (JPA) annotation de classe @Controller annotation de méthode @RequestMapping(.....) paramètre « magique » Model m , qui sera passé à la vue m.addAttribute("letruc", valeur) pour remplir le « modèle de vue » paramètre et annotation @RequestParameter pour les formulaires capture de pattern dans l'url avec @PathVariable Une/des vue(s) fichiers Thymeleaf = XHTML + th:.... (templates dite naturelles) remplacer le contenu d'une balise, attribut ... th:text="${letruc}" ... accès à une propriété d'un objet ${letruc.machin} équivalent à letruc.getMachin() en Java répéter la balise donnée, attribut ... th:each="e : ${letruc}" mélanger texte et variables dans une balise la balise doit avoir th:inline="text" (ou il faut utiliser Thymeleaf 3) dans la balise, utiliser des doubles crochets, e.g., Bonjour [[${nom}]] ! gérer les formulaires (cf TP) avec th:action , th:object , th:field Convention maven (système de build) + Spring fichiers Java dans src/main/java/..... fichiers templates dans src/main/resources/templates/ fichiers statiques dans src/main/resources/static/ (pour les .css, .js, images etc) 11 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 12 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Fait entre temps : ajout d'un "id" aux classe du modèle (Equipe et Personne) th:inline="text" , lien détails ( th:href="@{....}" ) 13 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 14 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances suppression, @RequestParam , return "redirect:/...."; page de détails @PathVariable 15 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 16 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Programmation Web Avancée 4 : Plan MVC Web et Spring MVC Projets Rappel : MVC Web en Pratique formulaire d'ajout avec th:action (et th:object , th:field , et constructeur vide) 17 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Injection de Dépendances Introduction à la persistance en Java Java Persistence API (JPA) 18 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Injection de dépendance (DI) Cas sans injection de dépendance il nous faut une instance (par ex, une connection DB) on la crée (ou on utilise une « Factory ») Patron « injection de dépendance » Dependency Injection (DI) Inversion of Control (IoC) quelqu'un fourni l'instance (e.g. avec @Component ), qui est injectée dans notre programme injection par constructeur ou par “setter” 1 2 3 4 class UserObject { @Inject Connection connection; @Inject BlablaService blabla; } Ce que fait à peu près le framework d'injection : il cherche des implémentations de Connection et BlablaService, puis 1 2 3 4 5 Injectons avec @Inject et @Component (+ ajout de dépendance maven à javax.inject) Connection cDB = new SQLDataConnection(); BlablaService s = new BlaBlaServiceImpl(); UserObject obj = new UserObject(); obj.setConnection(cDB); obj.setService(s); 19 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 20 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Programmation Web Avancée 4 : Plan MVC Web et Spring MVC Persistence: motivation When we close/restart an application memory is freed all objects are lost Projets Rappel : MVC Web en Pratique Injection de Dépendances Introduction à la persistance en Java Persistence saving objects state ... on a permanent storage (non-volatile), e.g., database, file, etc allows for reloading objects later Java Persistence API (JPA) 21 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Persistence Options in Java Simple JDBC with or without DAOs (DataAccessObjects) direct access to the SQL database DAO: object that encapsulates/hides SQL requests ORM Concept: Object-Relational Mapping systematic mapping between Java objects and database relations/tables Persistence Frameworks with ORM JPA (Java Persistence API) JDO (Java Data Objects) EJB 3 (Entreprise JavaBeans) Hibernate (Spring), via JPA 23 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 22 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Simple JDBC Example 1 import java.sql.*; 2 … 3 // JDBC driver name and database URL 4 static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 5 static final String DB_URL = "jdbc:mysql://localhost/EMP"; 6 // Database credentials 7 static final String USER = "username"; 8 static final String PASS = "password"; 9 10 public static void main(String[] args) throws ... { 11 12 Class.forName(JDBC_DRIVER); 13 14 Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); 15 16 Statement stmt = conn.createStatement(); 17 18 ResultSet rs = stmt.executeQuery("SELECT id, prenom, nom, age FROM Employes"); 19 20 while(rs.next()){ 21 22 int id = rs.getInt("id"); 23 int age = rs.getInt("age"); 24 String first = rs.getString("prenom"); 25 String last = rs.getString("nom"); 26 27 System.out.print(id + " : " + first + " " + last + " agé de " + age); 28 } 29 30 rs.close(); // hum.... 31 stmt.close(); // hum.... 32 conn.close(); // hum.... 33 } 34 … 24 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Simple JDBC example, Java 7+ 1 import java.sql.*; 2 … 3 // JDBC driver name and database URL 4 static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; 5 static final String DB_URL = "jdbc:mysql://localhost/EMP"; 6 // Database credentials 7 static final String USER = "username"; 8 static final String PASS = "password"; 9 10 public static void main(String[] args) throws ... { 11 12 Class.forName(JDBC_DRIVER); 13 14 try ( 15 Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); 16 Statement stmt = conn.createStatement(); 17 ResultSet rs = stmt.executeQuery("SELECT id, prenom, nom, age FROM Employes"); 18 ) { 19 20 while(rs.next()){ 21 22 int id = rs.getInt("id"); 23 int age = rs.getInt("age"); 24 String first = rs.getString("prenom"); 25 String last = rs.getString("nom"); 26 27 System.out.print(id + " : " + first + " " + last + " agé de " + age); 28 } 29 } 30 } 25 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances JDBC simple : avantages/inconvénients ? 26 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Objet-Relational Mapping: concept Object-Relational Mapping Relation(s) Car id: long price: long model: String company: String Questions? what class corresponds to what table what attribute corresponds to what column what attribute corresponds to what foreign key what are the multiplicities Vehicle id company model price opt_id In practice using JDBC, manually… tedious source code very long (most of the app) very repetitive code dangerous code (error-prone) difficult to evolve Option * id: long desc: String Option id using a persistence framework desc JPA, JDO, Hibernate writing metadata on Java classes and attributes Objects 27 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 28 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Programmation Web Avancée 4 : Plan JPA: Java Persistance API MVC Web et Spring MVC Why the JPA standard? Pure JDBC: tedious Data Access Objects: abstraction, but too much code need a Object/Relational Mapping (ORM) description XML description too verbose and not DRY (Don't Repeat Yourself) proliferation of frameworks (hibernate, toplink, ...) need a usable standard Projets Rappel : MVC Web en Pratique Injection de Dépendances Introduction à la persistance en Java Java Persistence API (JPA) What is JPA? a set of annotations and conventions description of object/relational mappings originally, a part EJB 3 (Entreprise Java Beans) an EntityManager to manage data (transparent in Spring) to save, em.persist() to delete, em.remove() to read, em.find() , … 29 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 30 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances JPA Annotations: simple example 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import import import import javax.persistence.Column; javax.persistence.Entity; javax.persistence.Id; javax.persistence.GeneratedValue; @Entity public class Car { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String company; private String model; private long price; } ...constr/get/set... Important! 31 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances JPA Annotations: simple example 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import import import import import javax.persistence.Column; javax.persistence.Entity; javax.persistence.Id; javax.persistence.GeneratedValue; javax.persistence.Table; @Entity @Table(name = "Vehicle") public class Car { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.AUTO) private long id; @Column(name = "company") private String company; @Column(name = "model") private String model; @Column(name = "price") private long price; } ...constr/get/set... Important! 32 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances JPA Annotations Class-level @Entity @Table (EJB @Stateless) (EJB @Stateful) … Attribute-level, JavaBean @Column @Id @GeneratedValue @Temporal, @Lob, @Basic @Version @Transient … Others @PersistenceContext … Manipulating JPA Entities (Using an EntityManager ) to read, em.find() , … to save, em.persist() to delete, em.remove() Using Repositories Attribute-level, JavaBean relations @OneToOne @ManyToOne @OneToMany @ManyToMany @MapKey @OrderBy … 33 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances abstraction to list and filter objects need to define an interface implemented automatically, e.g., by Spring Data interfaces: Repository, CrudRepository, PagingAndSortingRepository implementation is obtained via dependency injection 34 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances What Did We Just Do? Update the model add an @Entity on the class add a long id field, with @Id @GeneratedValue(strategy=GenerationType.AUTO) JPA ( @Entity , @Id , @OneToMany , ...), Spring Data ( CrudRepository x2 + .save ), /TEST Create a new repository an (empty) interface (not a class) extending CrudRepository<MyEntity, Long> Used the new repository interface injected it used findAll and save the implementation being provided by spring data According to project configuration (and defaults) spring automatically uses an H2 database the database is in memory (by default) the database schema is automatically created the database is dropped at startup 35 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 36 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances What Did We Just Do? Changing project configuration to override default configuration adding key=value properties in application.properties Using a file database (instead of solely in-memory) spring.datasource.url=jdbc:h2:/tmp/mytestdb Keeping Our Data! Tuning application.properties Stopped dropping (and recreating) the database everytime spring.jpa.hibernate.ddl-auto=none NB about previous point in case one need to re-create the databse (schema update) the line can be remove or, use spring.jpa.hibernate.ddl-auto=create-drop Some properties spring.datasource.password , spring.datasource.username server.port and WAY more 37 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 38 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances Points Clés ORM : avantages/inconvénients ? 39 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances 40 / 40 − Rémi Emonet − Programmation Web Avancée Spring MVC, Injection de Dépendances