Controlador JSF, Servicio y DAO

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.

Ver también:

  • Por qué JSF llama getters varias veces
  • ¿Cómo elegir el scope del frijol correcto?

¿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.

Ver también:

  • JSF gestionó las convenciones de nomenclatura de frijoles

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.

Ver también:

  • Encontré JPA, o similar, no aliento el patrón DAO
  • ¿Relación DAO y JDBC?
  • ¿Cuándo es necesario o conveniente usar Spring o EJB3 o todos juntos?

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.

Ver también:

  • Capa de servicio JSF
  • ¿Qué componentes son MVC en el marco JSF MVC?

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 .

Ver también:

  • Creación de páginas de detalles maestros para las entidades, cómo vincularlas y qué ámbito de bean elegir
  • Pasar un bean Pojo administrado JSF2 a EJB o poner lo que se requiere en un objeto de transferencia
  • El filtro no inicializa EntityManager
  • javax.persistence.TransactionRequiredException en una pequeña aplicación facelet

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.