domingo, 20 de janeiro de 2013

Tutorial: JAX-RS com Jersey no tomcat 7.0 para iniciantes

Good news everyone! Hoje vamos ver um longo tutorial que vai do zero ao aplicativo rodando em um tomcat 7 usando JAX-RS!

De modo a produzirmos exatamente os resultados esperados e vistos quando escrevi isso aqui, os seguintes pré-requisitos devem ser respeitados:

  1. Linux Fedora 15 (64 bits)
  2. eclipse indigo (3.7)
  3. Sun/Oracle Java ou OpenJDK, versão 6
  4. mysql 5.1 (padrão no opensuse 11.4)
  5. Jersery 1.10
  6. tomat 7.0.22

Claro, pequenas variações podem dar certo também, e os passos que apresentaremos podem servir de referencial para soluções parecidas.

Abaixo nosso roteiro:

1- instalar o mysql 2- configurar o mysql 3- instalar o eclipse (e o java) 4- instalar o tomcat 7.0 5- configurar o tomcat 7.0 (no eclipse, criar o Resource do mysql no globalnamingresource, driver jdbc do mysql) 6- escrever pequena agenda de exemplo

No Fedora 15 a ferramenta de linha de comando que instala automagicamente os programas é o yum.

Digite o seguinte comando no terminal para instalar o servidor de banco de dados e o suporte a conexão via java:

sudo yum install mysql-server mysql-connector-java

A 'parte java' do processo abordaremos mais à frente. Vamos por hora apenas colocar o banco pra rodar:

sudo service mysqld start

A instalação padrão vem desprotegida; você pode pesquisar em separado como ativar a segurança do mysql, é um assunto bastante conhecido e não preciso repeti-lo aqui.

Vamos criar o banco de dados e o usuário para a aplicação de exemplo que mostraremos bem mais à frente:

mysql -u root

O prompt do mysql surgirá e nele iremos criar o banco de dados:

create database agenda;

Em seguida damos grant ao usuário e apresentamos uma senha:

grant all privileges on agenda.* to useragenda@localhost identified by 'senha';
flush privileges;

Agora vamos fazer login com o usuário que criamos. No terminal do mysql, dê um CTRL+D (terminará a seção e retornará ao shell) e faça login da seguinte forma:

mysql -D agenda -u useragenda -p Enter password:

A senha não será ecoada. Crie a tabela de contatos utilizando o seguinte SQL:

[sourcecode language="sql"] create table tb_contatos( id integer not null primary key auto_increment, nome varchar(300) not null, endereco varchar(600) not null, telefone varchar(8), data_nascimento date);

Assim o banco estará pronto para usar. Atenção ao nome do banco, do usuário e senha; precisaremos destes dados mais adiante.

Agora é hora de providenciarmos as ferramentas java; comecemos pelo openjdk disponível no repositório do Fedora 15:

sudo yum install java-1.6.0-openjdk-devel.x86_64

Alguns pacotes tem nomes longos, e saber exatamente o que instalar pode dar algum trabalho. É possível fazer uma busca por parte do nome, coisa que facilita encontrar o que se precisa:

sudo yum search openjdk

Na lista de resultados você encontrará o que precisa, :-)

Dando continuidade, providenciaremos os downloads do eclipse, do tomcat e do jersey framework. Há um eclipse disponível nos repositórios do fedora, entretanto você encontrará mais pessoas usando o eclipse fornecido diretamente pela fundação eclipse.

Baixe os seguintes arquivos:

download eclipse

download tomcat

download jersey

Atenção: embora eu já tenha esclarecido, reforço: o Fedora escolhido foi o 64 bits; isto influencia no download do elipse, que também será aa versão para linux em 64 bits, pois o eclipse possui uma parte nativa. Mas isto é outra história.

Descompacte o eclipe e o tomcat na sua pasta home, entre na pasta do eclipse e execute-o. A seguinte tela surgirá:

Feche o welcome e vá na aba servers. Este eclipse é o JEE - Java Enterprise Edition. Quem trabalha a sério com java baixa esta versão, mesmo que não vá escrever nada para a WEB no momento.

Crie um novo servidor:

Use o filtro, procure por tomcat v7. será a opção a aparecer na caixa logo abaixo. Indique em seguida o caminho da pasta do tomcat:

O projeto Servers será criado. Ele contém as configurações que este tomcat "capturado" pelo eclipe utilizará por padrão. Você pode fazer o eclipse usar a configuraação de dentro do próprio tomcat bem facilmente, mas deixo isso por sua conta, ;-)

Abra o projeto Servers, entre na pasta do tomcat que foi configurado, abra o xml chamado server.xml e selecione a aba source já no editor; ela fica no rodapé do editor. Aí sim você terá acesso ao conteúdo do xml.

Procure a sessão GlobalNamingResources; lá adicione a configuração do datasource para o mysql:

	

O xml resultante deve se parecer com o seguinte:

Observe o banco, usuário e senha: tem de ser os mesmos utilizados anteriormente, na configuração do mysql.

Não basta o xml, o driver JDBC do mysql, que baixamos lá no início do tutorial, deve ser copiado para a pasta lib do tomcat.

Você encontrará este driver na pasta "/usr/share/java", copie o driver de nome "mysql-connector-java-5.1.15.jar"; o outro arquivo de nome mais simples é um link simbólico para este aqui.

Como deve ficar a lib do tomcat:

Agora, vamos criar a aplicação java que consumirá este datasource. A aplicação não terá pistas sobre que banco de dados é este ou onde ele se encontra; apenas saberá o name do Resource: "jdbc/agenda"; é assim que a especificação espera que você use recursos.

É bem simples criar uma aplicação web em java usando esta versão do eclipse; tem um botão que faz quase tudo hoje em dia:

No wizard basta você dar o nome do projeto. Observe que a versão do webmodule será a 3.0, ou seja, salvo uma exceção, sem arquivos xml de configuração dentro do projeto da aplicação. Até outro dia isto era impensável em projetos java, hoje é regra.

Vá até o zip do framework jersey agora. Descompacte, entre na pasta lib:

Copie todos os .jar para dentro da pasta lib do projeto no eclipse.

A partir desta parte, a parte final, este tutorial torna-se diferente dos tutoriais comumente vistos sobre JEE. Nada de Servlets, JSF-ismos ou EJB's: iremos criar REST Resources!

O passo inicial é criar o "entry point" da aplicação JAX-RS. Basta criar uma classe que estenda de "javax.ws.rs.core.Application", no nosso exemplo a classe App:

	package org.sample.jaxrs;

	import java.util.Set;
	import java.util.TreeSet;

	import javax.ws.rs.ApplicationPath;
	import javax.ws.rs.core.Application;

	@ApplicationPath("/resource")
	public class App extends Application {

		@Override
		public Set> getClasses() {
			Set> set = new TreeSet>();
			set.add(ContatoResource.class);
			return set;
		}
	}

Esta será também a raíz de todas as chamadas do serviço REST. O propósito do método getClasses é listar os Recursos anotados com os caminhos e verbos HTTP.

Vamos ver o recurso REST:

	package org.sample.jaxrs;

	import java.sql.Connection;
	import java.sql.Date;
	import java.sql.PreparedStatement;
	import java.sql.ResultSet;
	import java.sql.Statement;
	import java.util.ArrayList;
	import java.util.List;

	import javax.naming.InitialContext;
	import javax.sql.DataSource;
	import javax.ws.rs.GET;
	import javax.ws.rs.POST;
	import javax.ws.rs.Path;

	@Path("/contato")
	public class ContatoResource {

		@GET
		public List listContatos() throws Exception {
			List ret = new ArrayList();
			DataSource ds = (DataSource) new InitialContext()
					.lookup("java:comp/env/jdbc/agenda");
			Connection con = ds.getConnection();
			Statement stm = con.createStatement();
			ResultSet rs = stm
					.executeQuery("select id,nome,endereco,telefone,data_nascimento from tb_contatos");
			while (rs.next()) {
				ret.add(new ContatoBean(rs.getInt(1), //
						rs.getString(2), //
						rs.getString(3), //
						rs.getString(4), //
						rs.getDate(5)));
			}
			rs.close();
			stm.close();
			con.close();
			return ret;
		}

		@POST
		public void addContato(ContatoBean c) throws Exception {
			DataSource ds = (DataSource) new InitialContext()
					.lookup("java:comp/env/jdbc/agenda");
			Connection con = ds.getConnection();
			PreparedStatement pst = con
					.prepareStatement("insert into tb_contatos(nome,endereco,telefone, data_nascimento) values (?,?,?,?)");
			pst.setString(1, c.getNome());
			pst.setString(2, c.getEndereco());
			pst.setString(3, c.getTelefone());
			pst.setDate(4, new Date(c.getDataNasc().getTime()));
			pst.executeUpdate();
			pst.close();
			con.close();
		}
	}

Embora esteja perfeitamente em ordem, e no glassfish e outros servidors JEE6 certificados código similar funcione corretamente, um ajuste será necessário em nossas configurações de projeto específicas para o tomcat. Crie um arquivo chamado context.xml dentro da pasta META-INF que se encontra dentro da pasta WebContent. O arquivo deverá conter esta configuração:

	
		
	

A classe ContatoBean é um pojo simples com anotações do JAXB:

	package org.sample.jaxrs;

	import java.util.Date;

	import javax.xml.bind.annotation.XmlAccessType;
	import javax.xml.bind.annotation.XmlAccessorType;
	import javax.xml.bind.annotation.XmlRootElement;
	import javax.xml.bind.annotation.XmlType;

	@XmlRootElement
	@XmlType(name = "contato")
	@XmlAccessorType(XmlAccessType.FIELD)
	public class ContatoBean {

		private int id;
		private String nome;
		private String endereco;
		private String telefone;
		private Date dataNasc;

		public ContatoBean() {
		}

		public ContatoBean(int id, String nome, String endereco, String telefone,
				Date dataNasc) {
			this.id = id;
			this.nome = nome;
			this.endereco = endereco;
			this.telefone = telefone;
			this.dataNasc = dataNasc;
		
		}

		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 getEndereco() {
			return endereco;
		}

		public void setEndereco(String endereco) {
			this.endereco = endereco;
		}

		public String getTelefone() {
			return telefone;
		}

		public void setTelefone(String telefone) {
			this.telefone = telefone;
		}

		public Date getDataNasc() {
			return dataNasc;
		}

		public void setDataNasc(Date dataNasc) {
			this.dataNasc = dataNasc;
		}

	}

Estas 3 classes e aquele xml incidental ilustram como é o lado do servidor de aplicações JAX-RS. Vamos ver agora um pequeno cliente javascript para este serviço.

Usando o que foi visto no post anterior (que tratava justamente de submissões de entidades e não de formulários) podemos montar o seguinte cliente (salve-o como index.html dentro de WebContent):

	
	
	
	
	Insert title here
	
	
	
	
		
		








id nome endereco telefone data de nascimento

Observe as duas dependências de script. Estas foram apresentadas no post anterior, não irei cobrir aqui.

Embora pouco funcional, este exemplo mostra claramente como podemos, a partir de um formulário, montar rapidamente um objeto JSON e envia-lo para o servidor, onde ele é convertido automaticamente para um objeto java.

Embora longo, este tutorial mostra o básico para montar um ambiente JAX-RS dentro do tomcat, cobrindo, de fato, mais passos de configuração do que efetivamente o código necessário para publicar recursos REST. De certo modo isto é bom, pois há pouco código a produzir ou configurar uma vez que o JAX-RS resolve de maneira elegante a tradução de objetos e o roteamento dos serviços.

Caso escolhêssemos um outro conjunto de tecnologias (glassfish ou jboss no lugar do tomcat) talvez o número de passos fosse menor.

Encerrando, espero que isto lhe seja útil, combine com outros conhecimentos e produza algo ainda melhor!

Nenhum comentário :

Postar um comentário