sexta-feira, 25 de janeiro de 2013

Montando um ambiente JSF 2.0

Há quem goste, :-)

Aqui iremos acompanhar a montagem de um ambiente de desenvolvimento e teste para programação web com JSF 2.0, usando ainda o kit de componentes do richfaces.

O ambiente utilizado segue:

  • openSUSE 12.1
  • Eclipse Indigo (SR1) JEE
  • Apache Tomcat 7.0.x
  • Apache MyFaces Core 2.0
  • RichFaces 4.1.0.Final
  • Java 1.6 OpenJDK
  • PostgreSQL 9.1.
  • Driver JDBC do PostgreSQL 9.1.

Proceda com os downloads (descompactando em local conhecido):

eclipse: http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/indigosr1

tomcat7: http://tomcat.apache.org/download-70.cgi

myfaces: http://myfaces.apache.org/download.html

richfaces: http://www.jboss.org/richfaces/download/stable

Descompacte tudo:

Hora de preparar o postgre. abra um terminal, vire root e execute o seguinte comando:

linux-13tn:/home/sombriks # zypper in postgresql postgresql-contrib postgresql-server

No mesmo terminal de root inicie o banco:

linux-13tn:/home/sombriks # service postgresql start

Nota: não foi preciso tampouco encontrado o comando para inicializar o banco; classicamente havia a necessidade de rodar o init-db, mas nesta release do openSUSE não é mais.

Em seguida vamos ajustar o banco para autenticar através de login/senha. entre com o seguinte comando para editar o pg_hba.conf:

linux-13tn:/home/sombriks # vi /var/lib/pgsql/data/pg_hba.conf

Aos marinheiros de primeira viagem em vi:

  • pressione insert e então você poderá editar o arquivo
  • pressione esc e volte para o modo comando
  • :wq salva as modificações
  • :q! sai sem salvar

Estamos procurando estas linhas:

O objetivo é mudar o método de autenticação local para trust e os métodos de autenticação de rede para md5:

Nota: trust para conexões locais é bom pra exemplos mas é ruim para produção porque não obriga senha nesta modalidade de conexão. Mas ao obrigar senha precisaremos configurar corretamente o usuário postgres, e isso é assunto para outro post.

Não esqueça de sair apertando esq e depois digitando :wq para salvar. Reinicie o banco de dados agora; alteramos a forma de autenticação mas as configurações não surtiram efeito ainda: linux-13tn:/home/sombriks # service postgresql restart

Hora de criar o banco: no PostgreSQL você deve efetuar as tarefas administrativas com o usuário postgres: linux-13tn:/home/sombriks # su - postgres

Em seguida use as ferramentas do banco para criar o esquema e o usuário. Segue saída do terminal: postgres@linux-13tn:~> createdb financeiro_db postgres@linux-13tn:~> createuser financeiro_user A nova role poderá criar um super-usuário? (s/n) n A nova role poderá criar bancos de dados? (s/n) n A nova role poderá criar novas roles? (s/n) n postgres@linux-13tn:~>

Com isto temos uma base de dados e um usuário, mas não terminamos por aqui. Temos de ajustar a senha do novo usuário e as permissões dele na nova base de dados. Ainda com este terminal do usuário postgres, invoque o cliente do banco, o psql: postgres@linux-13tn:~> psql psql (9.1.1) Digite "help" para ajuda. postgres=# alter user financeiro_user with encrypted password 'financeiro_senha'; ALTER ROLE postgres=# grant all privileges on database financeiro_db to financeiro_user; GRANT postgres=#

Pronto, dê CTRL+D até o terminal fechar, esta etapa está concluída.

Como você deve suspeitar, a aplicação de exemplo será uma pequena aplicação de registro financeiro. O script da base segue, salve-o em uma pasta conhecida com o nome financeiro.sql:

drop table if exists tb_movimentos;
create table tb_movimentos(
	id serial not null,
	descricao varchar(300) not null,
	valor decimal(10,2) not null,
	primary key (id)
);

Abra um novo terminal e execute o script (em meu exemplo ele está salvo na pasta Downloads): sombriks@linux-13tn:~/Downloads> psql financeiro_db financeiro_user -f financeiro.sql -W Senha para usuário financeiro_user: psql:financeiro.sql:1: NOTA: tabela "tb_movimentos" não existe, ignorando DROP TABLE psql:financeiro.sql:7: NOTA: CREATE TABLE criará sequência implícita "tb_movimentos_id_seq" para coluna serial "tb_movimentos.id" psql:financeiro.sql:7: NOTA: CREATE TABLE / PRIMARY KEY criará índice implícito "tb_movimentos_pkey" na tabela "tb_movimentos" CREATE TABLE sombriks@linux-13tn:~/Downloads>

Temos o banco de dados praticamente finalizado desta maneira.

Instale o JDK: zypper in java-1_6_0-openjdk-devel

Nota: no openSUSE você pode pedir um pattern para desenvolvimento java, que irá lhe proporcionar uma quantidade maior de bibliotecas e ferramentas para trabalhar com java: zypper in patterns-openSUSE-devel_java

E um detalhe que não devemos deixar passar, consiga o driver JDBC do postgre: http://jdbc.postgresql.org/download.html

Deixe o jar com os outros downloads por enquanto, iremos cuidar dele no momento oportuno.

Entre agora na pasta descompactada do eclipse e execute-o com clique duplo no executável. crie um workspace padrão e feche a aba do 'welcome' quando terminar de iniciar a IDE. Selecione a aba Servers

Na área branca clique com botão direito>New>Server. No filtro da tela digite tomcat v7 para poder selecionar a única opção restante na caixa abaixo. Aperte o botão Next.

Na seguinte tela aperte o botão browse e indique a pasta descompactada do tomcat que baixamos:

Pressione Finish. O workspace do eclipse deve ficar assim:

O ajuste adicional aqui é o seguinte: vá ao gerenciador de arquivos, siga para a pasta onde estão os downloads. Copie o jar do driver jdbc do banco para dentro da pasta lib do tomcat:

Voltemos ao eclipse e criemos o DataSource; abra o projeto Servers (que foi criado junto com o servidor) dentro da pasta de configurações do servidor siga para o arquivo server.xml. Procure a sessão GlobalNamingResources:

Nota: caso seu eclipse esteja fechando sem razão aparente, siga os passos descritos no link abaixo e reinicie o openSUSE: https://bugzilla.novell.com/show_bug.cgi?id=731075

Adicione esta definição de Resource:


Salve o arquivo e partamos para a criação do projeto web:

Vamos chamar o projeto de financeiro. Deixe todas as opções de configuração no padrão:

Expanda a pasta do projeto e siga para WebContent>WEB-INF>lib. Iremos copiar as bibliotecas necessárias para rodar JSF 2.0 para cá. Vá para a pasta downloads e entre na pasta descompactada do MyFaces. Entre na pasta lib:

Copie estas libs e cole na lib do projeto, lá no eclipse. Siga procedimento similar para as bibliotecas do richfaces. primeiro artifacts/framework:

E copie também as bibliotecas de artifacts/ui; em ambos os casos os jars com os fontes são opcionais:

Embora quase lá, não estamos totalmente prontos: uma pequena série de dependências deve ser satisfeita agora. Elas estão apontadas em richfaces-4.1.0.Final/readme.txt e em http://myfaces.apache.org/core20/index.html#Requirements

jstl 2.1: http://download.java.net/maven/1/jstl/jars/

sac-1.3: http://repo1.maven.org/maven2/org/w3c/css/sac/1.3/

cssparser-0.9.5: http://repo1.maven.org/maven2/net/sourceforge/cssparser/cssparser/0.9.5/

google-guava-r08: http://repo1.maven.org/maven2/com/google/guava/guava/r08/

annotations.jar e validation-api.jar são opcionais.

Após todo este exercício, a pasta lib do projeto estará assim, com aproximadamente 10MB de bibliotecas:

No projeto, dentro de WebContent/META-INF, crie um arquivo chamado context.xml com o seguinte conteúdo:



	

Em WebContent, crie um index.jsp com este conteúdo aqui:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




    


Não teremos nossa aplicação JSF aqui, mas sim o "bootstrap" que irá nos levar ao contexto do JSF. Nota: os exemplos abaixo tem propósito didático, não ponha isso em produção sem falar com um adulto, ;-)

Crie um arquivo chamado inicio.xhtml (atenção para a extensão) e insira isto:



	
	
		#{registroBean.listRegistros}
		
			
				
				
				
				
				
				
				
			
		
		
			
				
					
						
					
					
				
				
					
						
					
					
				
				
					
						
					
					
				
			
		
	


Observe que no projeto a extensão do arquivo será xhtml, mas ele atenderá em inicio.jsf, inicio.faces ou ainda faces/inicio.xhtml

No exemplo acima utilizamos um ManagedBean chamado RegistroBean, segue abaixo:

package sample.financeiro;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javax.annotation.Resource;
import javax.faces.bean.ManagedBean;
import javax.sql.DataSource;

@ManagedBean(name = "registroBean")
public class RegistroBean {

	// suporte JDBC
	@Resource(name = "jdbc/financeiro")
	private DataSource ds;
	private ResourceBundle b = ResourceBundle//
			.getBundle(this.getClass().getName());

	// atributos do form
	private RegistroVo item = new RegistroVo();

	// lista
	private List registros;

	public RegistroVo getItem() {
		return item;
	}

	public void setItem(RegistroVo item) {
		this.item = item;
	}

	public List getRegistros() {
		return registros;
	}

	public void setRegistros(List registros) {
		this.registros = registros;
	}

	public void addRegistro() throws Exception {
		Connection co = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			String sql = b.getString("insert");
			co = ds.getConnection();
			ps = co.prepareStatement(sql);
			ps.setString(1, item.getDescricao());
			ps.setDouble(2, item.getValor());
			ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rs != null)
				rs.close();
			if (ps != null)
				ps.close();
			if (co != null)
				co.close();
		}
		registros = null;
		listRegistros();
	}

	public void listRegistros() throws Exception {
		if (this.registros != null)
			return;
		List registros = new ArrayList();
		Connection co = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			String sql = b.getString("select.all");
			co = ds.getConnection();
			ps = co.prepareStatement(sql);
			rs = ps.executeQuery();
			while (rs.next()) {
				RegistroVo r = //
				new RegistroVo(rs.getInt(1), rs.getString(2), rs.getDouble(3));
				registros.add(r);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rs != null)
				rs.close();
			if (ps != null)
				ps.close();
			if (co != null)
				co.close();
		}
		this.registros = registros;
	}
	// truque
	public String getListRegistros() throws Exception {
		listRegistros();
		return "";
	}
}

Note o suporte à anotação @Resource funcionando. uma vez que já temos o ResoruceLink o DataSource será injetado no bean pelo servidor, basta sair usando.

Vale ressaltar ainda que o método getListRegistros é um truque para carregarmos a lista que será usada na tabela. A outra parte do truque é na linha 9 do inicio.xhtml.

Devemos ainda ter o arquivo RegistroBean.properties no mesmo pacote do bean:

select.all = select id,descricao,valor from tb_movimentos order by id
insert = insert into tb_movimentos(descricao,valor) values (?,?)

E por fim a classe RegistroVo:

package sample.financeiro;

public class RegistroVo {

	private int id;
	private String descricao;
	private Double valor;

	public RegistroVo() {
	}

	public RegistroVo(int id, String descricao, Double valor) {
		this.id = id;
		this.descricao = descricao;
		this.valor = valor;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public Double getValor() {
		return valor;
	}

	public void setValor(Double valor) {
		this.valor = valor;
	}

}

Pronto, com isso temos um bom exemplo de como salvar coisas no banco usando JSF.

Sem mais, até o próximo post!

Nenhum comentário :

Postar um comentário