Académique Documents
Professionnel Documents
Culture Documents
© M. Lahmer, v.2023
•JDK 1.0
•JDK 1.1
•Décembre 98 : Java 2
Spécification
J2ME J2SE JEE
(Java 2 Micro Edition) (Java 2 Standard Editon) (Java 2 Enterprise Edition)
Implémentation SUN
J2SDK JEE SDK
(Java 2 SDK Standard Edition) (Java 2 SDK Enterprise Edition)
JEE Evolution
Oracle decided to give away the rights for Java EE to the Eclipse Foundation
Java Entreprise Edition
Objectifs de JEE
=>
Permettre aux développeurs de se
concentrer sur le développement métier en
les dégageant des services bas niveaux
(Transactions, Intégration, Équilibrage de
charge, Nommage, Persistance, Sécurité,
Clustering…)
Application
Interface Java pour un
accès standard à des
bases de données JDBC API
hétérogènes.
JDBC Driver
DB API
DB
Java Entreprise Edition
Java Application
Java Servlets
Convertis en Servlets.
Utilise la notion des tags pour inclure du code Java
dans le HTML.
JavaMail
JEE
Home
Bean
Remote
EJB Container
Java Entreprise Edition
Trois approches :
• Approche fonctionnelle.
• Approche conversationnelle.
• Approche de persistance.
Équivalent à :
• Stateless session bean
• Stateful session bean
• Entity bean
Une servlet est une classe Java qui implémente les primitives du
protocole HTTP
init
service(
destroy(
Servlet
Une servlet simple
package estm.dsic;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
@WebServlet(name = "UserServlet", urlPatterns = "/userServlet",
initParams={
@WebInitParam(name="name", value="Not provided"),
@WebInitParam(name="email", value="Not provided")}))
public class UserServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>première servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Salam a tous in jakarta ee </h1>");
out.println("</body>");
out.println("</html>"); }}
</servlet>
<servlet-mapping>
<servlet-name>userServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
</web-app>
HttpServletRequest/HttpServletResponse
HttpSServletRequest
getParameter(paramName), getParameteres(),getRequestDispatcher()
getAttribute(attName), getAttributes(),setAttribute(name,value),
getServletContext(), getCookies(), getSession(), getContentLength,
getContentType
HttpServletResponse
addCookie(Cookie cookie), sendError(int sc),sendRedirect(String url)
sendError(int sc,String msg), getWriter(), setCharacterEncoding,
setContentLength, setContentType, setLocale
Modèle MVC
HTML/Servlet
HTML/Servlet (2)
composant
HTML/Servlet (3)
<!DOCTYPE html>
<html>
<head>
<title>Context and Initialization Servlet Parameters</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Please fill the form below:</h2>
<form action="${pageContext.request.contextPath}/userServlet" method="post">
<label for="name"><strong>Name:</strong></label>
<input type="text" name="name" id="name">
<label for="email"><strong>Email:</strong></label>
<input type="text" name="email" id="email">
<input type="submit" value="Send">
</form>
</body>
</html>
Cookies
Cookie ck=new Cookie("user", "lahmer");
response.addCookie(ck);
Cookie ck[]=request.getCookies();
for(int i=0;i<ck.length;i++){
out.print("<br>"+ck[i].getName()+" "+ck[i].getValue());}
DataSource et JNDI
Scriptlet JSP
Actions standards
■ Exemple: <jsp:useBean> ... </jsp:useBean>
Directives
Directives: exemples
Directives supplémentaires
Inclure un fichier
■ <%@ include file="header.html" %>
Redirection
■ <jsp:forward page="page.jsp" /> redirige la requête vers
une autre ressource :
■ .jsp, servlet, …
Expressions de script
Pour les expression de la forme <%= expr %>, expr est évalué puis
affiché sous forme de chaîne de caractère dans la sortie standard out.
Dans une servlet il peut être équivalent à :
PrintWriter out = response.getWriter();
...
out.print(expr);
Exemples
Déclaration
<%!
private int toInt(String s){
return Integer.parseInt(s);}
%>
<html>
<body><center>
<%!int compteur=0;%>
<%int t=0;%>
<h1>Variable persistante :<%=compteur++%> </h1>
<hr>
<h2>Variable non persistante :<%=t++%> </h2>
</center>
</body>
</html>
<html>
<head><title>Test Jsp</title></head>
<body>
<h1>JSP Processing form with GET</h1>
<form action="Form.jsp" method="GET">
Login: <input type="text" name="login"><br />
Password: <input type="text" name="passwd">
<p><input type="submit" name="button"
value="Valider"></p>
</form>
</body>
</html>
Les Objets implicites
request de type HttpServletRequest ;
response de type HttpServletResponse ;
out de type JspWriter, sous-type de PrintWriter ;
session de type HttpSession ;
application de type ServletContext ;
config de type ServletConfig ;
pageContext de type PageContext (permet de partager des données
entre pages) ;
page équivalent à this
exception définie dans une page jsp d'erreur pour le traitement des
erreurs
Par défaut la méthode service d'une page jsp est multithread. Donc il e
indispensable d'appliquer un mécanisme de synchronisation sur les obje
partagés
<% synchronized (application) {
SharedObject foo = (SharedObject)
application.getAttribute("sharedObject");
foo.update(someValue);
application.setAttribute("sharedObject",foo);}
%>
Composante JavaBean
Un bean en java est une classe
■ Avec un constructeur par défaut
■ Des méthodes de la forme getProperty et setProperty ou property est le nom de la
propriété de la classe
■ ne doit pas avoir d'attribut public
■ Si la propriété est de type booléen la méthode getProp() est remplacée par isProp().
Une instance d'un bean peut être construite à partir de JSP par
■ <jsp:useBean id = "instance" class = "beanClass" />
■ Si l'instance existe déjà alors cette instruction n'a aucun effet
Package Test
public class hello{
private String message; // propriété
public hello()
{ message = "Hello World"; }
public String getMessage()
{ return message; }
public void setMessage(String m)
{ message = (m == null) ? "Hello World" : m;
}
}
Communication avec le bean
application
plus visible
Session
Request
Page
Moins visible
Interaction entre JSP et Servlets
Par défaut toutes les pages JSP et servlets participent à une session HTTP
L'objet session est une bonne place pour stocker les beans et les objets
partagés
Chaque session est identifiée par un ID et stockée dans le navigateur
comme une cookie
Java Server Faces est un framework de développement d’applications Web en Java Java
Server Faces permet
une séparation de la couche présentation des autres couches (MVC)
un mapping entre l’HTML et l’objet
un ensemble de composants riches et réutilisables
une liaison simple entre les actions côté client de l’utilisateur (eventListener) et le code
Java côté serveur
Création de nouveaux composants graphiques
JSF peut être utilisé pour générer autre chose que du HTML (XUL, XML, WML, …)
Jakarta Server Faces 3.0, Release for Jakarta EE 9
Jakarta Faces 4.0, Release for Jakarta EE 10
primefaces https://www.primefaces.org
Java Server Face : principe de fonctionnement
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/
javaee/web-facesconfig_2_2.xsd »>
<managed-bean>
<managed-bean-name>hello</managed-bean-name>
<managed-bean-class>estm.dsic.jee.models.HelloBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>
JSF : faces-config.xml
<?xml version="1.0"?>
<faces-config>
<navigation-rule>
<from-view-id>/page.jsp</from-view-id>
<navigation-case>
<from-outcome> Cas-1 </from-outcome>
<to-view-id>/page1.jsp</to-view-id>
</navigation-case>
</navigation-rule>
…
</faces-config>
Pour chaque valeur de message une page vue de direction est indiquée
dans la balise <navigation-case>
<from-action>: l’action dans le managedBean
<from-outcome>: la valeur du message
<to-view-id> : la vue de direction
JSF : ManagedBean
JSF : View
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="Nom :"/>
<h:inputText value="#{login.nom}" />
<h:outputText value="Mot de passe :"/>
<h:inputSecret value="#{login.mdp}"/>
<h:commandButton value="Login" action="Enregistrer"/>
</h:panelGrid>
</h:form>
</f:view>
</html>
Navigation
JSF : Navigation
<navigation-case>
<from-outcome>Annuler</from-outcome>
<to-view-id>/Rejet.jsp</to-view-id>
</navigation-case>
• Messages
FacesMessage facesMessage = new FacesMessage("Votre message");
FacesContext facesContext =FacesContext.getCurrentInstance();
facesContext.addMessage("myform:id_Input", facesMessage);
<h:message for="id_Input" style="color:red" />
• Session
ExternalContext ec=
FacesContext.getCurrentInstance().getCurrentInstance().getExternalC
ontext();
ec.invalidateSession();
JSF 2.3
@FacesConfig
@ApplicationScoped
Class FacesApp{}
@Inject FacesContext facesContext;
@Inject ExternalContext externalContext;
Validator prédéfini
Tag Function
f:validateDoubleRange Attributs minimum et maximum
f:validateLongRange Attributs minimum et maximum
f:validateLength Attributs minimum et maximum
f:validateRegEx Une expression régulière
f:validator Un validateur personalisé
l’attribut binding pointe vers une classe qui
implémente Validator
f:validateBean Un validateur personalisé
l’attribut binding pointe vers une instance de
BeanValidator
f:validateRequired Ne doit pas être nul (même effet que required)
JSF: Validator personnalisé
@FacesValidator("org.estm.EmailValidator")
public class EmailValidator implements Validator{
private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\." +
"[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*" +
"(\\.[A-Za-z]{2,})$";
private Pattern pattern;
private Matcher matcher;
public EmailValidator(){
pattern = Pattern.compile(EMAIL_PATTERN);
}
@Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
matcher = pattern.matcher(value.toString());
if(!matcher.matches()){
FacesMessage msg =
new FacesMessage("E-mail validation failed.",
"Invalid E-mail format.");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
JSF: Converter
Conversion automatique si on a associé le composant à une
propriété d’un managed bean avec un type standard
• BigDecimalConverter, BooleanConverter, DateTimeConverter,
DoubleConverter, EnumConverter, …
• Pour une date (date, time, ou les deux):
<h:outputText value="#{user.date-naiss}">
<f:convertDateTime type="date" dateStyle="full" /> </
h:outputText>
Attributs pour personnaliser le convertisseur dateStyle, locale,
pattern, timeStyle, timeZone, type
• Convertisseur personnalisés
<h:inputText value="#{Bean.age}" />
<f:converter ConverterId="#{MyCoverter}" />
</h:inputText>
JSF: Converter personnaliser
@Override
public Object getAsObject(FacesContext context, UIComponent component,
String value)
{}
@Override
public String getAsString(FacesContext context, UIComponent component,
T value)
{
}
}
Ajax en JSF
1 <h:form id="form_1">
2 <h:panelGrid id="panel_1" rows="2">
3 <!-- content irrelevant -->
4 </h:panelGrid>
5 </h:form>
6
7 <h:form id="form_2">
8 <h:commandButton id="button">
9 <f:ajax render=":form1:panel_1 panel_2" />
10 </h:commandButton>
11 <h:panelGrid id="panel_2">
12 <!-- content irrelevant -->
13 </h:panelGrid>
14 </h:form>
JSF : AJAX : demo
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:form>
<h:inputText id="inputName" value="#{user.login}"></h:inputText>
<h:commandButton value="valider">
<f:ajax execute="inputName" render="outputMessage" />
</h:commandButton>
<h:outputText id="outputMessage"
value="#{user.login!=null ? user.welcomeMessage : ' '}" />
</h:form>
</html>
Demo messages
faces-config.xml
<application>
<resource-bundle>
<base-name>estm.dsic.business.messages</base-name>
<var>msg</var>
</resource-bundle>
</application>
*.xhtml
<f:loadBundle basename="estm.dsic.business.messages" var=« msg"/>
<h:outputText value=« #{msg[‘E0001']}/>
<h:outputText value=« #{msg.E0001}/>
<h:outputFormat value=« #{msg[‘I0001']}>
• <f:param value="param0" />
<f:param value="param1" />
</h:outputFormat>
Jakartaee-9.1/api
[
appAuthentication-2.0, appAuthorization-2.0, appClientSupport-2.0,
appSecurity-4.0, batch-2.0, beanValidation-3.0, cdi-3.0, concurrent-2.0,
connectors-2.0, connectorsInboundSecurity-2.0, distributedMap-1.0,
enterpriseBeans-4.0, enterpriseBeansHome-4.0, enterpriseBeansLite-4.0,
enterpriseBeansPersistentTimer-4.0, enterpriseBeansRemote-4.0,
expressionLanguage-4.0,
faces-3.0, jakartaee-9.1, jdbc-4.2, jndi-1.0, json-1.0, jsonb-2.0, jsonp-2.0,
mail-2.0, managedBeans-2.0,
mdb-4.0, messaging-3.0, messagingClient-3.0, messagingSecurity-3.0,
messagingServer-3.0,
pages-3.0, persistence-3.0, persistenceContainer-3.0, restConnector-2.0,
restfulWS-3.0, restfulWSClient-3.0, servlet-5.0, ssl-1.0, transportSecurity-1.0,
webProfile-9.1, websocket-2.0, xmlBinding-3.0, xmlWS-3.0
REST principe
•Text
•XML
•JSON
•Binaire
import javax.ws.rs.GET;
//Context de l’application sous Wildfly
import javax.ws.rs.Path; import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Produces; import javax.ws.rs.core.Application;
@Path("services") @ApplicationPath("/api")
public class jaxrsServices { public class RsApp extends Application{
@GET
}
@Path("/hello")
@Produces(value="text/plain") URL
http://localhost:8080/Projet/api/services/hello
public String getHello()
{
return "SALAM";}}
@QueryParam
Permet d'associer un paramètre de la requête à un champ ou un paramètre
d'une méthode
@DefaultValue("defaultValue") Permet de spécifier la valeur par
défaut
@GET
@Path("/json")
@Produces(MediaType.APPLICATION_JSON)
public Client getjsonHello(@DefaultValue("lahmer")@QueryParam("nom")
String nom){
return L.get(nom);//L de type Vector}
L’accès se fait par URL: http://machine/api/json?nom=lahmer
Annotations Jax-rs @PathParam
@PathParam
Dans l’annotation « @Path », il est possible de mettre des
parties variables entre accolades {}. Ils peuvent alors être
récupérés comme paramètres de la méthode avec l’annotation
« @PathParam »
@DELETE
@Path("/delete/{userId}")
public boolean deleteUser(@PathParam("userId") String
userId)
{..}
L’accès se fait par URL: http://machine/rest/delete/1
Annotations Jax-rs @FormParam
@FormParam
Permet de récupérer directement les paramètres depuis un
formulaire html.
<form action="add" methode="post">
<input name="nom" typte=text/>
….
</form>
@POST
@Path("/add/")
public boolean addUser(@FormParam("nom") String nom)
{..}
URL: http://machine/rest/add
Java Persistance API
« JPA »
94
JPA Les principes
❖ JEE propose une couche d’abstraction par dessus JDBC pour la persistence des données appelée
JPA
❖ JPA précise les modalités de fonctionnement d’un ORM (Object Relationnel Mapping) Java à base
des annotations
❖ Plusieurs implémentations JPA qui supporte la version 3.0 :
❖ Eclipse Link
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>3.0.1</version>
</dependency>
❖ OpenJpa
❖ Hibernate
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core-jakarta</artifactId>
<version>5.5.2</version>
</dependency>
❖ Les entités dans les spécifications de l'API Java Persistence permettent d'encapsuler les données
d'une occurrence d'une ou plusieurs tables.
❖ Généralement, elle représente une table dans une base de données relationnelle, et chaque
instance de l'entité correspond à une ligne dans cette table.
95
Entity JPA
import java.io.Serializable;
Annotation Description
import javax.persistence.* @Entity Declares the class as an
@Entity entity
public class Mesure implements @Table Specifies details of the table
Serializable { such as name
private static final long @NamedQuery Specifies a predefined
serialVersionUID = 1L; database query that is run
@Id by an EntityManager
@GeneratedValue(strategy = instance.
GenerationType.IDENTITY) @Id Declares the primary key of
private Long id; the entity
@Column() @GeneratedValue Specifies the strategy used
private double cm; for generating the value of
@Column(name="litre") the primary key. The
strategy =
private double l;
GenerationType.AUTO
//getters
@Column Specifies that the field is
//setters
mapped to a column in the
}
database table.
96
Persistence.xml
Chemin : Projet/src/main/resources/META-INF/persistence.xml
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="mydb" transaction-type="JTA">
<jta-data-source>jdbc/mydb</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="jakarta.persistence.schema-generation.database.action"
value="create"/>
</properties>
</persistence-unit>
</persistence>
98
EMP DEPARTMENT
ID DEPT_ID ID DNAME
PK FK PK
99
@Entity
@Table(name = "users")
@Entity
public class User {
@Table(name = "address")
@Id
public class Address {
@GeneratedValue(strategy =
@Id
GenerationType.AUTO)
@GeneratedValue(strategy =
@Column(name = "id")
GenerationType.AUTO)
private Long id;
@Column(name = "id")
@OneToOne(cascade =
private Long id;
CascadeType.ALL)
@OneToOne(mappedBy = "address")
@JoinColumn(name = "address_id",
private User user;
referencedColumnName = "id")
//... getters and setters
private Address address;
}
// ... getters and setters
}
100
Relation: Many to Many
@Entity @Entity
@Table(name="EMP") public class Project {
public class Employee { @Id
@Id
private int id;
private int id;
@JoinTable(name="EMP_PROJ",
private String name;
joinColumns=
@JoinColumn(name="EMP_ID"),
@ManyToMany(mappedBy="p")
inverseJoinColumns= private Collection<Employee> e;
@JoinColumn(name="PROJ_ID")) // getters & setters
@ManyToMany ...
private Collection<Project> p; }
}
101
Employee
EMP -id
-name
PK ID -startDate
NAME
START_DATE
DAILY_RATE
TERM
VACATION
EMP_TYPE
ContractEmployee
NurunEmployee
-dailyRate
-term -vacation
102
PK,F ID -id
-name
K DAILY_RATE
-startDate
TERM
EMP
PK ID
NAME
START_DATE
EMP_TYPE
NurunEmployee
PK,F ID
K VACATIO ContractEmployee
N -dailyRate
NurunEmployee
-term -vacation
103
Entity Manager
@Transactionnal
Class Dao {
@PersistenceContext(name = "jpa-unit")
EntityManager em;
//Insert
User u = new user();
em.persist(u);
//Search, update
User u = em.find(user.class, 1);u.setName("new Name »);
em.merge(u)
And remove
em.remove(u);
//Select
Query q = em.createQuery("SELECT u FROM user u");
List<user> userList = q.getResultList();
}
105
Queries: NamedQueries
On peut sauvegarder des gabarits de requête dans nos entités.
C’est ce qu’on appelle une NamedQuery. Ceci permet :
❖ La réutilisation de la requête
❖ D’externaliser les requête du code.
@Entity
@NamedQuery(name="myQuery", query="Select o from MyPojo o")
public class MyPojo { … }
106