Blog

Criando e consumindo WebServices REST em Java


Assim como explicado no artigo "Criando e consumindo WebServices SOAP em Java" é muito comum que cada vez mais analistas optem por utilizar uma arquitetura distribuída e busquem tornar seus projetos prontos para operarem em multiplataformas. Evidentemente, existem muitas práticas necessárias para atingir este objetivo e, portanto, não se trata apenas de uma prática ou outra, mas sim o conjunto delas. Neste artigo apenas será abordado uma das tecnologias disponíveis para isso.

Para tornar mais fácil a compreensão da tecnologia, foi utilizado um exemplo de uma consulta de endereço por CEP com apenas um método com um retorno fixo simples. 


package com.joaofelipe.cep;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Endereco {

    public String estado;
    public String cidade;
    public String bairro;
}


Nota-se no código a seguir, que foi criada uma interface que possui apenas um método, "consultar". Este método apresenta a anotação "@Get", indicando que o método será acessível diretamente via GET. A anotação "@Path" define a rota a qual este método estará escutando e, portanto, não deverão existir rotas coincidentes. A notação "@Produces(MediaType.APPLICATION_JSON)" indica a forma a qual os dados serão retornados para o cliente, neste caso conteúdo em formato Json. A notação "@Consumes(MediaType.APPLICATION_JSON)" define como os dados serão aceitos quando vindos do cliente, neste caso conteúdo em formato Json.

A classe também possui uma anotação "@Path" para definir a rota referente a ela. As demais anotações também poderiam ser anotadas diretamente na classe, o que faria com que os métodos assumissem este mesmo comportamento, exceto se eles também tivessem a anotação com uma informação diferente.


package com.joaofelipe.cep;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/cep")
public class CepService {

    @GET
    @Path("/consultar/{param1}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Endereco consultar(@PathParam("param1") int cep) {

        Endereco endereco = new Endereco();
endereco.estado = "BA"; endereco.cidade = "Salvador"; endereco.bairro = "Pituba"; return endereco; } }


Para rodar o serviço (servidor) foi utilizado o Jersey e o Grizzly, conforme exemplo a seguir:


package com.joaofelipe.cep;

import java.util.HashMap;
import java.util.Map;

import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;

public class CepServicePublisher {

    public static void main(String[] args) {        
        final String baseUri = "http://localhost:7080/";
        final Map initParams = new HashMap();

        // Register the package that contains your javax.ws.rs-annotated beans here
        initParams.put("com.sun.jersey.config.property.packages","com.joaofelipe.cep");

        System.out.println("Starting grizzly...");
        try {
            SelectorThread threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);
            System.out.println(String.format("Jersey started with WADL " + "available at %sapplication.wadl.", baseUri));
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}


A biblioteca Jersey pode ser baixada via maven ou diretamente pelo site:

<!-- https://mvnrepository.com/artifact/com.sun.jersey/jersey-bundle -->
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-bundle</artifactId>
    <version>1.19.2</version>
</dependency>


A biblioteca Grizzly pode ser baixada via maven ou diretamente pelo site:

<!-- https://mvnrepository.com/artifact/com.sun.grizzly/grizzly-servlet-webserver -->
<dependency>
    <groupId>com.sun.grizzly</groupId>
    <artifactId>grizzly-servlet-webserver</artifactId>
    <version>1.9.64</version>
</dependency>

Para consumir o WebService REST é possível acessar diretamente o servidor via URL, como no exemplo a seguir:


http://localhost:7080/cep/consultar/41810215


Ainda assim, é possível consumir o serviço diretamente em outro projeto, por exemplo, utilizando a biblioteca JAX-RS, podendo ser realizado da seguinte forma:


package com.joaofelipe.cep;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;

public class CepClient {

    public static void main(String[] args) {

        Endereco endereco = consultar(41810215);

        System.out.println("Estado: " + endereco.estado);
        System.out.println("Cidade: " + endereco.cidade);
        System.out.println("Bairro: " + endereco.bairro);
    }

    public static Endereco consultar(int cep) {

        Client client = ClientBuilder.newClient();

	WebTarget target = client.target("http://localhost:7080/cep/consultar/" + cep);

	Endereco endereco = target.request().get(Endereco.class);

        return endereco;
    }
}


A biblioteca JAX-RS pode ser baixada via maven ou diretamente pelo site:

<!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
<dependency>
    <groupid>javax.ws.rs</groupid>
    <artifactid>javax.ws.rs-api</artifactid>
    <version>2.0</version>
</dependency>



No fim seu projeto deve ficar divido de forma semelhante a apresentada acima. Importante observar que neste exemplo o projeto "rest-common" é utilizado pelos demais projetos "rest-server" e "rest-client".

REST Java WebService

Criando e consumindo WebServices SOAP em Java


É muito comum que cada vez mais analistas optem por utilizar uma arquitetura distribuída e busquem tornar seus projetos prontos para operarem em multiplataformas. Evidentemente, existem muitas práticas necessárias para atingir este objetivo e, portanto, não se trata apenas de uma prática ou outra, mas sim o conjunto delas. Neste artigo apenas será abordado uma das tecnologias disponíveis para isso.

Para tornar mais fácil a compreensão da tecnologia, foi utilizado um exemplo de uma consulta de endereço por CEP com apenas um método com um retorno fixo simples. 


package com.joaofelipe.cep;

public class Endereco {

    public String estado;
    public String cidade;
    public String bairro;
}


Nota-se no código a seguir que foi criada uma interface que possui apenas um método, "consultar". Este método apresenta a notação "WebMethod" que indica se tratar de um método acessível do WebService. Os métodos que não possuem essa notação não serão acessíveis como métodos do WebService, mas terão comportamento normal assim como qualquer método de uma classe.

A interface também possui algumas anotações como "WebService", que indica se tratar de uma classe com comportamento de serviço web. Já a anotação "SOAPBinding(style = Style.RPC)" indica a forma como o serviço está sendo disponibilizado, neste caso, via RPC.


package com.joaofelipe.cep;
import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; @WebService @SOAPBinding(style = Style.RPC) public interface CepServer { @WebMethod Endereco consultar(int cep); }


Russell Butek explica um pouco mais sobre as diferenças de estilo do SOAPBinding no developerWorks da IBM:


Before I go any further, let me clear up some confusion that many of us have stumbled over. The terminology here is very unfortunate: RPC versus document. These terms imply that the RPC style should be used for RPC programming models and that the document style should be used for document or messaging programming models. That is not the case at all. The style has nothing to do with a programming model. It merely dictates how to translate a WSDL binding to a SOAP message. Nothing more. You can use either style with any programming model.


Na classe CepServerImpl estão as implementações dos métodos da interface CepServer, apresentada acima. A anotação "WebService(endpointInterface = "com.joaofelipe.cep.CepServer")" indica o pacote e a interface do WebService.


package com.joaofelipe.cep;
import javax.jws.WebService; @WebService(endpointInterface = "com.joaofelipe.cep.CepServer") public class CepServerImpl implements CepServer { public Endereco consultar(int cep) { Endereco endereco = new Endereco(); endereco.estado = "BA"; endereco.cidade = "Salvador"; endereco.bairro = "Pituba"; return endereco; } }


Para rodar o serviço utilizamos apenas um Endpoint, pois não havia necessidade de utilizar algo com mais recursos, como um Apache Tomcat ou outro servidor qualquer. Desta forma, apenas iniciamos o serviço e deixamos ele acessível para que um cliente o consuma. Para saber um pouco mais sobre EndPoints, visite o site da Oracle em docs.oracle.com.


package com.joaofelipe.cep;
import javax.xml.ws.Endpoint; public class CepServerPublisher { public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:9871/cep", new CepServerImpl()); } }


Para consumir o WebService SOAP que criamos, será preciso mapear seus métodos da seguinte forma:


package com.joaofelipe.cep;
import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; class CepClient { public static void main(String args[]) throws Exception { URL url = new URL("http://127.0.0.1:9871/cep?wsdl"); QName qname = new QName("http://cep.joaofelipe.com/","CepServerImplService"); Service ws = Service.create(url, qname); CepServer cep = ws.getPort(CepServer.class); Endereco endereco = cep.consultar(41810215); System.out.println("Estado: " + endereco.estado); System.out.println("Cidade: " + endereco.cidade); System.out.println("Bairro: " + endereco.bairro); } }


Evidentemente, o projeto onde o WebService será consumido precisa conhecer a classe Endereco e a interface que define os métodos do mesmo e, portanto, será preciso criar um projeto para ser utilizado por ambos, evitando assim duplicidade de código que ocorreria caso uma cópia da classe e da interface existisse em cada projeto, o que não deixa de ser funcional.



No fim seu projeto deve ficar divido de forma semelhante a apresentada acima. Importante observar que neste exemplo o projeto "soap-common" é utilizado pelos demais projetos "soap-server" e "soap-client".

SOAP Java WebService