Pense na dor de cabeça -- WebService REST retornar ArrayList

Parece até besteira fazer esse processo, mas até os mais experientes se deparam com isso e tropeçam, podem resolver mas se não for algo do dia-a-dia acaba dando um bug nos neurônios.

A idéia é ter uma lista ou base de dados que seja divulgada por meio de um WebService Rest para que seja utilizado por alguma aplicação ou mesmo via web.

No exemplo estou utilizando uma base de dados de clientes, ao ser solicitada a listagem, retorna-se a lista, uma mensagem de retorno, e um código de retorno. Isso para que seja tratado pelo cliente, para casos de erro, sucesso etc...

Vamos então:

O servidor REST em questão foi montado com uso do eclipse, maven, com Tomcat. Essa estrutura fica para outra postagem. Mas, basicamente cria-se um novo projeto maven, utilizando maven-archetype-quickstart.


No pom.xml com as seguintes dependencies:

<dependency>    <groupId>com.ibm.db2.jcc</groupId>    <artifactId>db2jcc</artifactId>    <version>db2jcc4</version></dependency>
<!-- https://mvnrepository.com/artifact/com.ibm.db2/db2jcc --><!-- https://mvnrepository.com/artifact/com.ibm.db2.jcc/db2jcc4 --><!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --><dependency>    <groupId>com.google.code.gson</groupId>    <artifactId>gson</artifactId>    <version>2.8.0</version></dependency>
<dependency>    <groupId>org.glassfish.jersey.containers</groupId>    <artifactId>jersey-container-servlet</artifactId>    <version>2.22.2</version></dependency>         <dependency>    <groupId>com.fasterxml.jackson.datatype</groupId>    <artifactId>jackson-datatype-jsr310</artifactId>    <version>2.9.5</version></dependency> <dependency>    <groupId>org.glassfish.jersey.media</groupId>    <artifactId>jersey-media-json-jackson</artifactId>    <version>2.22.2</version></dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>1.17</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-servlet</artifactId> <version>1.17</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>1.17</version> </dependency> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>jsr311-api</artifactId> <version>1.1.1</version> </dependency> </dependencies> <build> <finalName>MeuSite</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <webXml>WebContent\WEB-INF\web.xml</webXml> </configuration> </plugin> <plugin>        <groupId>org.apache.maven.plugins</groupId>        <artifactId>maven-compiler-plugin</artifactId>        <version>3.1</version>        <configuration>            <source>1.8</source>            <target>1.8</target>        </configuration>    </plugin> </plugins> </build> 

Repare que no meu pom.xml tem uma dependência para DB2, pode ignorar, pois isso é devido meu ambiente ser desenvolvido em DB2 (O que danado é DB2 não é? Em outra postagem posso explicar, mas é um SGBD).


Faça então sua modelagem normalmente, classes, entities etc...

Na sua classe DAO o retorno da base utilize tipo ArrayList. Crie sua classe serviço como abaixo:


package DAO;
import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;import java.util.ArrayList;
import entities.Cliente;import util.ConnectionDB2;
public class ClienteDAO {
private static ClienteDAO instanciaUnica = new ClienteDAO(); public static ClienteDAO getInstance() { return instanciaUnica; } public ArrayList<Cliente> listarClientes() { ArrayList<Cliente> clientes = new ArrayList<Cliente>();
/*   àrea comentada para uso em testes

Cliente cliente = new Cliente(); cliente.setNome("teste0"); clientes.add(cliente);  Cliente cliente1 = new Cliente(); cliente1.setNome("teste1"); clientes.add(cliente1);  Cliente cliente2 = new Cliente(); cliente2.setNome("teste2"); clientes.add(cliente2);  Cliente cliente3 = new Cliente(); cliente3.setNome("teste3"); clientes.add(cliente3);  */
try {
Connection conn = ConnectionDB2.getConnection(); Statement statement = conn.createStatement();
// coloque o select de acordo com seu banco e o que deseja receber
                      String sql = "SELECT * FROM SEUBANCO.CLIENTES fetch first 10 rows only";
ResultSet result = statement.executeQuery(sql);
while (result.next()) { Cliente cliente = new Cliente(); cliente.setCod(result.getInt("COD")); cliente.setCgc(result.getString("CGC")); cliente.setNome(result.getString("NOME")); clientes.add(cliente);
}

} catch (Exception e) {
System.err.println(e.getMessage()); return null; }
return clientes; }
}

No código acima, caso não possua um banco em funcionamento, basta comentar a parte que trata de banco e descomentar a parte que utiliza um arraylist para simular e poder testar.


Agora o grande segredo da humanidade:

A classe de serviço é aquela que será utilizada pelo rest para "servir" as informações de seu webservice.


package servico;
import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;
import com.google.gson.Gson;
import DAO.ClienteDAO;import entities.RetornoClienteRest;
@Path("/cliente")public class ServiceCliente {
@GET @Path("/listarTodos") @Produces({MediaType.APPLICATION_JSON}) public String listarTodos() { RetornoClienteRest retorno = new RetornoClienteRest(); retorno.setMensagemRetorno("sucesso"); retorno.setCodigoRetorno(0); retorno.setListaClientesRetorno((ClienteDAO.getInstance().listarClientes())); return new Gson().toJson(retorno); }
}

Lembra-se lá em cima no pom.xml? Tem uma entrada de dependencia do Gson

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.0</version>
</dependency>


Este cara que faz  mágica. Caso esse código não dê certo para você, faça uma busca no site: https://mvnrepository.com/ nele você encontra tudo, ou quase tudo, por exemplo resolvi um problema intrigante com o DB2 que quando estava utilizando a biblioteca jdbc que vem no próprio client causa erro no retorno de certas strings, mas resolvi importando dependência pelo maven.


Adapte a função listarTodos() de acordo com seu ambiente, no meu caso criei  uma classe RetornoClienteRest que possui atributos:

codigoRetorno -> indica um codigo de retorno para depuração, ajuda na modelagem e identificar se foi tudo ok ou se houve problemas
mensagemRetorno -> diz" Sucesso", ou "Foi mal" se colocar alguma condição, vai depender do que queira.

Por fim ListaClienteRetorno, é o bendito ArrayList que demorei tanto a retornar, o Rest não tem muito amor pelo array, então deu muito trabalho resolver buscando muita dica e código pela internet. Não encontrei o post de forum onde consegui essa dica, quando encontrar novamente colocarei o link para referenciar. Quiz logo documentar o fato e compartilhar, pois tirou um pouco o juízo. Quando se está ainda aprendendo muita coisa demora a sair, mas à medida que vai apanhando as coisas fluem.

Ressalvas: 
* Não garanto que os códigos postados funcionem em seu ambiente, adaptações podem ser necessárias, para isso que estamos Java não é?

* Buscando pela internet diversas soluções podem resolver o problema relatado, mas esta fois a mais fácil, menos traumática sem alterar muito meu projeto, e também foi a mais didática levando em consideração meu nível de conhecimento.

* Nada vem de graça, mas o retorno é grande. Se eu não tivesse pesquisado não teria efetivamente entendido o funcionamento do processo, de como vem e retornam informações. Com isso várias idéias e projetos vem a mente pra por em prática. Pense nisso quando for apenas copiar e colar.


Comentários