sexta-feira, 14 de novembro de 2014

Habilitar CORS para acessar serviços REST

Uma vez que implementamos e disponibilizamos o serviço Restfull, precisamos definir qual domínio pode ter acesso a este serviço. Os navegadores possuem uma segurança que não permitem arquivos javascript acessarem serviços externos via http, os chamados CORS (Cross-Origin Resource Sharing). 
Se tentarmos acessar um serviço sem habilitá-lo, nos deparamos com esta mensagem:



Precisamos habilitar o CORS em nosso servidor, resumindo precisamos seguir 2 passos:
  1. Escrever um header para retorno da resposta http em um filtro.
  2. Mapear na aplicação (web.xml) este filtro.
(obs: utilizando java servlet)

1) O filtro com habilitando o CORS.
public class SimpleCORSFilter implements Filter{
 @Override
 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  HttpServletResponse response = (HttpServletResponse) res;
  response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(req, res);
 }

 @Override
 public void destroy() {
 }

 @Override
 public void init(FilterConfig arg0) throws ServletException {
 }
}

Explicando...
response.setHeader("Access-Control-Allow-Origin", "*");
Neste trecho definimos permissão para qualquer (*) domínio acessar nosso serviço!

2) Mapendo filtro na aplicação

 simpleCORSFilter
  br.com.adriano.filter.SimpleCORSFilter 



     simpleCORSFilter
     /*

Com apenas isso, seu serviço está disponível para ser utilizado!

quarta-feira, 12 de novembro de 2014

REST + Jersey + JSON

Hoje vamos criar um projeto com API Rest que retorne uma lista de objetos como JSON. Uma das principais dificuldades que encontrei ao criar um projeto sem o Maven, foi encontrar os jars para o retorno do json.
Existem diversos posts com exemplos de utilização de Rest na internet bem simples, porém apenas com os jars recomendado não consegui retornar via json, apenas xml. O grande segredo está nos jars jackson. Então vamos lá...

Crie um Dynamic Web Project no Eclipse:
Minha estrutura ficou assim:


Os jars necessários para aplicação funcionar estão aí. No meu caso, utilizei o servidor Weblogic, mas poderia ser o Tomcat, por exemplo.

web.xml 
  LaboratorioRest
  
  
   RestController
   com.sun.jersey.spi.container.servlet.ServletContainer
   
    com.sun.jersey.config.property.packages
    br.com.adriano.rest
   
   
  com.sun.jersey.api.json.POJOMappingFeature
  true
 
  
  
  
   RestController
   /*
  
  

Entendendo...

Definimos um nome para servlet para garantir acesso a API Rest.
RestController
com.sun.jersey.spi.container.servlet.ServletContainer
Definimos um parâmetro para dizer qual package vai conter os serviços Rest.

    com.sun.jersey.config.property.packages
    br.com.adriano.rest

Outro parâmetro necessário para o Jersey converter o objeto em JSON.

 com.sun.jersey.api.json.POJOMappingFeature
 true

Usuario.java
package br.com.adriano.model;
import javax.xml.bind.annotation.*;
public class Usuario {
 
 private String login;
 private String senha;
 public String getLogin() {
  return login;
 }
 public void setLogin(String login) {
  this.login = login;
 }
 public String getSenha() {
  return senha;
 }
 public void setSenha(String senha) {
  this.senha = senha;
 }
 
 @Override
 public String toString() {
  return super.toString();
 }
}

Caso queira retornar XML, você deve anotar @XmlRootElement na classe Usuario. Para Json não é necessário.

UsuarioResource.java
package br.com.adriano.rest;
import java.util.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import br.com.adriano.model.*;
@Path("/usuarios")
public class UsuarioResouce {
 static private Map usuarioMap;
 static {
  usuarioMap = new HashMap();
  Usuario usuario1 = new Usuario();
  usuario1.setLogin("admin");
  usuario1.setSenha("passAdmin");
  usuarioMap.put(1, usuario1);
  Usuario usuario2 = new Usuario();
  usuario2.setLogin("adriano");
  usuario2.setSenha("adr123");
  usuarioMap.put(2, usuario2);
 }
 @GET
 @Path("/json")
 @Produces(MediaType.APPLICATION_JSON)
 public List getUsuarios() {
  return new ArrayList(usuarioMap.values());
 }
}
Entendendo...
@Path é o caminho que será acessado pela url para chegar até nossa classe UsuarioResource.
@Path("/usuarios")
public class UsuarioResouce 

Criei uma massa de dados como teste apenas para emular dados vindo do banco. 
static private Map usuarioMap;
 static {
  usuarioMap = new HashMap();
  Usuario usuario1 = new Usuario();
  usuario1.setLogin("admin");
  usuario1.setSenha("passAdmin");
  usuarioMap.put(1, usuario1);
  Usuario usuario2 = new Usuario();
  usuario2.setLogin("adriano");
  usuario2.setSenha("adr123");
  usuarioMap.put(2, usuario2);
 }

@Produces - Definimos o tipo de retorno de dados que queremos, no caso, JSON. (Caso queria XML utilize ("text/xml").        
 @GET
 @Path("/json")
 @Produces(MediaType.APPLICATION_JSON)
 public List getUsuarios() {
  return new ArrayList(usuarioMap.values());
 }

A partir daí, podemos subir a aplicação. Abra o browser e digite o caminho da url do seu projeto. No meu caso foi http://localhost:7001/LaboratorioRest/usuarios/json. Deve aparecer a lista do objeto Usuario em JSON. 
[{"login":"admin","senha":"passAdmin"},{"login":"adriano","senha":"adr123"}]



Bom, é isso! Sem os jars 'jackson' a página não retornava o json. Espero ter ajudado.

Código disponível em: https://github.com/adrianonegrao/angular-js pasta lab-rest.

[]s