sábado, 6 de febrero de 2016

Elegir IaaS, PaaS, SaaS o un Shared Hosting

A lo largo del tiempo al desarrollar una aplicación web, una de las preguntas iniciales era con que lenguaje, tecnología y base de datos íbamos a desarrollarlo, en base a estos parámetros escogíamos un hosting y uno de los planes que mas convenía también en cuanto a economía, rendimiento, capacidad de almacenamiento y demás características.

El alojamiento compartido actualmente se ha vuelto horrible, pues en algunos casos el plan original que teníamos ya se encuentra inactivo por lo cual la empresa proveedora pide que migremos a un nuevo plan pero a mayor costo, esto también debido a que a lo largo del tiempo nuestros aplicativos consumen mas espacio en disco y por lo tanto también en memoria.

El hosting compartido (Shared hosting) es una tecnología antigua que quizá con el tiempo deje atrás (Si, aun conservo uno). Lidiar con un hosting compartido a veces es complicado, no se lo deseo ni a mis enemigos.

Un problema del hosting compartido es por ejemplo hacer que soporte instancias de Node.js, si nosotros usáramos un PaaS por ejemplo Heroku, Nodejitsu o Modulus esto es simple, pero instalar una instancia de Node.js en un hosting compartido a veces no es posible.



Actualmente contamos con alternativas al hosting compartido como son IaaS, PaaS y SaaS.

IaaS (Infraestructura como servicio):  se refiere a la tercerización de los equipos utilizados para apoyar las operaciones, incluido el almacenamiento, hardware, servidores y componentes de red. Ejemplo: DigitalOcean

PaaS (Plataforma como servicio): es un conjunto de utilitarios para abastecer al usuario de sistemas operativos y servicios asociados a través de Internet sin necesidad de descargas o instalación alguna. Ejemplo: OpenShift

SaaS (Software como servicio): es un modelo de distribución en el que las aplicaciones están alojadas por un proveedor de servicio y puestas a disposición de los usuarios a través de Internet. Ejemplo: Temboo

Entonces cual usar?. Pues para obtener la respuesta debes evaluar grado de libertad que necesites, si vas a tener uno o muchos clientes alojados, la tecnología o tecnologías que usaras para el desarrollo de tus aplicaciones así como la base de datos o bases de datos que necesites, la magnitud de transferencia, almacenamiento necesario y finalmente tus habilidades, por ejemplo si vas a contratar un IaaS el cual esta sobre un servidor CentOS y no tienes la mas remota idea de linux pues es evidente que no es la mejor opción para usted.

En cuanto a seguridad, en cada una de las tecnologías en la nube disponibles debe quedar claro que hay una responsabilidad compartida entre el usuario y el proveedor del servicio las cuales se muestran en el siguiente gráfico tomado de IEEE (click en la imagen para ampliar):


viernes, 22 de enero de 2016

Construir un formulario file upload arrastrable con DropzoneJs y PHP

DropzoneJS es una librería open source que permite subir archivos de manera drag and drop y pre-visualizando las imágenes. Es una buena opción al no depender de JQuery.



En este tutorial, construiremos un file upload múltiple usando DropzoneJS, mientras que nuestro backend será soportado por el lenguaje PHP. En mi caso utilizare WAMP Server.

La estructura de nuestro proyecto será la siguiente:



El archivo dropzone.js es la libreria javascript principal.
El archivo index.php es el formulario en el que se arrastran las imágenes para subirlas a la carpeta uploads que se encuentra dentro del proyecto.
El archivo upload.php es el archivo backend que soporta la subida de archivos internamente.
Dentro de la carpeta css están los archivos de estilos dropzone.css y style.css en caso de dar un poco de diseño al formulario.
Dentro de la carpeta uploads se almacenará los archivos una vez arrastrados al formulario de subida.

Pueden bajar el proyecto completo del siguiente enlace del Google Drive: Descargar Proyecto.

Una vez entendido esto bajamos el archivo zip, descomprimimos y copiamos toda la carpeta dropuploadonly al directorio www del WAMP Server por defecto la ruta es C:\wamp\www\ en caso no usemos wamp podemos buscar la carpeta www del apache.

Para probar abrimos el navegador y entramos a la dirección http://localhost/dropuploadonly/index.php

Al arrastrar un archivo podemos darnos cuenta que se almacena automáticamente en la ruta C:\wamp\www\dropuploadonly\uploads

En caso de requerir la pre-visualización de los archivos ya existentes en la carpeta almacén de archivos pueden bajar del Google Drive: Este otro proyecto, la estructura es la misma del ejemplo básico solo la carpeta tiene otro nombre (dropsample), a fin de no afectar al ejemplo básico.

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.

viernes, 20 de junio de 2014

Conversión de archivos PDF y WORD a fragmentos en TXT en Java

Este mes estuve trabajando en una librería customizada en java la cual debía convertir ciertos documentos, algunos con extensión PDF y otros en WORD (.doc), en archivos de texto plano TXT, aparte de esta tarea se requería fragmentar los archivos TXT según ciertos indicadores de corte (TOKENS).



Todo este proceso aparentemente sin sentido era necesario pues existe una arquitectura de búsqueda de IBM denominada Content Analytics que realiza la tarea de una manera mas óptima y para lo cual requiere la fragmentación.



La parte de extracción de texto plano ,la desarrolle basandome en las siguientes API's: para PDF use iText (anteriormente denominada lowagie) y para WORD use Apache POI. Añadí finalmente un archivo de configuración (config.properties) en donde se especifica una ruta de entrada para PDF, una ruta de entrada para WORD y una sola ruta de exportación para ambos, aparte también añadí un vector de tokens para PDF separado por comas y otro vector de tokens para WORD, también separado por comas.Existen en la solución dos archivos demo.java uno es para PDF y otro es para WORD. Espero les sirva, les dejo aquí el link del drive, hasta la próxima!


lunes, 2 de junio de 2014

Eliminar sesiones bloqueantes en Oracle

En estos días tuve que lidiar con ciertos procesos en lote que al fallar causaban bloqueos en tiempo de ejecución debido a la falta de un commit o rollback dependiendo del punto de vista claro. A continuación dejo un script que me fue útil para revertir tales bloqueos teniendo en cuenta que se conoce a priori el nombre de la tabla bloqueada involucrada.




           
--1. Obtener el o los ID's del objeto tabla probablemente bloqueado:

SELECT object_id FROM dba_objects WHERE object_name='USUARIO';

--2. Obtener los valores SID para el o los ID's recuperados en el paso 1:

SELECT sid FROM v$lock WHERE id1 IN (74590,75456) 

--3. Obtener los valores de sesion usando los SID's recuperados en el paso 2:

SELECT sid, serial# from v$session where sid in (67,72,131,132,198,11)

--4. Matar sesiones bloqueantes en la tabla usando pares 'sid,serial#' del paso 3:

ALTER SYSTEM KILL SESSION '11,1202'
ALTER SYSTEM KILL SESSION '67,2405'
ALTER SYSTEM KILL SESSION '72,972'
ALTER SYSTEM KILL SESSION '131,1847'
ALTER SYSTEM KILL SESSION '132,1598'
ALTER SYSTEM KILL SESSION '198,16041'


Espero les sea de utilidad.

sábado, 24 de mayo de 2014

Obtener el IP cliente con java en un esquema HA, con proxy o balanceador de carga

Eventualmente, se puede usar el comando servletRequest.getRemoteAddr() para recuperar la direccion IP del cliente que accede a nuestra aplicación java web de la siguiente manera:

 
   String ipAddress = request.getRemoteAddr();


Pero, si el usuario se conecta via un servidor proxy (ya sea de software o hardware) o en un esquema de alta disponibilidad considerando un balanceador de carga, el código original devolvera el ip del balanceador, router o proxy, no el ip del cliente original conectado.



Para resolver este problema, se debe recuperar la direccion IP del encabezado de la peticion HTTP mas conocida como “X-Forwarded-For (XFF)“ De la siguiente manera:

            
   //el cliente esta conectandose a traves de algun otro equipo?
   String ipAddress = request.getHeader("X-FORWARDED-FOR");  
   if (ipAddress == null) {  
    ipAddress = request.getRemoteAddr();  
   }


Hasta la próxima!

jueves, 22 de mayo de 2014

Configurar Jasper Reports 5 en JBoss EAP como módulo

En esta última semana tuve que resolver un problema de dependencia para poder usar el componente Jasper Reports 5 en el servidor JBoss EAP 6 instalado en Red Hat, en mi escenario ya estaba configurado el jasper como modulo sin embargo se usaba una versión anterior a la requerida por mi aplicación (específicamente la 3) lo cual desencadenaba errores al querer ejecutar los reportes del nuevo site. Por lo cual procedí a modificar la carpeta del módulo anterior ya configurado a fin de elevar la version del Jasper, primero se debe bajar el servicio del jboss con el comando en la terminal service jboss-as stop como root claro despues localize la carpeta del módulo del jasper en la siguiente ubicación /opt/jboss6/jboss-eap-6.0/modules/JasperReport3/main/


Copie todos los archivos jar necesarios en la carpeta main antes descrita a fin de que pueda levantar el Jasper Reports 5, la carpeta quedo con los siguientes archivos (dar click en la imagen para ampliar):


Luego de copiar los archivos antes descritos se debe modificar el archivo module.xml que es finalmente en el que se configuran las dependencias en los JAR del módulo, evidentemente antes en este archivo se encontraba direccionado el jar del Jasper Reports 3 y sus dependencias por lo cual solo tuve que actualizar este documento ahora referenciando a los nuevos componentes del Jasper Reports 5 copiados anteriormente.


Luego de modificar y guardar el archivo module.xml iniciamos nuevamente el servicio con el comando en la terminal service jboss-as start como root y ya podemos usar el Jasper Reports 5 en nuestro servidor.

Si desean bajar la carpeta main completa la dejo comprimida en el siguiente enlace del drive. Espero les sea de ayuda. Hasta la próxima!