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:

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:

	<Resource name="jdbc/agenda" 
		driverClassName="com.mysql.jdbc.Driver"
		type="javax.sql.DataSource"
		url="jdbc:mysql://localhost/agenda"
		auth="Container" 
		username="useragenda"
		password="senha"
		maxActive="30"
		maxIdle="3" />

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<Class<?>> getClasses() {
			Set<Class<?>> set = new TreeSet<Class<?>>();
			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<ContatoBean> listContatos() throws Exception {
			List<ContatoBean> ret = new ArrayList<ContatoBean>();
			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:

	<Context>
		<ResourceLink 
			name="jdbc/agenda" 
			global="jdbc/agenda"
			type="javax.sql.DataSource"/>
	</Context>

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):

	<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
	<html>
	<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Insert title here</title>
	<script type="text/javascript" src="jquery-1.6.4.js"></script>
	<script type="text/javascript" src="jq-json-post-0.1.js"></script>
	</head>
	<body>
		<label>id:</label>
		<br />
		<span id="idcontato"></span>
		<br />
		<label>Nome:</label>
		<br />
		<input id="nomecontato" />
		<br />
		<label>Endereço:</label>
		<br />
		<input id="enderecocontato" />
		<br />
		<label>Telefone:</label>
		<br />
		<input id="telefonecontato" maxlength="8" />
		<br />
		<button id="salvar">Salvar</button>
		<hr />
		<table>
			<thead>
				<tr>
					<th>id</th>
					<th>nome</th>
					<th>endereco</th>
					<th>telefone</th>
					<th>data de nascimento</th>
				</tr>
			</thead>
			<tbody id="tabela">
				<!-- dynamic content goes here -->
			</tbody>
		</table>
		<script type="text/javascript">
			var id = $("#idcontato");
			var nome = $("#nomecontato");
			var endereco = $("#enderecocontato");
			var telefone = $("#telefonecontato");
			var salvar = $("#salvar");
			var tabela = $("#tabela");
			var list = [];

			function update() {
				tabela.html("");
				for ( var x in list) {
					var str = "<tr>";
					str += "<td>" + list[x]["id"] + "</td>";
					str += "<td>" + list[x]["nome"] + "</td>";
					str += "<td>" + list[x]["endereco"] + "</td>";
					str += "<td>" + list[x]["telefone"] + "</td>";
					str += "<td>" + list[x]["dataNasc"] + "</td>";
					str += "</tr>";
					tabela.append(str);
				}
			}

			salvar.click(function() {
				$.json_post("resource/contato", {
					nome : nome.val(),
					endereco : endereco.val(),
					telefone : telefone.val(),
					dataNasc : new Date()
				}, function() {
					$.getJSON("resource/contato", function(ret) {
						if (ret && ret.contatoBean)
							list = ret.contatoBean;
						else
							list = [];
						update();
					});
				});
			});
		</script>
	</body>
	</html>

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 fetivamente 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 escolhessemos 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!

3 ideias sobre “Tutorial: JAX-RS com Jersey no tomcat 7.0 para iniciantes

  1. Pingback: Cliente android consumindo REST de forma transparente, fácil e rápida « sombriks have a plan

Deixe um comentário