web-dev-qa-db-fra.com

Contrôleur JSF, service et DAO

J'essaie de m'habituer au fonctionnement de JSF en ce qui concerne l'accès aux données (provenant d'un fond de printemps)

Je crée un exemple simple qui maintient une liste d'utilisateurs, j'ai quelque chose comme

<h:dataTable value="#{userListController.userList}" var="u">
    <h:column>#{u.userId}</h:column>
    <h:column>#{u.userName}</h:column>
</h:dataTable>

Ensuite, le "contrôleur" a quelque chose comme

@Named(value = "userListController")
@SessionScoped
public class UserListController {
    @EJB
    private UserListService userListService;

    private List<User> userList;

    public List<User> getUserList() {
        userList = userListService.getUsers();
        return userList;
    }
}

Et le "service" (bien qu'il ressemble plus à un DAO) a

public class UserListService {

    @PersistenceContext
    private EntityManager em;

    public List<User> getUsers() {
        Query query = em.createQuery("SELECT u from User as u");
        return query.getResultList();
    }
}

Est-ce la bonne façon de faire les choses? Ma terminologie est-elle correcte? Le "service" ressemble plus à un DAO? Et le contrôleur a l'impression de faire une partie du travail du service.

32
PDStat

Est-ce la bonne façon de faire les choses?

Hormis la mise en œuvre de la logique métier de manière inefficace dans une méthode getter de bean managé et l'utilisation d'une portée de bean managé trop large, cela semble correct. Si vous déplacez l'appel de service de la méthode getter vers un @PostConstruct méthode et utilisez soit @RequestScoped ou @ViewScoped au lieu de @SessionScoped, ça va mieux.

Voir également:


Ma terminologie est-elle correcte?

Ça va. Tant que vous y êtes cohérent et que le code est lisible de manière sensée. Seule votre façon de nommer les classes et les variables est quelque peu maladroite (illogique et/ou duplication). Par exemple, personnellement, j'utiliserais users au lieu de userList, et j'utiliserais var="user" au lieu de var="u", et utilisez id et name au lieu de userId et userName. En outre, un "UserListService" sonne comme s'il ne pouvait traiter que des listes d'utilisateurs au lieu des utilisateurs en général. Je préfère utiliser "UserService" afin que vous puissiez également l'utiliser pour créer, mettre à jour et supprimer des utilisateurs.

Voir également:


Le "service" ressemble plus à un DAO?

Ce n'est pas exactement un DAO. Fondamentalement, JPA est le véritable DAO ici. Auparavant, lorsque JPA n'existait pas, tout le monde a créé des interfaces DAO afin que les méthodes de service puissent continuer à les utiliser même lorsque l'implémentation sous-jacente ("plain old" JDBC, ou "good old" Hibernate, etc.) change. La vraie tâche d'une méthode de service est de gérer de manière transparente les transactions. Ce n'est pas la responsabilité du DAO.

Voir également:


Et le contrôleur a l'impression de faire une partie du travail du service.

Je peux imaginer qu'il fait cela dans cette configuration relativement simple. Cependant, le contrôleur fait en fait partie du frontend et non du backend. Le service fait partie du backend qui doit être conçu de manière à être réutilisable sur tous les frontends différents, tels que JSF, JAX-RS, Jlet + Servlet "plain", même Swing, etc. En outre, le contrôleur spécifique au frontend ( également appelé "backing bean" ou "présentateur") vous permet de traiter de manière spécifique au frontend des succès et/ou des résultats exceptionnels, comme dans le cas de JSF affichant un message de visages en cas d'exception levée par un service.

Voir également:


Dans l'ensemble, l'approche correcte serait comme ci-dessous:

<h:dataTable value="#{userBacking.users}" var="user">
    <h:column>#{user.id}</h:column>
    <h:column>#{user.name}</h:column>
</h:dataTable>
@Named
@RequestScoped // Use @ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {

    private List<User> users;

    @EJB
    private UserService userService;

    @PostConstruct
    public void init() {
        users = userService.listAll();
    }

    public List<User> getUsers() {
        return users;
    }

}
@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public List<User> listAll() {
        return em.createQuery("SELECT u FROM User u", User.class).getResultList();
    }

}

Vous pouvez trouver ici un projet de lancement réel en utilisant ici les pratiques canoniques Java EE/JSF/CDI/EJB/JPA: application de lancement Java EE .

Voir également:

67
BalusC

C'est un dao, enfin un dépôt mais ne vous inquiétez pas trop de cette différence, car il accède à la base de données en utilisant le contexte de persistance.

Vous devez créer une classe de service, qui encapsule cette méthode et où les transactions sont appelées.

Parfois, les classes de service ne semblent pas nécessaires, mais lorsque vous avez une méthode de service qui appelle de nombreuses méthodes dao, leur utilisation est plus garantie.

Normalement, je finis par créer le service, même si cela ne semble pas nécessaire, pour garantir que les modèles restent les mêmes et que le dao n'est jamais injecté directement.

Cela ajoute une couche supplémentaire d'abstraction rendant la refactorisation future plus flexible.

6
NimChimpsky