SeamFramework.orgCommunity Documentation

Capítulo 3. Exemplo de aplicação web JSF

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.