tutorial - jsf primefaces
Controlador JSF, Serviço e DAO (2)
Estou tentando me acostumar com o funcionamento do JSF no que diz respeito ao acesso a dados (provenientes de um segundo plano na primavera)
Estou criando um exemplo simples que mantém uma lista de usuários, tenho algo como
<h:dataTable value="#{userListController.userList}" var="u">
<h:column>#{u.userId}</h:column>
<h:column>#{u.userName}</h:column>
</h:dataTable>
Então o "controlador" tem algo como
@Named(value = "userListController")
@SessionScoped
public class UserListController {
@EJB
private UserListService userListService;
private List<User> userList;
public List<User> getUserList() {
userList = userListService.getUsers();
return userList;
}
}
E o "serviço" (embora pareça mais com um DAO) tem
public class UserListService {
@PersistenceContext
private EntityManager em;
public List<User> getUsers() {
Query query = em.createQuery("SELECT u from User as u");
return query.getResultList();
}
}
Essa é a maneira correta de fazer as coisas? Minha terminologia está correta? O "serviço" parece mais um DAO? E o controlador parece que está fazendo parte do serviço.
Essa é a maneira correta de fazer as coisas?
Além de executar a lógica de negócios da maneira ineficiente em um método gerenciador de beans gerenciados e usar um escopo de beans gerenciados muito amplo, parece bom.
Se você mover a chamada de serviço do método getter para o método
@PostConstruct
e usar
@RequestScoped
ou
@ViewScoped
vez de
@SessionScoped
, a aparência será melhor.
Veja também:
Minha terminologia está correta?
Está bem.
Desde que você seja consistente com ele e o código seja legível de maneira sensata.
Somente sua maneira de nomear classes e variáveis é um pouco estranha (ilógica e / ou duplicada).
Por exemplo, eu pessoalmente usaria
users
vez de
userList
e usaria
var="user"
vez de
var="u"
e usaria
id
e
name
vez de
userId
e
userName
.
Além disso, um "UserListService" parece que só pode lidar com listas de usuários em vez de usuários em geral.
Prefiro usar o "UserService" para que você também possa usá-lo para criar, atualizar e excluir usuários.
Veja também:
O "serviço" parece mais um DAO?
Não é exatamente um DAO. Basicamente, o JPA é o verdadeiro DAO aqui. Anteriormente, quando o JPA não existia, todo mundo fazia a homologação de interfaces do DAO, para que os métodos de serviço possam continuar usando-os mesmo quando a implementação subjacente (JDBC "simples" ou "Hibernate" etc.) é alterada. A tarefa real de um método de serviço é gerenciar transações de forma transparente. Isso não é de responsabilidade do DAO.
Veja também:
- Encontrei JPA, ou similar, não incentive o padrão DAO
- Relação DAO e JDBC?
- Quando é necessário ou conveniente usar o Spring ou o EJB3 ou todos eles juntos?
E o controlador parece que está fazendo parte do serviço.
Eu posso imaginar que ele faz isso nesta configuração relativamente simples. No entanto, o controlador é de fato parte do front-end e não do back-end. O serviço faz parte do back-end, que deve ser projetado de forma que seja reutilizável em todos os diferentes front-ends, como JSF, JAX-RS, JSP + Servlet "simples", até Swing, etc. Além disso, o controlador específico do front-end ( também chamado de "backing bean" ou "apresentador") permite lidar de maneira específica com o front-end com êxito e / ou resultados excepcionais, como no caso do JSF, exibindo uma mensagem de rosto no caso de uma exceção lançada de um serviço.
Veja também:
Em suma, a abordagem correta seria como abaixo:
<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();
}
}
Você pode encontrar aqui um projeto de kickoff do mundo real aqui, utilizando as práticas canônicas de Java EE / JSF / CDI / EJB / JPA: aplicativo de kickoff de Java EE .
Veja também:
- Criando páginas de detalhes mestres para entidades, como vinculá-las e qual escopo de bean escolher
- Passando um Bean Pojo Gerenciado JSF2 no EJB ou Colocando o que é Requerido em um Objeto de Transferência
- O filtro não inicializa o EntityManager
- javax.persistence.TransactionRequiredException no aplicativo de facelet pequeno
É um
DAO
,
na verdade um repositório,
mas não se preocupe muito com essa diferença, pois está acessando o banco de dados usando o contexto de persistência.
Você deve criar uma classe de
Service
que agrupe esse método e é onde as
transações
são invocadas.
Às vezes, as classes de
service
parecem desnecessárias, mas quando você tem um método de
service
que chama muitos métodos
DAO
, seu uso é mais garantido.
Normalmente, acabo criando o
service
, mesmo que pareça desnecessário, para garantir que os padrões permaneçam os mesmos e o
DAO
nunca seja injetado diretamente.
Isso adiciona uma camada extra de abstração, tornando a refatoração futura mais flexível.