PrimeFaces e MySQL: Criando uma galeria de imagens

Este artigo mostrará como criar uma galeria de imagens com o componente Gallery do PrimeFaces, armazenando as imagens em um banco de dados MySQL.

O JavaServer Faces (JSF) é um dos frameworks mais utilizados para a criação de aplicações web em Java, além do JSF, é possível utilizar o PrimeFaces para a criação de interfaces ricas. Ele é uma especificação para o desenvolvimento de aplicações Web, seguindo o padrão Model View Controler (MVC) em Java, e surgiu como uma alternativa ao Struts, que na época era o principal framework para implementar aplicações nesse padrão de projeto. Sua primeira versão foi disponibilizada em 2004 e em 2013 foi lançada a versão 2.2.

Atualmente, existem diversos frameworks para construção de interfaces ricas com o JSF, entre eles, um dos principais é o Primefaces que disponibiliza diversos componentes. Atualmente esse framework está na versão 5.1 e contém um grande número de componentes, entre eles, o gallery que é um componente para a exibição de uma galeria de imagens.

Este artigo mostrará como implementar uma aplicação com os framework JSF utilizando alguns dos principais componentes do PrimeFaces. A aplicação terá uma tela de cadastro, onde será feito o upload de uma imagem, e uma tela com o componente gallery, onde será exibida uma galeria com diversas imagens cadastradas. As imagens serão armazenadas em um banco de dados MySQL.

Configurando o projeto com o Maven

Para facilitar a configuração do projeto será utilizado o Maven. Para a criação desse projeto serão necessárias as dependências do conector com o MySQL, as bibliotecas do PrimeFaces e também do JSF. Para a biblioteca do PrimeFaces também é necessário adicionar as informações do repositório desse framework. São necessárias ainda, as dependências commons-io e commons-fileupload, utilizadas pelo componente de upload de arquivos do PrimeFaces. A Listagem 1 mostra o arquivo pom.xml do projeto criado.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.devmedia</groupId> <artifactId>primefaces</artifactId> <version>0.0.1</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>5.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.faces</artifactId> <version>2.1.13</version> <scope>compile</scope> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> </dependencies> <repositories> <repository> <id>prime-repo</id> <name>PrimeFaces Maven Repository</name> <url>http://repository.primefaces.org</url> <layout>default</layout> </repository> </repositories> </project>
Listagem 1. Configurando o projeto com o PrimeFaces 5

Depois de configurar as dependências do projeto, é necessário configurar a aplicação para usar o framework JSF e, como o projeto é de uma aplicação Web, necessitamos criar o arquivo web.xml. O passo mais importante é configurar o Faces Servlet, que utiliza a classe javax.faces.webapp.FacesServlet, e configurar o mapeamento das URL’s que serão tratadas pelo JSF, no caso, todos os endereços que terminarem com *.xhtml. Também foi configurado que caso aconteça algum erro na aplicação, a requisição seja redirecionada para a página inicial da aplicação. A Listagem 2 mostra o código do arquivo web.xml.

<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>com.devmedia.primefaces</display-name> <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> <filter> <filter-name>PrimeFaces FileUpload Filter</filter-name> <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class> </filter> <filter-mapping> <filter-name>PrimeFaces FileUpload Filter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> <welcome-file-list> <welcome-file>/index.xhtml</welcome-file> </welcome-file-list> <error-page> <exception-type>javax.faces.application.ViewExpiredException</exception-type> <location>/index.xhtml</location> </error-page> </web-app>
Listagem 2. Configuração do Web.xml do projeto

Para executar a aplicação é necessário um servidor de aplicação, que pode ser o JBoss, o Jetty ou qualquer outro que execute aplicações web Java. Para o desenvolvimento desse artigo foi utilizado o Tomcat 8.

Criando a aplicação

Depois de todas as configurações realizadas é iniciado o desenvolvimento da aplicação. O primeiro passo é a criação da classe que representara os objetos que serão cadastrados no banco de dados. A Listagem 3 exibe o código da classe Local, que é a entidade dos objetos que serão salvos no MySQL. Essa entidade tem os atributos:

package com.devmedia.model; import java.util.Date; public class Local { private int id; private String nome; private String cidade; private String pais; private byte[] imagem; private Date dataCadastro; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getCidade() { return cidade; } public void setCidade(String cidade) { this.cidade = cidade; } public String getPais() { return pais; } public void setPais(String pais) { this.pais = pais; } public byte[] getImagem() { return imagem; } public void setImagem(byte[] imagem) { this.imagem = imagem; } public Date getDataCadastro() { return dataCadastro; } public void setDataCadastro(Date dataCadastro) { this.dataCadastro = dataCadastro; } }
Listagem 3. Classe Local

Como a aplicação salvará os dados no banco de dados MySQL, é necessário criar essa tabela no banco de dados, por isso, a Listagem 4 mostra o código SQL para a criação da tabela local. As colunas criadas são as mesmas dos atributos da classe Local. No desenvolvimento dessa aplicação foi utilizado o banco de dados MySQL, mas qualquer outro banco pode ser utilizado, bastando alterar o pom.xml para adicionar a dependência do conector de outro banco, e alterar a String de conexão com o banco de dados.

CREATE DATABASE local; use local; CREATE TABLE local ( id INT PRIMARY KEY, nome VARCHAR(30), cidade VARCHAR(30), pais VARCHAR(30), imagem BLOB, data_cadastro TIMESTAMP );
Listagem 4. Código SQL para a criação da tabela Local

A aplicação criada terá métodos para inserir e para recuperar locais no banco de dados. A Listagem 5 mostra o código da classe que faz todos os acessos ao banco de dados, o construtor da classe que faz a conexão com o banco de dados passando o nome, o usuário e a senha do banco de dados utilizado. O método closeConnection, simplesmente fecha a conexão com o banco de dados.

O método insertLocal insere no banco de dados um local passado como parâmetro. Para isso, foi criado um PreparedStatement, que recebe o SQL que será executado e o número de parâmetros que devem ser passados para a query. Logo depois, esses parâmetros são passados para a query. Depois o insert é executado e, se o local for cadastrado com sucesso, o método retorna true; caso contrário, é criado um log com a mensagem de erro e o método retorna false.

O método listaLocais recupera todos os locais cadastrados no banco e coloca no retorno do método, inclusive a imagem do local cadastrado. O primeiro passo para isso é criar um objeto do tipo Statement e passar como parâmetro para esse objeto o comando SQL da busca. A consulta do exemplo é bastante simples e retorna todos os locais cadastrados na tabela local.

package com.devmedia.model; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import com.devmedia.model.Local; public class Connect { Connection con = null; public Connect() throws SQLException { try { Class.forName("com.mysql.jdbc.Driver"); System.out.println("Instalou driver"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } String url = "jdbc:mysql://localhost:3306/local"; String user = "root"; String password = "eduardo73"; con = DriverManager.getConnection(url, user, password); } public void closeConnection() throws SQLException { con.close(); } public boolean insertLocal(Local local) { try { PreparedStatement preparedStatement = con .prepareStatement("insert into local(id, nome, cidade, pais, imagem, data_cadastro) values(?,?,?,?,?,?)"); preparedStatement.setInt(1, local.getId()); preparedStatement.setString(2, local.getNome()); preparedStatement.setString(3, local.getCidade()); preparedStatement.setString(4, local.getPais()); preparedStatement.setBytes(5, local.getImagem()); preparedStatement.setDate(6, new java.sql.Date(new Date().getTime())); preparedStatement.execute(); return true; } catch (SQLException ex) { Logger lgr = Logger.getLogger(Connect.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); return false; } } public List<Local> listaLocais() { ArrayList<Local> lista = new ArrayList<Local>(); Statement st = null; ResultSet rs = null; try { st = con.createStatement(); String sql = "select * from local "; rs = st.executeQuery(sql); while (rs.next()) { Local local = new Local(); local.setId(rs.getInt(1)); local.setNome(rs.getString(2)); local.setCidade(rs.getString(3)); local.setPais(rs.getString(4)); local.setImagem(rs.getBytes(5)); local.setDataCadastro(rs.getDate(6)); lista.add(local); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(Connect.class.getName()); lgr.log(Level.SEVERE, ex.getMessage(), ex); } finally { try { if (rs != null) { rs.close(); } if (st != null) { st.close(); } if (con != null) { con.close(); } } catch (SQLException ex) { Logger lgr = Logger.getLogger(Connect.class.getName()); lgr.log(Level.WARNING, ex.getMessage(), ex); } } return lista; } }
Listagem 5. Classe de conexão com o banco de dados

A Listagem 6 mostra o código do ManagedBean criado para controlar o cadastro e a listagem das imagens dos Locais para serem exibidos na galeria de imagens.

ManagedBean são as classes que conectam o código Java, com o código da visão e para criar uma classe desse tipo é necessário utilizar a anotação @ManagedBean e dizer qual o nome desse ManagedBean. O nome é importante, pois nas telas, para acessar a classe, será utilizado o nome usado nessa anotação.

O primeiro método desse ManagedBean é o método cadastraLocal, que recebe um local que foi criado na tela de cadastro. Depois é criada uma conexão com o banco de dados e finalmente é chamado o método insereLocal da classe Connect, que faz a inserção do local no banco de dados. Se o cadastro for efetuado com sucesso, é retornada uma mensagem de sucesso para o usuário, caso contrário, uma mensagem informando o usuário do erro é enviada.

O método listarLocais recuperar todos os locais que estão cadastrados no banco de dados e retorna para a tela que chamou esse método. No JSF, todos os métodos que retornam objetos para a tela devem ter o nome iniciado com get. Ainda no ManagedBean são criados os métodos get e set para o atributo Local da classe. Esse método será utilizado para retornar as imagens.

package com.devmedia.managedbeans; import java.io.FileOutputStream; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.context.FacesContext; import org.primefaces.event.FileUploadEvent; import com.devmedia.model.Connect; import com.devmedia.model.Local; @ManagedBean(name = "LocalMB") @ViewScoped public class LocalManagedBean { private Local local = new Local(); private List<String> imagens; public void handleFileUpload(FileUploadEvent event) { local.setImagem(event.getFile().getContents()); FacesMessage message = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded."); FacesContext.getCurrentInstance().addMessage(null, message); } public String cadastraLocal() throws SQLException { Connect con = new Connect(); if (con.insertLocal(local)) { FacesContext.getCurrentInstance().addMessage( null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Sucesso!", "Local cadastrado com sucesso!")); } else { FacesContext.getCurrentInstance().addMessage( null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro!", "Erro no cadastro de local!")); } con.closeConnection(); return ""; } public List<String> getImages() throws SQLException, IOException { Connect con = new Connect(); List<Local> listaLocais = con.listaLocais(); List<String> images = new ArrayList<String>(); String path = FacesContext.getCurrentInstance() .getExternalContext().getRealPath("/temp"); for (Local local : listaLocais) { FileOutputStream fos = new FileOutputStream(path + "/" + local.getNome() + ".jpg"); fos.write(local.getImagem()); fos.close(); images.add(local.getNome() + ".jpg"); } return images; } public Local getLocal() { return local; } public void setLocal(Local local) { this.local = local; } }
Listagem 6. Managed Bean para cadastrar e listar Locais

Criando a tela de cadastro de local

Depois de criados o ManagedBean, é possível criar a tela de cadastro de local que terá:

A Listagem 7 exibe o código para a criação dessa tela.

Ainda na tela de cadastro existe um botão que é representado pelo componente commandButton.O texto do atributo value indica o texto que aparecerá no botão, o atributo opcional icon indica um ícone para aparecer no botão. O atributo action indica qual o método do ManagedBean que será executado e o atributo update indica que o componente de exibição de mensagens deve ser atualizado depois de cada cadastro.

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> <h:head> </h:head> <h:body> <h:form> <p:messages id="messages" /> <p:panelGrid columns="2"> <p:outputLabel for="id" value="ID:" /> <p:spinner id="id" value="#{LocalMB.local.id}" /> <p:outputLabel for="nome" value="Nome:" /> <p:inputText id="nome" value="#{LocalMB.local.nome}" /> <p:outputLabel for="cidade" value="Cidade:" /> <p:inputText id="cidade" value="#{LocalMB.local.cidade}" /> <p:outputLabel for="pais" value="Pais:" /> <p:inputText id="pais" value="#{LocalMB.local.pais}" /> <p:fileUpload fileUploadListener="#{LocalMB.handleFileUpload}" mode="advanced" dragDropSupport="false" update="messages" sizeLimit="1000000" fileLimit="3" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" /> <p:commandButton value="Cadastrar" icon="ui-icon-star" action="#{LocalMB.cadastraLocal}" update="messages"> </p:commandButton> </p:panelGrid> </h:form> </h:body> </html>
Listagem 7. Tela de cadastro de Local

A Figura 1 mostra a tela criada no código da Listagem 7, que tem um campo para o cadastro de cada atributo da classe Local, além do campo para o upload da imagem. Acima do formulário é mostrada a mensagem de sucesso, indicando que o cadastro do local foi realizado com sucesso.

Figura 1. Tela de cadastro de usuários

O último passo é a criação da tela que mostra a galeria de imagens. Para isso, é utilizado o componente gallery do Primefaces, que é um componente bastante poderoso e que disponibiliza um grande número de funcionalidades com uma implementação bastante simples. O atributo value indica o método do ManagedBean de onde virão as imagens, no caso, o método getImagems do ManagedBean LocalMB. O atributo var indica o nome da variável para ser utilizada na recuperação dos dados dos objetos. O atributo showCaption indica que deve ser mostrado na galeria uma descrição da imagem.

A Listagem 8 mostra o código para a criação da tela da galeria de imagens.

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> <h:head> </h:head> <h:body> <h:form> <p:galleria value="#{LocalMB.images}" var="image" panelWidth="500" panelHeight="313" showCaption="true"> <p:graphicImage value="temp/#" alt="Image Description for #" title="#" /> </p:galleria> </h:form> </h:body> </html>
Listagem 8. Tela de listagem de Usuários

A Figura 2 mostra a tela da galeria de imagens criada na Listagem 8. Como no banco de dados haviam três locais cadastrados, a galeria exibe as três imagens pequenas e o usuário pode selecionar a imagem que quer visualizar.

Figura 2. Tela da galeria de imagens

Este artigo mostrou como criar uma aplicação simples com o JavaServer Faces, o PrimeFaces e o MySQL para o cadastro de imagens, e a exibição de uma galeria de imagens com o componente gallery do Primefaces. O projeto utilizou a versão mais recente do PrimeFaces, que é hoje um dos principais frameworks para a criação de interfaces ricas do JSF.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados