Implémentation d'une architecture deux tiers en Java EE
KX
Messages postés16752Date d'inscriptionsamedi 31 mai 2008StatutModérateurDernière intervention31 août 2024
-
21 mai 2022 à 11:58
Cet article a pour but d’expliquer un code Java complet d'une application serveur qui sert d'intermédiaire entre la base de données et les clients (architecture deux tiers).
Pour plus d'explications sur l'architecture voir l'article Architecture client/serveur à 3 niveaux
Le programme d'exemple fait très peu de chose, il permet de gérer une liste d'utilisateurs (table USER en base de données) qui disposent d'un LOGIN et d'un PASSWORD.
La classe UserEntity.java définit la table USER de la base de données et l'objet Java qui permet de manipuler les données correspondantes (LOGIN et PASSWORD).
Remarque : il n'est pas nécessaire de créer la table en base de données, le programme le fera automatiquement lors de sa première exécution.
package ccm.kx.server.jpa;
import javax.persistence.*;
@Entity
@Table(name = "user")
@NamedQuery(name = "findAllUsers", query = "SELECT login FROM UserEntity")
public class UserEntity {
@Id
@Column(name = "login")
private String login;
@Column(name = "password")
private String password;
public String getLogin(){
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword(){
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Quant à la classe UserService.java elle définit des méthodes d'accès qui permettent de faire des requêtes en base de données.
package ccm.kx.server.service;
import java.util.List;
import javax.persistence.EntityManager;
import ccm.kx.server.ServerLauncher;
import ccm.kx.server.jpa.UserEntity;
public class UserService {
private EntityManager em = ServerLauncher.getEntityManager();
public boolean checkUser(String login, String password) {
UserEntity user = em.find(UserEntity.class, login);
return user != null && user.getPassword().equals(password);
}
public void createUser(String login, String password) {
UserEntity user = new UserEntity();
user.setLogin(login);
user.setPassword(password);
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
}
public void updatePassword(String login, String password) {
UserEntity user = em.find(UserEntity.class, login);
if (user == null)
return;
user.setPassword(password);
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
}
public List<String> listAllUsers(){
return em.createNamedQuery("findAllUsers", String.class).getResultList();
}
}
Remarque : comme pour la création de la table en base de données, il n'est pas nécessaire d'écrire les requêtes SQL non plus, le code Java qui décrit les données que l'on souhaite obtenir permet de construire automatiquement les bonnes requêtes.
NB. Pour la dernière méthode, on a utilisé une @NamedQuery "findAllUsers" qui est décrite dans UserEntity via une requête JPQL (pas SQL), c'est à dire que l'on écrit
SELECT login FROM UserEntity
(l'attribut login de la classe UserEntity) mais pas
SELECT login FROM user
(la colonne login de la table user).
Resources REST
Les services REST permettent aux clients de communiquer avec le serveur, c'est le point d'entrée des requêtes et le point de sortie des réponses, UserResource.java en définit trois :
/user/list pour lister les utilisateurs
/user/updatePassword pour modifier un mot de passe
dans cette configuration la base de données sera créée dans le dossier C:/h2/ qu'il conviendra de modifier si nécessaire.
on est ici en mode drop-and-create, qui va détruire et créer automatiquement la base de données à chaque démarrage, c'est pratique lors du développement du programme, mais dans la mesure où cela supprime toutes les données à chaque fois, il faudra retirer cette ligne une fois le programme terminé.
on définit dans data.sql un script à utiliser lors du démarrage du programme, c'est la seule requête SQL du programme :
INSERT INTO USER (LOGIN, PASSWORD)
SELECT 'admin', 'admin' WHERE NOT EXISTS (SELECT * FROM USER);
Quant à la configuration du serveur, elle se place dans la méthode main de ServerLauncher.java qui sera ici en standalone, mais pourrait être embarqué dans un serveur d'application par exemple.
package ccm.kx.server;
import java.io.IOException;
import java.net.URI;
import java.util.logging.Logger;
import javax.persistence.*;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
public class ServerLauncher {
private static final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("ccm_kx_server");
public static EntityManager getEntityManager(){
return entityManagerFactory.createEntityManager();
}
public static void main(String[] args) throws IOException {
try {
URI uri = URI.create("http://localhost:8080/");
ResourceConfig configuration = new ResourceConfig().packages("ccm.kx.server.rest");
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(uri, configuration);
Logger.getGlobal().info("\n\tPress Enter to shutdown server.\n");
System.in.read();
server.shutdownNow();
} finally {
entityManagerFactory.close();
}
}
}