jueves, 21 de enero de 2016

Crear Servicios Rest en JAVA y Habilitar CORS

JSON es un formato de datos usado para intercambiar información entre aplicaciones web (por lo general usado en Servicios REST, aclarar que no es el único formato usado).



Un ejemplo del uso de JSON es el siguiente:

{
 "data1":4444,

 "data2":"hola mundo rest",

 "list":["Willy","Arturo","Tom","Tony","Carlos","Roque","Feri"]
}

JSON fue diseñado inicialmente para compartir datos en el mismo dominio, esto para prevenir posibles ataques y reducir la vulnerabilidad, entonces como hacer si necesitas comunicar dos websites en distintos dominios usando este formato de intercambio de datos?

JSONP fue desarrollado para resolver esto. JSONP se ve enteramente como un  JSON, incluso en el inicio de su nombre. Un ejemplo de JSONP se da cuando añadimos un nombre de función, en el ejemplo "callback", lo cual hace que el json se convierta en una función javascript, la cual al importarla es posible usar de la siguiente manera:


callback(
{
 "data1":4444,

 "data2":"hola mundo rest",

 "list":["Willy","Arturo","Tom","Tony","Carlos","Roque","Feri"]
});

Existe una manera mas sencilla de resolver esto y es habilitar CORS en la respuesta del web service rest, como en nuestro caso usamos el lenguaje JAVA, la manera de hacer esto es añadiendo las siguientes lineas al servlet.

response.addHeader("Access-Control-Allow-Origin", "*");

response.addHeader("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS, DELETE");

response.addHeader("Access-Control-Allow-Headers", "Content-Type");

response.addHeader("Access-Control-Max-Age", "86400");

De esta forma evitamos el problema crossdomain que comentábamos al inicio. Una vez entendido esto procedemos a crear nuestra solución.

En mi caso use NetBeans IDE 8.1 con JDK 7 y Glassfish Server 4.1.1, sin embargo esto no es limitante, creamos un Nuevo Proyecto del Tipo Java Web/Web Application, añadimos la librería gson-1.7.1.jar a las dependencias.

Para emular el servicio de datos creamos una clase POJO simple denominada objeto.java de la siguiente manera

package pe.globalhub.rest;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author wcastro
 */

public class objeto {
   
    private int data1 = 4444;

    private String data2 = "hola mundo rest";

    private List list = new ArrayList() {
      {
            add("Willy");
            add("Arturo");
            add("Tom");
            add("Tony");
            add("Carlos");
            add("Roque");
            add("Feri");
      }
    };       

    /**
     * @return the data1
     */

    public int getData1() {
        return data1;
    }

    /**
     * @param data1 the data1 to set
     */

    public void setData1(int data1) {
        this.data1 = data1;
    }

    /**
     * @return the data2
     */
    public String getData2() {
        return data2;
    }

    /**
     * @param data2 the data2 to set
     */
    public void setData2(String data2) {
        this.data2 = data2;
    }

    /**
     * @return the list
     */
    public List getList() {
        return list;
    }

    /**
     * @param list the list to set
     */
    public void setList(List list) {
        this.list = list;
    }
  
    @Override
    public String toString() {
       return "DataObject [data1=" + getData1() + ", data2=" + getData2() + ", list="
            + getList() + "]";
    }

}

Añadimos ahora un servlet denominado restServlet.java el cual publicará nuestro objeto en formato JSON:

package pe.globalhub.rest;

import com.google.gson.Gson;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 *
 * @author wcastro
 */

public class restServlet extends HttpServlet {

    /**
     * Processes requests for both HTTP GET and POST
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
       
        String tipo=request.getParameter("salida");
        boolean encapsularJS=false;

        if(tipo!=null)
        {
            if("application/json".equalsIgnoreCase(tipo))
            {
                encapsularJS=false;
            }
            else if("application/javascript".equalsIgnoreCase(tipo))
            {
                encapsularJS=true;
            }
        }
        else
        {//por defecto la salida es application/json
            tipo="application/json";
            encapsularJS=false;
        }

        response.setContentType(tipo+";charset=UTF-8");     

        //enable CORS in java servlet
       response.addHeader("Access-Control-Allow-Origin", "*");
       response.addHeader("Access-Control-Allow-Methods", "GET, PUT, POST, OPTIONS, DELETE");
       response.addHeader("Access-Control-Allow-Headers", "Content-Type");
       response.addHeader("Access-Control-Max-Age", "86400");
        //end enable CORS in java servlet

        try (PrintWriter out = response.getWriter()) {           

        objeto obj = new objeto();
 Gson gson = new Gson();
        String json = gson.toJson(obj);
        if(encapsularJS)
        {
            out.println("callback("+json+");");            
        }
        else
        {
            out.println(json);
        }                  
        }
    }

    // 

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }// 

}

Por último hacemos una interfaz de usuario en donde mostrar los datos recuperados del web service rest, en este caso usaremos jquery ui en un archivo jsp llamado userinterfacecross.jsp para poder consumir el servlet de la siguiente manera:

var url="http://10.1.50.41:8080/RestService/restServlet?salida=application/json";
 $.get(url , function( data ) { 
  var str="Resultados";
  var aResult=new Array();
  aResult=data.list;
  for (var i = 0; i < aResult.length; i++) {
   var array_element = aResult[i];
   str+="Elemento "+(i+1)+": "+array_element;
  }    
  $( "#result" ).html(str);
  }, "json" );

Aclarar que una vez descargado el proyecto deben cambiar la IP 10.1.50.41 y el puerto 8080 en el archivo userinterfacecross.jsp por los datos de su máquina antes de dar run file.

A continuación les dejo el enlace de Google Drive del proyecto finalizado Descargar Proyecto.

No hay comentarios:

Publicar un comentario