RESTful Web Services com RestEasy, Weld e Hibernate no JBoss AS 7.1.3 ( JBoss EAP 6.0.1 )

Postado em Atualizado em

Olá amigos,

Hoje vamos aprender um pouco sobre REST🙂

O REST(Representational State Transfer) descreve arquiteturas que utilizam o protocolo HTTP ou protocolos similares, restringindo a interface para um conjuntos de operações conhecidas como por exemplo GET, POST, PUT e DELETE para HTTP.

O termo Representational State Transfer foi introduzido e definido em 2000 por Roy Fielding em sua tese de doutorado.

http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

Na plataforma Java temos o JAX-RS que fornece uma API padronizada para a construção de Web Services RESTful. Essa API possui um conjunto de anotações e interfaces que são aplicadas nos POJOs expondo assim facilemente recursos na web. Essa abordagem torna simples a criação de Web Services RESTful em Java.

Um conceito muito importante quando utilizamos REST é a existência de resources, onde cada resource possui um identificador global, isto é, uma URI.
Os resources podem ser representados em diversos formatos por exemplo html, xml ou json.

A anotação @Path define o caminho relativo da URI. Todo resource deve possuir uma URI que é definida por essa anotação.
Essa característica é bastante poderosa pois permite incorporar variáveis dentro da sintaxe da URI e essas variáveis podem ser substituídas em tempo de execução.

Com o JAX-RS  os métodos HTTP mapeados para métodos Java de um resource. As anotações @GET, @PUT, @POST, @DELETE e @HEAD são utilizadas para realizar esse mapeamento. Podemos ainda definir subresources detro de um resource utilizando a anotação @Path nos métodos.

A anotação @Produces é utilizada para especificar os tipos MIME que um resource pode consumir que foram enviados de um cliente. Tipos MIME incluem PLAIN_TEXT, TEXT_XML, APPLICATION_XML e APPLICATION_JSON.

No JBoss podemos utilizar o RESTEasy que é uma implementação da especificação JAX-RS e que  fornece uma API Java para Web Services RESTful através do protocolo HTTP.  No post de hoje vamos criar um pequeno exemplo que lista os estados e cidades de todo o Brasil armazenados no MySQL.

O primeiro passo é criar no MySQL um database chamado jbossdb  e criar as tabelas tb_estados e tb_cidades utilizando o seguite script: Cidades Estados.  Faça também os inserts com os nomes dos estados e das cidades.

Configure um datasource no arquivo JBOSS_HOME/standalone/configuration/standalone.xml para o MySQL:

<datasource jndi-name="java:/MySQLDS" pool-name="MySQLDS-Pool" enabled="true" use-java-context="true">
  <connection-url>jdbc:mysql://localhost:3306/jbossdb</connection-url>
  <driver>mysql-connector-java-5.1.22-bin.jar</driver>
  <security>
   <user-name>root</user-name>
   <password>jboss</password>
  </security>
</datasource>

O pom.xml deverá ser algo como:

<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/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.jbossdivers</groupId>
 <artifactId>rest</artifactId>
 <packaging>war</packaging>
 <version>1.0</version>
 <name>rest Maven Webapp</name>
 <url>http://maven.apache.org</url>

 <repositories>
   <repository>
    <id>JBoss repository</id>
    <url>https://repository.jboss.org/nexus/content/groups/public/</url>
   </repository>
  </repositories>

  <dependencies>

   <dependency>
     <groupId>org.jboss.spec</groupId>
     <artifactId>jboss-javaee-6.0</artifactId>
     <version>1.0.0.Final</version>
     <type>pom</type>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.jboss.resteasy</groupId>
     <artifactId>resteasy-jaxrs</artifactId>
     <version>2.2.2.GA</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.jboss.resteasy</groupId>
     <artifactId>resteasy-jaxb-provider</artifactId>
     <version>2.2.2.GA</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.jboss.resteasy</groupId>
     <artifactId>resteasy-jettison-provider</artifactId>
     <version>2.2.2.GA</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-core</artifactId>
     <version>4.0.1.Final</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-entitymanager</artifactId>
     <version>4.0.1.Final</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-annotations</artifactId>
     <version>3.5.6-Final</version>
     <scope>provided</scope>
   </dependency>
   <dependency>
     <groupId>org.jboss.weld</groupId>
     <artifactId>weld-api</artifactId>
     <version>1.0</version>
     <scope>provided</scope>
    </dependency>
   </dependencies>
   <build>
    <plugins>
     <plugin>
       <artifactId>maven-resources-plugin</artifactId>
       <version>2.4.3</version>
       <configuration>
         <encoding>UTF-8</encoding>
       </configuration>
     </plugin>
     <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
           <source>1.6</source>
           <target>1.6</target>
        </configuration>
     </plugin>
     <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1.1</version>
        <configuration>
            <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
        </plugin>
     </plugins>
        <finalName>restapp</finalName>
     </build>
  </project>

Crie as entidades State e City para representar as tabelas tb_estados e tb_cidades:

Estado:

package com.jboss.rest.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@Entity
@Table(name="tb_estados")
public class State {

  @Id
  private Long id;
  private String uf;
  private String nome;

  //getters and setters
}

Cidade:

package com.jboss.rest.entity;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@Entity
@Table(name="tb_cidades")
public class City {

  @Id
  private Long id;
  private Long estado;
  private String uf;
  private String nome;

  //getters and setters
}

O nosso serviço conterá os métodos para Listar todos os Estados e Listar as Cidades por Estado:

package com.jboss.rest.service;

import com.jboss.rest.entity.City;
import com.jboss.rest.entity.State;

import java.awt.print.Book;
import java.util.List;
import javax.inject.Inject;
import javax.persistence.EntityManager;

import javax.persistence.Query;
import javax.ws.rs.*;

@Path("/service")
public class MyService {

  @Inject
  private EntityManager em;

  @GET
  @Produces("application/json")
  @Path("/liststates")
  public List<State> listAllStates() {

    Query query = em.createQuery("FROM com.jboss.rest.entity.State");
    List <State> stateList =  query.getResultList();

    return stateList;
  }

  @GET
  @Produces("application/json")
  @Path("/listcitiesbystate/")
  public List<City> listAllCitiesByState(@QueryParam("uf")String uf) {

    Query query = em.createQuery("FROM com.jboss.rest.entity.City c where c.uf =:uf ").setParameter("uf",uf);
    List <City> cityList =  query.getResultList();

    return cityList;
  }
}

No serviço estamos injetando o EntityManager então crie um resource como abaixo:

package com.jboss.rest.qualifier;

import javax.enterprise.inject.Produces;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class Resources {

  @PersistenceContext
  @Produces
  private EntityManager em;
}

Em resource/META-INF/ crie o persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

  <persistence-unit name="persistenceUnit" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/MySQLDS</jta-data-source>

    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
    </properties>
  </persistence-unit>
</persistence>

Em webapp/WEB-INF crie o arquivo beans.xml para conseguirmos utilizar o CDI:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" 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/beans_1_0.xsd">

</beans>

Configure também o web.xml:

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

  <display-name>Rest App</display-name>

  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/rest</param-value>
  </context-param>

  <context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
  </context-param>

  <servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

</web-app>

A estrutura final do projeto deverá ficar da seguinte maneira:

project

Agora faça o deploy da aplicação e acesse as urls dos serviços criados.

http://192.168.0.127:8080/restapp/rest/service/liststates

restestadoshttp://192.168.0.127:8080/restapp/rest/service/listcitiesbystate/?uf=mt

restcidades

Voce pode por exemplo criar um dropwdonw para listar as cidades quando um estado específico for selecionado:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="<c:url value="/js/jquery-1.9.1.min.js" />"></script>

<script type="text/javascript" charset="utf-8">

 $(document).ready(function() {

    $.ajax({
      contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
      type: "GET",
      url: "/restapp/rest/service/liststates",
      dataType:"json",
      success: function(json) {
      $.each(json, function(i, value) {

         $('#state').append($('<option>').text(value.uf).attr('value', value.uf));

         $('#state').change(function() {

         $('#city').empty();

         $.ajax({
           contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
           type: "GET",
           url: "/restapp/rest/service/listcitiesbystate/",
           data: 'uf='+ $('#state').val(),
           dataType:"json",
           success: function(json) {
           $.each(json, function(i, value) {
               $('#city').append($('<option>').text(value.nome).attr('value', value.nome));
           });
        }
     });

   });

  });
 }
});
});

</script>

</head>
<body>
  <form action="" id="test">
       <h2>Rest Service</h2>

       <select id="state" name="state"></select>
       <br />
       <select id="city" name="city"></select>
  </form>
</body>
</html>

restapp

Para mais informações consulte a JAX-RS 1.1 specification, JSR-311: http://jcp.org/en/jsr/detail?id=311

A aplicação utilizada nesse post está no github ( Sem querer comitei as confs do Intellij depois deleto!)

Espero que tenha ajudado.

Abraços

Mauricio Magnani Jr

3 comentários em “RESTful Web Services com RestEasy, Weld e Hibernate no JBoss AS 7.1.3 ( JBoss EAP 6.0.1 )

    jorge guedes alcoforafo neto disse:
    11 de abril de 2013 às 12:37

    Muito bom o post, parabens…

    m-malik.com disse:
    30 de abril de 2013 às 18:19

    […] Magnani Jr ссылается сюда со словами: «O REST(Representational State Transfer) descreve a […]

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s