Escolar Documentos
Profissional Documentos
Cultura Documentos
3 e PrimeFaces
Fonte: Tabela CRUD simples com JSF 2.3 e PrimeFaces - rieckpil (rieckpil-de.translate.goog)
<groupId>de.rieckpil.blog</groupId>
<artifactId>simple-crud-table-with-jsf-and-primefaces</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<repositories>
<repository>
<id>prime-repo</id>
<name>Prime Repo</name>
<url>http://repository.primefaces.org</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>8.0</version>
</dependency>
<dependency>
<groupId>org.primefaces.themes</groupId>
<artifactId>all-themes</artifactId>
<version>1.0.10</version>
</dependency>
</dependencies>
<build>
<finalName>crud-table-jsf-primefaces</finalName>
</build>
</project>
Para elementos JSF mais convenientes, estou usando a biblioteca PrimeFaces e sua biblioteca ' all-theme' para alterar o tema padrão posteriormente. Além
disso, você precisa declarar explicitamente o repositório PrimeFaces para poder obter esses temas. Para poder armazenar as entidades JPA na memória H2,
configurei o persistence.xml no src/main/resources/META-INF da seguinte forma:
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>bootstrap</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>customers.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Aqui estou especificando o tema de bootstrap PrimeFaces e o mapeamento de servlet para as visualizações. Neste exemplo, escreverei apenas uma visualização
( customers.xhtml) que deve ser carregada como arquivo central de boas-vindas.
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
@NotEmpty
private String firstName;
@Column(nullable = false)
@NotEmpty
private String lastName;
@Column(nullable = false)
@NotEmpty
@Email
private String email;
@Past
private LocalDate dayOfBirth;
Neste exemplo, estou misturando anotações JPA e anotações de validação de bean , o que é bom para esta pequena vitrine, mas para projetos maiores, eu
sugeriria usar algum tipo de objeto de transferência que obtivesse as anotações de validação de bean e fosse mapeado para a entidade JPA dentro um
serviço. As anotações de validação do bean ( @NotEmpty, @Email, @Past) são muito importantes porque nos ajudarão posteriormente na validação da
entrada do usuário.
Essas anotações declarativas não precisam de implementação de nossa parte, pois o servidor de aplicativos fornece uma implementação de referência em tempo
de execução. Outro recurso interessante que vem com a validação de bean e o componente de entrada PrimeFaces é que todos os campos de
entrada obrigatórios@NotEmpty (por exemplo , ou @NotNull) são marcados com um asterisco preto '*' fora da caixa.
Para a interação com o EntityManager , criei um EJB simples sem estado que é responsável pelas operações CRUD (criar, ler, atualizar e excluir). O código
deve ser bastante simples e não quero entrar em detalhes aqui:
@Stateless
public class CustomerManager {
@PersistenceContext
private EntityManager entityManager;
if (managedCustomer != null) {
entityManager.remove(managedCustomer);
}
}
}
this.entityManager.persist(newCustomer);
}
customers.forEach(entityManager::merge);
}
}
O bean de apoio correspondente para a visualização JSF também é bastante simples e mais ou menos apenas delega as operações ao EJB injetado.
@Named
@ViewScoped
public class CustomersBacking implements Serializable {
@Inject
private CustomerManager customerManager;
@PostConstruct
public void init() {
this.customers = customerManager.loadAllCustomers();
}
public void delete(Customer customer) {
customerManager.delete(customer);
customers.remove(customer);
}
customerManager.update(customers);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Update successful"));
}
Todos os clientes disponíveis são armazenados em uma lista dentro de @PostConstruct. O campo adicional cliente é necessário para armazenar as
entradas atuais do usuário final no objeto Cliente. Quando um novo cliente é armazenado no banco de dados no método add() , a referência será substituída
para obter campos de entrada vazios na visualização.
O método update() é responsável por atualizar todos os clientes disponíveis, pois não forneço um mecanismo de atualização para cada objeto de cliente. Isso é
tudo no back-end para nosso caso de uso simples. Vamos continuar com a visão. Vou dividir a explicação da view em duas partes, uma para a tabela de dados e
outra para o formulário de criação de um novo cliente.
<h:form id="customers">
<p:growl id="growl" sticky="true" />
<p:column headerText="Id">
<h:outputText value="#{customer.id}"/>
</p:column>
<p:column>
<p:commandButton update="customerList" value="Delete" icon="ui-icon-closethick"
action="#{customersBacking.delete(customer)}"
styleClass="ui-priority-primary">
</p:commandButton>
</p:column>
</p:dataTable>
<br/>
<p:commandButton style="float: right" id="save" value="Save" tyleClass="ui-priority-primary"
action="#{customersBacking.update}" icon="ui-icon-disk" update="growl">
<f:ajax execute="@form" render="@form"/>
</p:commandButton>
</h:form>
O namespace <p:…> está referenciando os componentes PrimeFaces, que são declarados na parte superior do arquivo .xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
No topo do <p:dataTable> estou declarando um elemento growl que é o componente PrimeFaces para exibir mensagens que são publicadas
no FacesContext atual . A tabela de dados está usando a lista de clientes do backing bean como sua fonte de dados e exibirá uma linha para cada cliente na
lista.
Além de apenas exibir os dados, adicionei elementos <p:inputText> para atributos que devem ser atualizáveis como nome, sobrenome e e-mail do cliente. Os
outros campos são somente leitura. Para a conversão do dia de nascimento do cliente, estou utilizando o elemento auxiliar <f:convertDateTime> .
Cada linha da tabela também recebe uma coluna extra com um botão de comando de exclusão para excluir a linha selecionada. O cliente que deve ser excluído
é passado para o método delete(Customer customer) do backing bean . Por padrão, os botões de comando PrimeFaces executam uma solicitação AJAX e
você pode especificar o elemento que deve ser atualizado após a chamada AJAX no updateatributo do elemento <p:commandButton> .
O último botão de comando é responsável por salvar as alterações feitas em diversos clientes e irá atualizar o elemento rosnado para a nova Mensagem do
Faces. A parte HTML da criação de um novo cliente também é bastante simples:
<h:form id="add">
<h:panelGrid columns="3" cellpadding="5" style="margin: 0 auto;">
<p:outputLabel for="firstName" value="First name" />
<p:inputText id="firstName" value="#{customersBacking.customer.firstName}" />
</h:panelGrid>
</h:form>
Para cada atributo modificável, estou fornecendo um componente outputLabel , inputText e message . Para o dia de nascimento, adicionei um componente
simples de calendário PrimeFaces que também fornecerá uma máscara para o formato de data necessário. Quando o usuário insere dados e tenta criar um
novo usuário, os dados de entrada serão validados de acordo com as anotações de Validação do Bean na entidade Cliente. Um nome ausente, um e-mail
formatado incorretamente ou um dia de nascimento futuro serão detectados e uma mensagem de erro será exibida:
Considerando o caso de uso e o público-alvo, acho que essa abordagem é uma forma realmente produtiva de criar aplicações web. Com os
componentes PrimeFaces , você obtém um conjunto de elementos prontos para uso e com o tema correto, eles também ficarão muito bonitos.
Escrever este aplicativo com um SPA e um backend de sua escolha levaria muito mais tempo e você produziria mais código. Experimente este exemplo você
mesmo ou dê uma olhada em meu repositório GitHub para obter a base de código completa e um tutorial passo a passo para executá-lo em sua máquina
no README.md do projeto.
Há muito mais para descobrir com JSF 2.3 e Java EE em geral (por exemplo, WebSockets , Internacionalização , Segurança …), então fique atento aos
próximos posts do blog. Para começar com JSF 2.3 , posso recomendar o Guia Definitivo para JSF em Java EE 8 de Bauke Scholtz ( @OmniFaces ) e Arjan
Tijms ( @arjan_tijms ).