Criando Native Queries Dinâmicas mais legíveis com JPA

Este post foi movido para o novo blog neste link.

Como refatorar sua classe para que ela possa ser testada

Este tutorial foi movido para o link.

Criando uma Enterprise Application (EAR) com Eclipse

Introdução

Ola pessoal, o objetivo deste post é demonstrar como criar um projeto J2EE no Eclipse.

O J2EE é a especificação Java para aplicações corporativas. É uma especificação bem completa e avançada que aborda temas específicos para o desenvolvimento de aplicações em larga escala e com alta escalabilidade, segurança, dentre outros requisitos não funcionais.

Obviamente cabe ao desenvolvedor utilizar a plataforma de uma maneira eficiente para manter todos estes requisitos.

Uma das partes da especificação trata do EJB (Enterprise Java Bean) que são componentes (classes) que o servidor de aplicação gerencia para o desenvolvedor tornando muito mais simples e produtivo construir aplicações.

Neste exemplo, vamos criar uma aplicação que ira receber uma requisição Web através de uma Servlet. Esta Servlet encaminhará a requisição para o EJB que simplesmente modificará a String recebida. É um exemplo bem simples mas que vai demonstrar todo o fluxo de dados de uma aplicação bem como a simplicidade de criarmos estes componentes.

Vou utilizar neste exemplo, a versão 3.0 do Dynamic Web Module num servidor Jboss AS 7. A versão do eclipse utilizada é a Juno.

Servidor de aplicação X Container WEB

Inicialmente, vamos definir a diferença entre um container WEB e um servidor de aplicação. A especificação J2EE define diversas normas que um servidor de aplicação deve implementar, como por exemplo, gerenciar um EJB, tratar de requisições via web-service, etc. Desta forma, um servidor de aplicação homologado deve implementar totalmente a especificação e por isso, torna-se um software robusto e complexo. Como exemplo de servidores, podemos citar o Glassfish que é o servidor oficial e que possui uma implementação padrão do J2EE, o JBOSS, o WebLogic.

Já um container WEB implementa uma parcela da especificação e por isso é muito mais leve e simples. Como exemplo, podemos citar o Tomcat e o Jetty.

Outra diferença fundamental é que os containeres WEB executam apenas arquivos WAR (Web application ARchive) e os servidores de aplicação podem rodar também os EAR (Enterprise application ARchive) que são as aplicações mais completas e robustas.

Criando um projeto WEB

Nosso primeiro passo é criar um projeto WEB que normalmente contem as nossas servlets, filters, JSP, javascript, css, etc.
Para isso devemos seguir alguns passos.

Primeiro, no eclipse, selecione o menu File->New->Other. Ou digite o atalho Ctrl+N.
Agora digite Dynamic Web. Na listagem de templates abaixo, selecione o Dynamic Web Project e pressione Next.

Criando Dynamic Web Project

Criando Dynamic Web Project

Na próxima tela, vamos começar a configurar nossa aplicação. Digite um nome para a aplicação, no meu caso chamei de CriandoEARWeb. O sufixo Web é para separar logicamente o nome das aplicações criadas.

Configurando um Dynamic Web Project

Configurando um Dynamic Web Project

No meu caso, selecionei para que o projeto fosse salvo no meu workspace default, mas você pode configurar isso.
Como target selecionei o JBoss e no Dynamic Web Version selecionei a versão 3.0.
Observe que no item Configuration, o Eclipse possui templates para diferentes tipos de aplicações, como o JSF. Mas vamos manter a opção de Default Configuration for JBoss 7.1 Runtime. Clique em Next.

Dica: Caso você não tenha o JBoss na lista de servidores, aconselho a instalar o plugin JBoss Tools que é muito bom.

A próxima tela configura a pasta de fontes e onde devem ficar os arquivos compilados. Normalmente não se modifica esta configuração. Clique em Next.

Por fim, vamos configurar o context root, que é o nome que sua aplicação receberá dentro do servidor e como vamos acessá-la no browser. A configuração de WebContent define o nome da pasta onde estarão os nossos arquivos web (javascript, css, etc) e por fim, marque a checkbox para que o eclipse gere um arquivo web.xml default para você.

Configurando o Dynamic Web Project

Configurando o Dynamic Web Project

Você deve ter uma estrutura parecida com a da imagem abaixo. A diferença é que já foi criado um package br.com.coffeecode.servlet. Crie este package onde vamos adicionar nossas servlets.

Estrutura do Projeto Dynamic Web Project

Estrutura do Projeto Dynamic Web Project

Note que as configurações anteriores estão representadas nesta imagem, o nome da pasta onde ficam os insumos web é a WebContent e o arquivo web.xml foi gerado e esta localizado dentro da pasta WEB-INF.

Criando um Servlet

Agora vamos criar um servlet que irá encaminhar a requisição para um EJB e retornar para a tela o parâmetro alterado. Então crie uma nova classe Java dentro do pacote que criamos. A classe criada é esta e vamos explicá-la em seguida:

package br.com.coffeecode.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/echo")
public class EchoServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	     String text = req.getParameter("text");
	}

}

Esta classe é um servlet por herdar da classe HTTPServlet e possuir a annotation @WebServlet. Nesta annotation configuramos qual a url para acessar a nossa servlet. No nosso caso, é o nome da nossa aplicação mais a palavra echo. Dentro da servlet vamos esperar um parâmetro text.

Criando uma aplicação EJB

Criar uma aplicação EJB é igualmente simples. Dentro desta aplicação devemos incluir todas as nossas classes relacionadas ao domínio ou negócio. Logo, é nesta aplicação que fica a camada de model. É comum uma aplicação conter mais de um projeto EJB para aumentar a separação de domínios.

Utilize o atalho do eclipse Ctrl+N e digite na caixa de busca EJB. A primeira opção deve ser EJB Project. Selecione esta opção e clique em Next.

Criando aplicação EJB

Criando aplicação EJB

Na próxima tela configure um nome para a aplicação. Novamente você pode selecionar a localização do projeto e a versão do EJB a ser utilizada. Note que novamente coloquei a terminação EJB no nome do projeto, uma forma simples de identificar que se trata de um EJB Project.

Nomeando um EJB Project

Nomeando um EJB Project

Na próxima tela, novamente podemos selecionar a pasta de arquivos fontes, clique em Next.

Na última tela, podemos pedir para o eclipse gerar um arquivo de configuração. Deixe desmarcada a opção e clique em Finish.

Criando um projeto EJB

Criando um projeto EJB

Você deve ter uma estrutura de projeto parecida com a da imagem. Apenas acrescentei um pacote onde ficarão os EJB’s criados.

Estrutura do Projeto EJB

Estrutura do Projeto EJB

Criando um EJB

Neste nosso exemplo, vamos criar um EJB Stateless.
A diferença entre EJB’s Stateless e Statefull, é que os EJB Stateless não guardam estado. Isso significa que você deve imaginar que a cada nova requisição, você terá um EJB novo.
Na prática você não deve utilizar variáveis de instância como forma de poder recuperar dados a cada nova requisição. O próprio servidor pode criar um pool de EJB e nada garante que a instância que você irá receber a cada requisição é a mesma. Requisições Stateless devem receber os parâmetros necessários para o processamento e executá-lo sem necessitar de dados de navegação anteriores. Se necessitar, deve acessar estes dados de uma forma indireta, sem possuir estado no próprio EJB. Uma forma comum de fazer isso, é acessar um banco de dados.

Para criarmos um EJB precisamos criar uma interface Remote ou Local. A diferença entre as duas é que a interface Remote é utilizada para chamadas Remotas outras aplicações e a Local para chamadas internas (mesma aplicação). Como nós iremos encapsular numa mesma aplicação o projeto WEB e EJB, vamos utilizar a interface Local.

package br.com.coffeecode.ejb;

import javax.ejb.Local;

@Local
public interface TesteEjbLocal {

	public String addPipe(String text);

}

No código acima, criamos uma interface e marcamos ela com a annotation @Local. Além disso criamos um método addPipe que deverá ser implementado no EJB. Esta interface sera também a forma como a aplicação WEB acessará o nosso EJB, como veremos adiante.

Vamos agora implementar esta interface, criando o EJB que irá atender a requisição.

package br.com.coffeecode.ejb;

import javax.ejb.Stateless;

@Stateless
public class TesteEjb implements TesteEjbLocal {

	public String addPipe(String text) {
		return "|"+text+"|";
	}
}

No exemplo acima, criamos uma classe chamada TesteEjb e marcamos ela com a anotação Stateless. Como implementamos a interface que criamos anteriormente o método addPipe é implementado.

Criando um Enterprise Aplication R

Falta agora criarmos um projeto que irá encapsular estes dois como uma só aplicação J2EE. Para isso, vamos novamente utilizar o Ctrl+N do Eclipse e digitar Enterprise Application na caixa de busca.

Criando um projeto EAR

Criando um projeto EAR

Selecione o Enterprise Application Project e clique em Next.

Na próxima tela, iremos configurar o nome da aplicação e outras configurações. Repare que criei o nome da aplicação sem sufixo nenhum, pois este é o projeto que encapsula todos os outros. As configurações adicionais são semelhantes as anteriores, clique em Next.

Configurando Projeto EAR

Configurando Projeto EAR

Agora devemos selecionar quais os projetos devem fazer parte deste EAR, selecione os dois projetos criados anteriormente e clique em Finish.

EAR Configurando aplicações

EAR Configurando aplicações

O projeto criado será aquele que vamos incluir no servidor para executar. Falta agora fazermos a ligação entre o projeto WEB e o projeto EJB.

O arquivo application.xml é importante pois nele é informado todos os módulos da aplicação e qual a URL que a aplicação vai ser acessada, no nosso caso, EAR:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" 
 xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" 
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd"  id="Application_ID" version="6">
  <display-name>CriandoEAR</display-name>
  <module>
    <ejb>CriandoEAREJB.jar</ejb>
  </module>
  <module>
    <web>
      <web-uri>CriandoEARWeb.war</web-uri>
      <context-root>EAR</context-root>
    </web>
  </module>
</application>

Injetando o EJB

O próximo passo é adicionar a dependência do projeto EJB no projeto WEB. Para isso clique com o botão direito sobre o projeto WEB e selecione a opção Properties. Dentro da janela que irá se abrir, seleciona o item Java Build Path e clique na aba Projects. Clique em ADD e selecione o seu projeto EJB.

Projeto Web - Adicionar dependencia de outro projeto

Projeto Web – Adicionar dependencia de outro projeto

Vá até a servlet que criamos anteriormente e atualize a mesma para o arquivo abaixo:

package br.com.coffeecode.servlet;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import br.com.coffeecode.ejb.TesteEjbLocal;

@WebServlet("/echo")
public class EchoServlet extends HttpServlet {

	@EJB
	private TesteEjbLocal testeEjb;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String text = req.getParameter("text");
		String newText = testeEjb.addPipe(text);
		resp.getWriter().print(newText);
	}

}

Note que agora adicionamos uma variável de instância que é do tipo da interface Local que criamos no projeto EJB. A annotation @EJB é muito importante pois ela instrui o servidor a buscar um EJB desta interface e injetá-lo dinamicamente em nossa servlet. Note que NÃO EXISTE um new para esta variável. Mas fique tranquilo, estaremos livres do NullPointerException graças ao servidor de aplicação.

Agora nos resta testar a aplicação, para isso adicione ela ao ser servidor e inicie o mesmo:

Configurando servidor

Configurando servidor

Note que no log do servidor, é informado que um EJB foi encontrado:

java:global/CriandoEAR/CriandoEAREJB/TesteEjb!br.com.coffeecode.ejb.TesteEjbLocal
	java:app/CriandoEAREJB/TesteEjb!br.com.coffeecode.ejb.TesteEjbLocal
	java:module/TesteEjb!br.com.coffeecode.ejb.TesteEjbLocal
	java:global/CriandoEAR/CriandoEAREJB/TesteEjb
	java:app/CriandoEAREJB/TesteEjb
	java:module/TesteEjb

Pronto, basta executarmos agora via browser uma requisição para a nossa servlet:

Exemplo requisição

Exemplo requisição

Demonstramos neste post como criar uma Enterprise Application que muitas vezes pode complicar o desenvolvimento com J2EE mas que como vimos é bem simples e ainda nos força uma boa divisão em camadas.

Vídeo:

Java Message Service (JMS)

Olá a todos. Este é um tutorial dividido em 2 partes. A primeira explica os conceitos básicos do JMS e a segunda apresenta um exemplo prático utilizando EJB e o JBOSS AS 7.

A ideia é dar uma noção prática e básica sobre o JMS apresentando os conceitos com um exemplo de aplicação no mundo real.

Este tutorial foi inspirado apenas da documentação oficial da Oracle sobre Jms.

Introdução

Muitas vezes ao criarmos aplicações começamos a adicionar mais e mais complexidade e funções as chamadas e métodos que executamos. Isso é normal e até um bom sinal. As necessidades aumentam e os problemas evoluem. O cliente esta satisfeito com seu software e agora não quer mais apenas ver as vendas do dia na tela. Ele quer que o sistema gerencie desde o processo de pedido até a expedição do mesmo. Parabéns, você fez um bom trabalho e vai ganhar mais dinheiro :).

Este aumento de complexidade pode ser feito de forma natural, com um código bem estruturado e escrito e particularmente no Java, podemos subdividir em diversos Beans, mantendo um baixo acoplamento e aumentando o reaproveitamento de código sem nos preocuparmos muio com questões como escalonamento. Eu disse não nos preocuparmos muito, mas eu poderia dizer não nos preocuparmos diretamente.

Muitas destas atividades extras que vamos adicionando, podem demorar um tempo para serem executadas. Podem também ser atividades de uma importância menor ou que não necessitem de uma resposta imediata. Pensar num caso de uso como um todo é um erro. Temos que pensar em todas as interações entre os componentes do software. Para uma mesma operação, podemos ter muitas destas interações.

Quer um exemplo? Vamos salvar um endereço. Então eu sei que o seu estado é o PR. Mas eu preciso salvar o id, então eu tenho que ir ao componente de endereço e solicitar a ele, o id do estado cuja sigla é PR. Após isso, posso validar seu endereço, no meu objeto de validação de endereço. Agora sim, vou salvar o endereço que eu criei. Então vou ir até o componente de persistência deste endereço. Beleza, agora preciso retornar uma resposta a quem fez esta solicitação.

Fácil perceber. Uma simples ação de salvar um endereço, pode envolver diversas etapas.

Vamos imaginar um caso clássico. Fazemos um pedido de compra. O cliente vê uma chamada para criar um pedido, uma baixa no estoque e uma nota gerada.

Por baixo dos panos, na implementação, podemos dividir o software exatamente com estas 3 etapas:

  • Criar o pedido
  • Atualização no estoque
  • Geração de nota fiscal

Claro que a situação que vou criar é hipotética e pode mudar conforme o caso. Mas normalmente na geração do pedido, o que importa realmente é saber se este pedido foi criado. Com isso, liberamos o cliente para que ele vá para a próxima etapa, que pode ser fazer um novo pedido, ou pagar o que foi criado. Percebem? Realmente é relevante eu atualizar o estoque dentro da mesma requisição? O mesmo vale para a nota.

Podemos observar claramente neste exemplo que a etapa de atualização de estoque e geração de nota fiscal não é algo que realmente necessário de adicionar neste processamento. Num ambiente web de alta concorrência, quanto mais rápido você responder a uma requisição, mais rápido você esta disponível para atender outra e não utilizar muitos recursos do SO.

Uma forma de resolver isso, poderia ser criando uma nova funcionalidade de gerar nota. A funcionalidade de atualização do estoque pode ainda ser realizada através de uma rotina assíncrona que executa em determinados períodos de tempo.

Neste ponto, estou pela primeira vez inserindo a palavra assíncrona. Das tarefas citadas, 2 são assíncronas, não fazem realmente parte da resposta que o cliente necessita, são tarefas importantes, mas não importam num primeiro momento.

Sempre que um cenário destes se apresenta podemos utilizar um serviço de Mensagens. E como normalmente acontece, a API de Mensagens do JAVA é simples, poderosa e eficiente.

Mensagem

O que é uma mensagem? Vamos supor que eu queira convidar pessoas para um churrasco. O convite para o churrasco é a mensagem. Mensagem é em termos gerais, a informação a ser transmitida.

Trazendo para o mundo do software, mensagem é uma maneira de diferentes aplicações se comunicarem, onde o emissor e o receptor não necessitam se conhecer ou estarem disponíveis no mesmo momento. O que importa para ambos é o formato da mensagem que irá ser enviada e recebida neste sistema.

Podemos perceber que este é um ambiente que possuem um acoplamento muito baixo, pois os sistemas em si, não se conhecem.

JMS

O JMS é a API do Java que permite ao desenvolvedor criar, enviar, receber e ler mensagens. Nada mais é do que um conjunto de interfaces e classes que ficarão responsáveis por cada uma destas etapas.

A API nos permite enviar mensagens assincronamente e garante que não teremos problemas na entrega da mesma, como por exemplo mensagens duplicadas sendo enviadas.

Arquitetura

A arquitetura da api JMS pode ser resumida abaixo:

Arquitetura JMS

Veremos agora, qual a responsabilidade de cada um dos componentes desta arquitetura:

  • JMS provider : É um componente que controla e mantem as filas e mensagens. Normalmente é implementado por um Servidor de Aplicação Java EE, como o Glassfish ou JBoss.
  • JMS Clients: São aplicações escritas por desenvolvedores que criam, enviam, recebem e leem mensagens. Estes clientes devem se conectar ao JMS Provider através do JNDI.
  • Messages: São os objetos utilizados para a comunicação entre os diferentes clientes.
  • Administered objects: São classes da API que devem ser criadas pelos clientes. Como exemplo temos as ConnectionFactories e os Senders.

Tipos de Domínios

Existem duas formas de projetarmos uma aplicação com JMS.

  • Point-to-point:

Neste tipo de domínio, uma aplicação possui apenas um consumidor, ou seja, ela quer enviar mensagens para apenas um destino. Observe a figura abaixo:

JMS - Queue

Neste exemplo o Client 1 (JMS Client) cria e envia uma Msg para uma fila (Administered Object). Uma segunda aplicação o Client 2, conhece a fila e recebe as mensagens da mesma.

  • Publish/Subscribe:

Neste outro tipo de domínio, uma aplicação cria e envia uma mensagem, mais de uma aplicação devem receber a mesma.

JMS - Topic

Neste exemplo, o Cliente 1 (JMS Client) cria e envia uma Msg para um tópico (Administered Object). Outros Jms Clients conectam-se a este Topico e ambos recebem as mensagens. Observe que pelo modelo, ambos clientes conhecem o topico e as mensagens, mas não conhecem a si próprios. Se adicionarmos mais um cliente, as aplicações não são impactadas.

Este é um resumo de como é a estrutura da api de JMS do Java. No próximo post, irei descrever como fazer uma implementação de JMS.

Limpar um formulário utilizando find e each (jquery)

Este post foi movido para um novo blog neste link.

Como converter Json com Java

Olá pessoal.

Hoje vou escrever sobre como converter objetos Java em objetos Json e vice-versa. O objetivo é apresentar alguns códigos que demonstram este processo.

O Json já é uma realidade inclusive no mercado. É muito mais fácil trabalhar com Json com javascript e com o Java também.

A quantidade de dados trafegados também cai muito, uma vez que o Json não utiliza o conceito de tags.

Para saber mais sobre Json, visite este link.

Criar um Json a partir do Java?

Para fazer as conversões de Json para Java (Json2Java ou J2J) vou utilizar uma biblioteca do google chamada gson.

Para começar, vamos criar uma classe que sera convertida em um Json. Essa classe sera um pojo bastante simples:

public class Pessoa {

	private String nome;
	private int idade;

	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public int getIdade() {
		return idade;
	}
	public void setIdade(int idade) {
		this.idade = idade;
	}

}

Nada diferente nesta classe, ela apenas representa uma pessoa e possui 2 atributos. Vamos apresentar agora uma classe que vai criar um objeto Pessoa, e convertê-lo em um json. Veja como é simples:

import com.google.gson.Gson;

public class ConverterJson {

	public static void main(String[] args) {
		Pessoa p = new Pessoa();
		p.setIdade(15);
		p.setNome("Almiro Fagundes");
		Gson g = new Gson();
		String json = g.toJson(p);
		System.out.println(json);
	}

}

O método toJson da classe Gson faz a conversão do objeto Pessoa, sem a necessidade de mapeamentos ou etapas adicionais.
A saída gerada é:

{"nome":"Almiro Fagundes","idade":15}

Como alterar nome do atributo e trabalhar com Datas?

Simples não? Vamos complicar um pouco, adicionando um campo data e personalizando o nome do atributo gerado no json:

import java.util.Date;
import com.google.gson.annotations.SerializedName;

	public class Pessoa {

	@SerializedName(value = "nome_completo")
	private String nome;
	private int idade;
	@SerializedName(value = "data_nascimento")
	private Date dataNascimento;

	public String getNome() {
		return nome;
	}
	public Date getDataNascimento() {
		return dataNascimento;
	}
	public void setDataNascimento(Date dataNascimento) {
		this.dataNascimento = dataNascimento;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public int getIdade() {
		return idade;
	}
	public void setIdade(int idade) {
		this.idade = idade;
	}

}

Observe que adicionamos uma notação chamada SerializedName que indica qual sera o nome do atributo no Json. Vamos converter o nosso objeto Pessoa para vermos o resultado.

	public static void main(String[] args) {
		Pessoa p = new Pessoa();
		p.setIdade(15);
		p.setNome("Almiro Fagundes");
		p.setDataNascimento(new Date());
		Gson g = new Gson();
		String json = g.toJson(p);
		System.out.println(json);
	}

A saída gerada no exemplo acima é:

{"nome_completo":"Almiro Fagundes","idade":15,"data_nascimento":"Aug 4, 2012 1:19:59 AM"}

Ok, conseguimos alterar o nome do atributo, mas o formato que a data foi impressa não ficou legal. Vamos definir então um pattern para a nossa data. E essa tarefa é muito simples também:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class ConverterJson {

	public static void main(String[] args) {
		Pessoa p = new Pessoa();
		p.setIdade(15);
		p.setNome("Almiro Fagundes");
		p.setDataNascimento(new Date());
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("dd/MM/yyyy");
		Gson g = builder.create();
		String json = g.toJson(p);
		System.out.println(json);
	}	
}

Opa, agora temos uma pequena diferença. Ao invés de criarmos um objeto Gson diretamente estamos utilizando um Builder. Neste objeto definimos qual o Pattern utilizado para a data. Agora sim, a saída gerada:

{"nome_completo":"Almiro Fagundes","idade":15,"data_nascimento":"04/08/2012"}

E se eu tiver que trabalhar com List?

Bom, e se o objeto que tem que ser convertido for um objeto do tipo List? Vamos fazer um teste, e adicionar uma lista de String com os nomes dos irmãos na classe Pessoa.

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.google.gson.annotations.SerializedName;

public class Pessoa {

	@SerializedName(value = "nome_completo")
	private String nome;
	private int idade;
	@SerializedName(value = "data_nascimento")
	private Date dataNascimento;

	private List<String> irmaos = new ArrayList<>();

	public List<String> getIrmaos() {
		return irmaos;
	}
	public void setIrmaos(List<String> irmaos) {
		this.irmaos = irmaos;
	}
	public String getNome() {
		return nome;
	}
	public Date getDataNascimento() {
		return dataNascimento;
	}
	public void setDataNascimento(Date dataNascimento) {
		this.dataNascimento = dataNascimento;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public int getIdade() {
		return idade;
	}
	public void setIdade(int idade) {
		this.idade = idade;
	}

}

Observe que adicionamos uma lista como atributo da classe. Vamos agora adicionar alguns dados a ela e ver o resultado convertido.

import java.util.Date;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class ConverterJson {

	public static void main(String[] args) {
		Pessoa p = new Pessoa();
		p.setIdade(15);
		p.setNome("Almiro Fagundes");
		p.setDataNascimento(new Date());
		p.getIrmaos().add("Marilde Louzato");
		p.getIrmaos().add("João Fagundes");
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("dd/MM/yyyy");
		Gson g = builder.create();
		String json = g.toJson(p);
		System.out.println(json);
	}

}

E o resultado é:

{"nome_completo":"Almiro Fagundes","idade":15,"data_nascimento":"04/08/2012","irmaos":["Marilde Louzato","João Fagundes"]}

Podemos perceber que para todos estes casos a biblioteca fez a conversão de uma forma elegante, sem ser intrusiva ao código. Tivemos que adicionar anotações apenas quando decidimos formatar os campos do objeto Json.

Outros testes que fiz foi com Listas de outros objetos e inner class. A biblioteca conseguiu fazer a conversão em todos estes casos.

E quando eu quero criar um objeto Java?

O processo inverso, adivinhem? Sim, é bem simples. Vou pegar o último Json gerado e vou fazer o inverso, pedir para ele criar um objeto Java:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class ConverterJson {

	public static void main(String[] args) {
		String json = "{\"nome_completo\":\"Almiro Fagundes\",\"idade\":15,\"data_nascimento\":\"04/08/2012\",\"irmaos\":[\"Marilde Louzato\",\"João Fagundes\"]}";
		GsonBuilder builder = new GsonBuilder();
		builder.setDateFormat("dd/MM/yyyy");
		Gson g = builder.create();
		Pessoa p = g.fromJson(json, Pessoa.class);
		System.out.println("Nome: " + p.getNome());
		System.out.println("Idade: " + p.getIdade());
		System.out.println("Data Nascimento: " + p.getDataNascimento());
		System.out.println("Irmãos: " + p.getIrmaos().toString());
	}

}

E o resultado:

Nome: Almiro Fagundes
Idade: 15
Data Nascimento: Sat Aug 04 00:00:00 BRT 2012
Irmãos: [Marilde Louzato, João Fagundes]

E a conversão foi feita.

Pessoal, muito simples trabalhar com Json em Java. Vocês encontram mais informações no site. Um abraço.

Tutorial JSF 2.0 – Criando um converter

Olá a todos.

Seguindo os tutoriais de JSF 2.0, vou criar um exemplo simples de como podemos criar um converter utilizando o JSF 2.0 e suas annotations. Você pode acompanhar os posts anteriores que ensinam como criar uma aplicação JSF e como funcionam os ManagedBean neste link.

Se você quer saber como criar um converter utilizando o JSF 1.2, veja este post.

Converter

Converter é o componente do JSF que é responsável por fazer a conversão de um objeto para uma String e de uma String para um objeto.

Ele atua entre a página JSF e o Managed Bean, convertendo textos da página automaticamente em objetos no Managed Bean. Desta forma, nós definimos como a conversão deve ocorrer e depois disso, trabalhamos como se estivéssemos acessando o próprio objeto na página JSF.

Esta abordagem é especialmente útil quando temos um objeto que possui uma conversão padrão. Logo, podemos implementar no componente como esta conversão ocorre, e apenas reutilizá-la. Trabalhamos mais orientado a objetos também, sem precisar acessar o conteúdo do objeto o tempo inteiro na hora de construí-lo.

Então vamos ao exemplo. Neste, criaremos um converter para estado. Vale notar que iremos inicializar os estados via código, mas nada impede de carregar estas informações do banco.

Vamos então ao nosso POJO, a classe State que representa o nosso estado:


public class State {

	private String name;
	private String uf;

	public State(String name, String uf) {
		super();
		this.name = name;
		this.uf = uf;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getUf() {
		return uf;
	}
	public void setUf(String uf) {
		this.uf = uf;
	}

	@Override
	public String toString() {
		return uf + " - " + name;
	}
}

A classe State não tem mistério, ela possui apenas os campos uf e name. Estes vão representar nosso Estado. A ideia é trabalhar com o atributo uf na página e receber o objeto State correspondente pronto no ManagedBean.

Vamos agora criar nossa classe converter, esta responsável pela conversão:

import java.util.HashMap;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter(value="stateConverter", forClass=State.class)
public class StateConverter implements Converter {

	private static Map<String, State> states = new HashMap<String, State>();

	static {
		states.put("RS", new State("Rio Grande do Sul", "RS"));
		states.put("SP", new State("São Paulo", "SP"));
		states.put("RJ", new State("Rio de Janeiro", "RJ"));
	}

	@Override
	public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
		System.out.println("Converter1");
		return states.get(arg2);
	}

	@Override
	public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
		System.out.println("Converter2");
		return ((State) arg2).getUf();
	}

	public static Map<String, State> getStates() {
		return states;
	}
}

Esta classe representa um converter do JSF. A grande novidade aqui é a annotation @FacesConverter. Mas vamos explicar passo a passo esta classe:

A interface Converter possui 2 métodos. Os nomes são auto explicativos. Um converte um atributo String em um Object e o seu nome é getAsObject. Já o outro método é o contrário, converte um Object em uma String e se chama getAsString. Estes métodos são o “core” da funcionalidade. Nestes 2 métodos vamos dizer como nosso objeto do ManagedBean sera convertido em uma String (getAsString) e também o caminho inverso, onde dizemos como converter uma String em um objeto (getAsObject). Na prática, definimos, como ele será enviado para a tela como string e como ele será construído novamente para  um Object no ManagedBean.

Vale ressaltar também a criação de um mapa contendo alguns estados. Para o nosso exemplo foram criados apenas 3 estados.

A annotation FacesConverter é a grande novidade nesta versão. O atributo value é um identificador que o converter terá dentro de nossa aplicação JSF, é a forma como vamos chamá-lo nas páginas. O atributo forClass indica para qual classe o seu converter realizará a conversão.

ManagedBean

Vamos ver como isso funciona na prática. Primeiro vamos criar nosso ManagedBean. Ele sera um ManagedBean normal do JSF 2.0 e terá um atributo state que será inicializado como São Paulo, SP.

import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedBean;

@ManagedBean(name="stateMBean")
@RequestScoped
public class StateManageBean {

	private State state = new State("São Paulo", "SP");

	public String teste() {
		System.out.println(state);
		return "";
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

}

Repare que temos um método action chamado teste, que chamaremos para imprimir qual foi o state que recebemos no ManagedBean.

Abaixo, temos a nossa página JSF, ela é basicamente um campo de texto e um botão. Note que no campo de texto, atribuímos a value o objeto state diretamente e não o famoso stateMBean.state.uf , ou seja, estamos acessando o objeto state diretamente através do Input Text. O atributo de converter nós atribuímos o valor que identificamos na annotation FacesConverter.

<f:view>
	<h:form>
		<h:inputText value="#{stateMBean.state}" converter="stateConverter" />
		<h:commandButton value="teste" action="#{stateMBean.teste}" />
	</h:form>
</f:view>

O que ocorre agora? Vamos testar, na primeira requisição, nosso ManagedBean é criado e o valor default para ele, é SP. Logo você deve receber este valor no input text.

Isso ocorre porque dentro do converter, no método getAsString estamos retornando a UF quando recebemos um objeto State. Se mudarmos lá para recebermos o nome, automaticamente o retorno muda.

Experimente utilizar um estado do nosso universo conhecido (3 estados), por exemplo, Coloque RS e verifique que o ao executar a action teste, o objeto state impresso não é mais o SP e sim RS.

E como isso aconteceu?

Novamente, foi coverter, ao executar o método getAsObject.

Este exemplo é bem simples, mas nos ajuda a entender o mecanismo do converter, qualquer dúvida postem nos comentários.

Um abraço.

Benchmark leitura de pastas com muitos arquivos

Olá a todos.

Este post é uma continuação ao post de geração de muitos arquivos em uma única pasta.

Após verificar o tempo de geração de arquivos em uma única pasta aproveitei para fazer uma segunda medição: Qual o tempo de leitura de arquivos em uma pasta com diferentes números de arquivos?

Para este exemplo, executei a rotina apenas no Ubuntu 12.04.

O algoritmo executado aproveitava os arquivos gerados do post anterior e gera um número aleatório que coincide com um arquivo na pasta. Esta rotina foi repetida, um certo número de vezes, para se chegar a um tempo médio de leitura. Os testes foram executados para cada uma das pastas geradas.

A tabela abaixo representa os dados medidos:

Interações Arquivos Tempo (mS)
1.000 10 0,377
1.000 1.000 0,864
1.000 1.000.000 0,783
1.000 10.000.000 0,868
1.000.000 10.000.000 0,399

Num primeiro momento podemos verificar (e que a maioria deve saber) que é mais rápido ler do que gravar arquivos.

O mais importante a ser verificado é o tempo constante de leitura. Os tempos menores podem se valer de algum recurso do sistema operacional, tal como cache ou outras funcionalidades do IO.

Nas primeiras medições foram executados loops de mil interações lendo nas diferentes pastas. O tempo aumenta muito pouco conforme aumentamos o número de arquivos nas pastas. Este tempo esta na ordem de 0.1 mS ou seja 0.0001 S. Para a grande maioria das aplicações, podemos considerar como irrelevante o tempo de leitura em pastas com muitos arquivos.

Por fim, um teste extremo foi executado, iterando 1 milhão de vezes na pasta que continha 10 milhões de arquivos. Surpreendentemente o tempo médio de leitura diminuiu, certamente por conta de recursos de IO do SO.

Bom pessoal, eu gostei muito de ter realizado estas medições, pois não tenho dúvidas: O tempo de gravação e leitura de arquivos em pastas que contenham muitos deles, aumenta mas numa proporção que não é relevante para a grande maioria das aplicações.

 

Um abraço.

Benchmark gerar arquivos numa unica pasta no Windows e Ubuntu

Olá.

Por diferentes razões, podemos nos deparar com situações onde é necessário criar arquivos em disco para fins de cache, armazenamento, etc.

O problema é que dependendo do caso, começa a aumentar a complexidade para manutenção nesta estrutura, caso uma única pasta contenha uma quantidade muito grande de arquivos.

Este post vem para responder uma dúvida que algumas vezes vinha a tona nesta discussões: Afinal, criar milhares e até milhões de arquivos em uma única pasta, prejudica o desempenho do file system?

Até o final do post poderemos responder esta questão. Para nos ajudar, foi escrito um programa na linguagem Java que irá gerar uma grande quantidade de arquivos numa única pasta. O arquivo gerado continha uma sequência numérica e ocupava 1Kbyte. Para fins de comparação, a rotina foi executa em 2 SO (Windows 7 e Ubuntu 12.04).

Vale afirmar ainda que os dados foram gravados numa partição formatada em NTFS.

Antes de começarmos, gostaria de ressaltar alguns pontos:

  • A linguagem Java foi escolhida meramente por facilidade. Escrever o programa em outras linguagens como o C irá acarretar em ganho de performance.
  • O objetivo do post não é provar qual SO é mais rápido. Não foram tomadas medidas para garantir um cenário semelhante na execução dos testes. Os dados gerados são aproximados e não devem ser tomados como verdades absolutas.

Dito isso, vamos ao que importa.

A rotina criada consistia num loop que criava os arquivos numa pasta pré-definida e calculava o tempo médio de criação dos arquivos.

Foram executados 4 testes diferentes que se diferenciavam pelo número de arquivos gerados: 10, 1.000, 1.000.000 e 10.000.000.

Ubuntu 12.04

O Ubuntu instalado é o 12.04  e não entrarei em detalhes sobre o kernel do linux que o mesmo executa.

A tabela abaixo apresenta os dados de cada uma das execuções.

Ubuntu
Execuções Tempo Total Média(s) Média(ms)
10 0,005 0,0005 0,5
1.000 0,933 0,000933 0,933
1.000.000 956,158 0,000956 0,956158
10.000.000 11846,077 0,001185 1,1846077

Podemos observar um pequeno crescimento do tempo médio de execução. Observe o gráfico abaixo:

 

ubuntu1

Podemos observar que realmente ocorre um aumento no tempo de criação dos arquivos no file system. Como o tempo apresentado é a média, a geração dos arquivos no file system leva mais tempo do que o apresentado na imagem. Mas a ideia é verificar que sim, existe um aumento no tempo da criação, mas este aumento se da na ordem de milisegundos.

 

Windows

Vamos observar agora se o Windows mantém um comportamento parecido. Segue os dados colhidos:

Windows
Execuções Tempo Total Média(s) Média(ms)
10 0,006 0,0006 0,6
1.000 0,87 0,00087 0,87
1.000.000 852,871 0,000853 0,852871
10.000.000 8005,498 0,000801 0,8005498

Abaixo o gráfico:

windows

Podemos verificar que com o Windows, ocorre um comportamento curioso: No teste executado, o tempo médio de criação diminuiu conforme aumentamos a quantidade de arquivos.

 

Conclusão

Inicialmente vamos responder aquela pergunta lá do início do post:

Afinal, criar milhares e até milhões de arquivos em uma única pasta, prejudica o desempenho do file system?

E surpreendentemente a resposta a ser dada é: Não. Mesmo no caso do Ubuntu, o tempo médio aumentou numa escala pequena. Para a grande parte de aplicações este tempo não deve ser crítico. Claro que em alguns casos, este tempo pode ser considerado.

Em linhas gerais, consegui tirar minha dúvida, ambos os SO conseguem administrar o File System de maneira eficiente, e a gravação do arquivo não levou muito mais tempo.

Obviamente que manipular estes arquivos para tarefas como cópia e listagem irá ficar lento pela quantidade de arquivos.

 

Algumas considerações finais:

Me espantou o fato de o Windows diminuir o tempo e a diferença de tempo entre eles. Vale mencionar aqui que a execução no Windows ocorreu com mais recursos da máquina disponíveis. Quando gerei os arquivos no Ubuntu estava utilizando o Navegador e escutando Música. Mais uma vez, o objetivo era verificar se iria ocorrer um aumento significativo e não obter um tempo preciso.

Um abraço.

Instalar Ruby e o Rails no Ubuntu 12.04

Olá a todos.

Desejo neste post descrever os passos que segui para instalar o ruby e o framework rails no meu ubuntu 12.04. Teremos também bibliotecas adicionais que foram utilizadas para criar e executar aplicações com Rails.

O Ruby é uma linguagem de programação orientada a objetos que tem como premissa ser simples e completa. O slogan da linguagem no site é: “O melhor amigo do programador”. Isto porque o criador da linguagem  Yukihiro Matsumoto juntou diversas características de que gostava de outras linguagens que ele utilizava.

O Rails é um framework web da linguagem Ruby. Ele busca o conceito de convenção ao invés de configuração. A ideia é evitar muita configuração em arquivos xml e criar um padrão que contempla grande parte das implementações do dia a dia no desenvolvimento.

Instalando o Ruby

Para instalar o Ruby inicialmente devemos baixar as bibliotecas da linguagem, abra o terminal e digite o comando abaixo:

sudo apt-get install irb libopenssl-ruby libreadline-ruby rdoc ri ruby ruby-dev

Para verificarmos se o Ruby foi instalado corretamente, vamos verificar a versão do Ruby:

ruby -v

Caso o Ruby tenha sido instalado com sucesso, uma mensagem com a versão instalado sera exibida no terminal.

Vamos testar ainda o funcionamento do irb que é o interpretador de código da linguagem. Digite irb e o código, conforme a figura abaixo:

Ao executarmos o comando irb abrimos o interpretador da linguagem ruby e podemos executar código Ruby. No exemplo utilizamos o comando puts que serve imprimir um texto na tela. Para sair do irb digite exit().

Instalando o Ruby Gems

O Ruby Gems é o gerenciador de módulos e bibliotecas do Ruby. O Gems, baixa e instala os módulos da linguagem. Já antecipo, que caso sua internet não seja muito rápida, os comandos podem demorar para terminar de executar. Primeiro devemos acessar o diretório onde o RubyGems deve ser instalado:

cd /usr/local/src

Após isso, vamos fazer o download do Gems:

sudo wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.6.tgz

Como você pode perceber, acabamos de baixar um arquivo compactado, então devemos descompactá-lo:

sudo tar xzvf rubygems-1.3.6.tgz

Agora vamos acessar o diretório que foi criado com a descompactação e instalar o gems:

cd rubygems-1.3.6
sudo ruby setup.rb

Para verificar a instalação do RubyGems utilize o comando abaixo:

gem1.8 list

Vamos atualizar o RubyGems para garantir que estamos com a última versão:

sudo gem1.8 update --system

Instalando o Ruby on Rails

Uma vez instalado o Ruby e o RubyGems, nos falta instalar o Rails:

sudo gem1.8 install rails -v=3.2.6

Este comando pode demorar a executar. Várias bibliotecas serão baixadas e instaladas. Após a conclusão da instalação, digite o comando abaixo para verificar a versão do rails instalada:

rails -v

Agora vamos instalar algumas bibliotecas extras necessárias para executar e criar aplicações utilizando o rails.
Primeiro vamos instalar o SQLLite que é um banco de dados utilizado por default em novas aplicações Rails.

sudo apt-get install libsqlite3-dev
sudo gem1.8 install sqlite3 -v '1.3.6'

O Ubuntu não possui um motor javascript nativo. Por isso devemos instalar as bibliotecas abaixo também:

sudo apt-get install libv8-dev

sudo apt-get install nodejs

gem1.8 install railties

Estas foram as bibliotecas que eu utilizei na instalação do Ruby e Rails. Já consigo executar a aplicação sem problemas.

Se você quiser instalar ferramentas adicionais bem como o mysql, sugiro seguir este manual, que foi a principal fonte que utilizei para instalar.