Estoy tratando de acostumbrarme a cómo funciona JSF con respecto al acceso a los datos (provenientes de un fondo de spring)
Estoy creando un ejemplo simple que mantiene una lista de usuarios, tengo algo así como
#{u.userId} #{u.userName}
Entonces el “controlador” tiene algo así como
@Named(value = "userListController") @SessionScoped public class UserListController { @EJB private UserListService userListService; private List userList; public List getUserList() { userList = userListService.getUsers(); return userList; } }
Y el “servicio” (aunque parece más como un DAO) tiene
public class UserListService { @PersistenceContext private EntityManager em; public List getUsers() { Query query = em.createQuery("SELECT u from User as u"); return query.getResultList(); } }
¿Es esta la forma correcta de hacer las cosas? ¿Mi terminología es correcta? El “servicio” se siente más como un DAO? Y el controlador siente que está haciendo parte del trabajo del servicio.
¿Es esta la forma correcta de hacer las cosas?
Además de llevar a cabo la lógica empresarial de la manera ineficiente en un método administrado de obtención de frijoles, y utilizando un scope de frijol administrado demasiado amplio, se ve bien. Si mueve la llamada de servicio desde el método getter a un método @PostConstruct
y usa @RequestScoped
o @ViewScoped
lugar de @SessionScoped
, se verá mejor.
¿Mi terminología es correcta?
Está bien. Mientras seas consecuente con él y el código sea legible de una manera sensata. Solo su forma de nombrar clases y variables es algo incómoda (ilógica y / o duplicada). Por ejemplo, yo personalmente usaría users
lugar de userList
, y usaría var="user"
lugar de var="u"
, y usaría id
y name
lugar de userId
y userName
. Además, un “UserListService” parece que solo puede tratar con listas de usuarios en lugar de usuarios en general. Prefiero usar “UserService” para que también pueda usarlo para crear, actualizar y eliminar usuarios.
El “servicio” se siente más como un DAO?
No es exactamente un DAO. Básicamente, JPA es el DAO real aquí. Anteriormente, cuando JPA no existía, todos creían interfaces DAO para que los métodos de servicio pudieran seguir utilizándolos incluso cuando la implementación subyacente (JDBC “viejo”, “viejo” Hibernate, etc.) cambia. La verdadera tarea de un método de servicio es administrar las transacciones de manera transparente. Esto no es responsabilidad del DAO.
Y el controlador siente que está haciendo parte del trabajo del servicio.
Me puedo imaginar que lo hace en esta configuración relativamente simple. Sin embargo, el controlador es, de hecho, parte de la interfaz y no del back-end. El servicio es parte del backend, que debe diseñarse de manera que sea reutilizable en todas las interfaces, como JSF, JAX-RS, JSP + “liso”, incluso Swing, etc. Además, el controlador específico de la interfaz ( también llamado “backing bean” o “presenter”) le permite tratar de una manera específica de frontend con éxito y / o resultados excepcionales, como en el caso de JSF que muestra un mensaje de caras en caso de una excepción lanzada desde un servicio.
Con todo, el enfoque correcto sería el siguiente:
#{user.id} #{user.name}
@Named @RequestScoped // Use @ViewScoped once you bring in ajax (eg CRUD) public class UserBacking { private List users; @EJB private UserService userService; @PostConstruct public void init() { users = userService.listAll(); } public List getUsers() { return users; } }
@Stateless public class UserService { @PersistenceContext private EntityManager em; public List listAll() { return em.createQuery("SELECT u FROM User u", User.class).getResultList(); } }
Aquí puede encontrar un proyecto de lanzamiento del mundo real utilizando las prácticas canónicas de Java EE / JSF / CDI / EJB / JPA: aplicación de inicio de sesión de Java EE .
Es un dao, bueno , en realidad es un repository, pero no se preocupe demasiado por esa diferencia, ya que está accediendo a la base de datos utilizando el contexto de persistencia.
Debe crear una clase de servicio, que ajuste ese método y sea donde se invocan las transacciones.
A veces las clases de servicio se sienten innecesarias, pero cuando tienes un método de servicio que llama a muchos métodos de dao, su uso está más justificado.
Normalmente termino creando el servicio, incluso si se siente innecesario, para asegurar que los patrones permanezcan iguales y el dao nunca se inyecta directamente.
Esto agrega una capa extra de abstracción que hace que la futura refactorización sea más flexible.