SeamFramework.orgCommunity Documentation
Vamos ilustrar essas ideias com um exemplo completo. Nós implementaremos um login/logout de usuário de uma aplicação que utiliza JSF. Primeiro, definiremos um bean com escopo de solicitação para manter o nome do usuário (username) e a senha (password) fornecidos durante o login, com as restrições definidas utilizando anotações da especificação Beans Validation:
@Named @RequestScoped
public class Credentials {
private String username;
private String password;
@NotNull @Length(min=3, max=25)
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
@NotNull @Length(min=6, max=20)
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
Esse bean é vinculado ao prompt de login no seguinte formulário JSF:
<h:form>
<h:panelGrid columns="2" rendered="#{!login.loggedIn}">
<f:validateBean>
<h:outputLabel for="username"
>Username:</h:outputLabel>
<h:inputText id="username" value="#{credentials.username}"/>
<h:outputLabel for="password"
>Password:</h:outputLabel>
<h:inputSecret id="password" value="#{credentials.password}"/>
</f:validateBean>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
<h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form
>
Os usuários são representados por uma entidade JPA:
@Entity
public class User {
private @NotNull @Length(min=3, max=25) @Id String username;
private @NotNull @Length(min=6, max=20) String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String setPassword(String password) { this.password = password; }
}
(Observe que também vamos precisar de um arquivo persistence.xml
para configurar a unidade de persistência JPA contendo a entidade User
.)
O verdadeiro trabalho é realizado por um bean com escopo de sessão que mantém informações sobre o atual usuário conectado e expõe a entidade User
para outros beans:
@SessionScoped @Named
public class Login implements Serializable {
@Inject Credentials credentials;
@Inject @UserDatabase EntityManager userDatabase;
private User user;
public void login() {
List<User
> results = userDatabase.createQuery(
"select u from User u where u.username = :username and u.password = :password")
.setParameter("username", credentials.getUsername())
.setParameter("password", credentials.getPassword())
.getResultList();
if (!results.isEmpty()) {
user = results.get(0);
}
else {
// perhaps add code here to report a failed login
}
}
public void logout() {
user = null;
}
public boolean isLoggedIn() {
return user != null;
}
@Produces @LoggedIn User getCurrentUser() {
return user;
}
}
@LoggedIn
e @UserDatabase
são anotações de qualificadores personalizados:
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, PARAMETER, FIELD})
public @interface LoggedIn {}
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, PARAMETER, FIELD})
public @interface UserDatabase {}
Precisamos de um bean adaptador para expor nossa EntityManager
typesafe:
class UserDatabaseProducer {
@Produces @UserDatabase @PersistenceContext
static EntityManager userDatabase;
}
Agora, DocumentEditor
ou qualquer outro bean, pode facilmente injetar o usuário atual:
public class DocumentEditor {
@Inject Document document;
@Inject @LoggedIn User currentUser;
@Inject @DocumentDatabase EntityManager docDatabase;
public void save() {
document.setCreatedBy(currentUser);
docDatabase.persist(document);
}
}
Ou podemos referenciar o usuário atual em uma visão JSF:
<h:panelGroup rendered="#{login.loggedIn}">
signed in as #{currentUser.username}
</h:panelGroup
>
Esperamos que este exemplo tenha dado um gostinho do modelo de programação em CDI. No capítulo seguinte, exploraremos a injeção de dependência com maior profundidade.