miércoles, marzo 25, 2015

Enviar y recibir informacion via HTTP desde y hacia objetos Genexus

Tradicionalmente se focaliza este tipo de soluciones de integracion a generar servicios web SOAP y RestFull, que de muchas maneras soluciona la problema de integracion, pero al mismo tiempo por la diversidad de IDEs que se utiliza para su desarrollo, dificulta el proceso de mantenimiento o mejoras, ya sea por un tema propio de los servicios web SOAP o por el incremento y mejoras a las librerias que soportan los servicios web restfull.

Estuve por algunos dias con muchas dificultades en poner a punto unos servicios web restfull que habia generado con las versiones anteriores de Jersey, debido a que tenia que migrar hacia un nuevo servidor de aplicacion tipo WebProfile o FullProfile, intente inicialmente migrar hacia Jboss y resulta complicado el proceso, ya que dichas servicios dejaron de funcionar, en base algunas consultas en la web por medio del Google, se pudo detectar que uno debe hacer una configuracion especial para tener la posibilidad de utilizar las mismas versiones de los jar que sirve para los servicios web restfull y que son utilizados por Genexus especialmente las ultimas versiones GxEvo1 GxEvo2 GxEvo3.

Estos servicios web restfull fueron generados con el IDE Eclipse Luna, con jdk1.6 y Tomcat7.

Se intento utilizar otro IDE como es el caso del NETBEANS 7.x pero se encontro con el mismo problema debido a que la nueva version de Jersey es full compatible con la version Jdk1.7 y Jdk1.8, ademas que incluye ciertas configuraciones propias de la version, lo que limitaba en sumo grado la migracion.

En virtud de ello se procedio a investigar como hacer un proceso de transferencia de informacion desde y hacia objetos Genexus generados principalmente con el Generador Java.

Existe ejemplos en el WIKI de Genexus donde evidencia la facilidad de intercambiar informacion entre dos objetos mediante solo la utilización de http y con xml, en virtud de ello reproduzco dicha solucion que fueron creados para el ejemplo en la misma KB.

1.- Consumidor de informacion, en el caso se crea un procedimiento con la propiedad de CALL PROTOCOL seteada a HTTP, cuyo comportamiento seria de EMISOR.

No hace uso de los parametros, simplemente se tiene que crear las siguientes variables:
//&HttpClien de tipo HttpClient
//&XmlWriter de tipo XMLWriter
//&XmlReader de tipo XMLReader
&DatoUno = 888 (Númericos)
&DatoDos = 999  (Númericos)


// Determino el host y el puerto a donde hacer el request

 

&HttpClient.host = "localhost"
&HttpClient.port = 8080
&HttpClient.BaseUrl = '/carpetaplicacion/'
 

// Agrego el XML al request, con valores  iniciales
 

&XmlWriter.openRequest(&HttpClient)
&XmlWriter.WriteStartElement("parametros")
&XmlWriter.WriteElement("a", &DatoUno)
&XmlWriter.WriteElement("b", &DatoDos)
&XmlWriter.WriteEndElement()
&XmlWriter.close()


          // Ejecuto el GET al webproc
 

&HttpClient.execute("GET", "gxobjeto")  // Procedimiento con Call Protocol = HTTP.
&EstatusCode    = &HttpClient.StatusCode
&Resultado = &HttpClient.ToString()


// Se procede a la lectura del XML que devuelve via HTTP con los nuevos valores a las variables

&XmlReader.openResponse(&HttpClient)
&XmlReader.read()
&XmlReader.read()
&DatoUno = Val(&XmlReader.value)
&XmlReader.read()  
&DatoDos = val(&XmlReader.value)
&XmlReader.close()
Return


2.- Procedimiento Gx Emisor. ( en mi caso gxobjeto, referencia en el punto 1)

Se debe crear las siguientes variables:
//&HttpRequest de tipo HttpRequest
//&HttpResponse de tipo HttpResponse
//&XmlWriter de tipo XMLWriter
//&XmlReader de tipo XMLReader

// &DatoUno numerico
// &DatoDos numerico
 

          // Leo los parámetros del XML
 

&XmlReader.openRequest(&HttpRequest)
&XmlReader.read()
&XmlReader.read()
&DatoUno = Val(&XmlReader.value)
&XmlReader.read()  
&DatoDos = Val(&XmlReader.value)
&XmlReader.close()

// Ejecuto algunas modificaciones a las variables

&DatoUno = &DatoUno + 1
&DatoDos = &DatoDos + 10
     
      // Registro los datos modificados en el response


&XmlWriter.openResponse(&HttpResponse)
&XmlWriter.WriteStartElement("parameters")
&XmlWriter.WriteElement("a", &DatoUno)
&XmlWriter.WriteElement("b", &DatoDos)
&XmlWriter.WriteEndElement()
&XmlWriter.close()
Return


Esto resulta una simple forma de intercambiar informacion entre dos aplicaciones o KB, generadas por Genexus, sin recurrir a los tipicos procesos de inspeccion tanto para WSDL y WADL .

3.- En el siguiente punto vamos a utilizar un servlet generado con Eclipse, el mismo que invocara a un procedimiento creado en genexus, para enviar y recibir información.

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;

public class EnviaryRecibirDatosConGET_A_Genexus
{
     private final static String USER_AGENT = "Mozilla/5.0";
  
    // Metodo pricnipal
    public static void main(String[] args) throws Exception
    {
        EnviaryRecibirDatosConGET_A_Genexus http = new EnviaryRecibirDatosConGET_A_Genexus();
         System.out.println("Proceso de prueba con el METODO GET EN HTTP");
        http.EnviarPorGet();
    }

    // Enviar Datos y receptar respuesta con el metodo get invocando un OBJETO GENEXUS.
    // Metodo para Enviar y Recibir datos por medio de GET HTTP

    private void EnviarPorGet() throws Exception
    {
         String url     = "http://localhost:8080/aplicacion/servlet/gxobjeto";
         URL laUrl     = new URL(url);
        HttpURLConnection conexion = (HttpURLConnection) laUrl.openConnection();
      
        // Asignar por omision el metodo GET
        conexion.setRequestMethod("GET");

        //adicionar al request header el agente
        conexion.setRequestProperty("User-Agent", USER_AGENT);

        conexion.setDoOutput(true);
        DataOutputStream grabaXml = new DataOutputStream(conexion.getOutputStream());
        // Escribir el XML
        grabaXml.writeBytes("<parametros>");
        grabaXml.writeBytes("        <DatoUno>77</DatoUno>");
        grabaXml.writeBytes("        <DatoDos>34</DatoDos>");
        grabaXml.writeBytes("</parametros>");  
        grabaXml.flush();
        grabaXml.close();
      
        int estatusCode = conexcion.getResponseCode();
        System.out.println("\nEnviando 'GET' request al URL : " + url);
        System.out.println("\EstatusCode : " + estatusCode);

        BufferedReader entrada = new BufferedReader(new InputStreamReader(conexion.getInputStream()));
        String lineaDatos;
        StringBuffer retorno = new StringBuffer();

        while ((lineaDatos = entrada.readLine()) != null)
        {
            retorno.append(lineaDatos);
            System.out.println(lineaDatos);
        }
        entrada.close();
 
        //Imprimir en Consola el Resultado de la consulta

        System.out.println(retorno.toString());
     }
 }
 

Se desplegaran datos en consola indicando como quedaron las variables respectivas.

4.- Servlet para intercambia información con  Genexus, mediante el metodo POST del HTTP.



3 comentarios:

Pablo Dante dijo...

Hola buen día
Estoy por hacer algo parecido a los dos Ejemplos primeros que describe.
Si bien son dos Procedimientos en Genexus.
Para ver o cotejar si funcionan los llamo desde un Web Panel?
Digo para ver los resultados de StatusCode o del ToString(); por ejemplo.
No sé mucho de el tipo de datos HTTP por eso si mi pregunta es muy trivial, me disculpo.
Un saludo cordial.

Mauricio dijo...

Hola,

Estoy haciendo el ejemplo y no me lee los datos de xml de respuesta.
La respuesta que me da es:

0OK – TED Obtenido correctamentePFRF
L1RFRD4=

Pero con la lectura que comentas no me devuelve ningún dato, esto lo hago de la siguiente forma:

&XmlReader.openResponse(&HttpClient)
&XmlReader.read()
&XmlReader.read()
&XmlReader.read()
&DatoUno = &XmlReader.value
&XmlReader.read()
&DatoDos = &XmlReader.value
&XmlReader.read()
&DatoTres = &XmlReader.value
&XmlReader.close()

Me puedes indicar que estoy haciendo mal por favor.
En el fondo saber como puedo leer los datos que me devuelve el servicio, la respuesta la tengo pero no puedo leerla.

Saludos cordiales.
MAHG.

Mauricio dijo...

Al final logre capturar os valores de la siguiente forma:

&XmlReader.openResponse(&HttpClient)
&XMLReader.ReadType(1,"TAG1 SERVICIO")
&DatoUno = &XMLReader.Value
&XMLReader.ReadType(1,"TAG2 SERVICIO")
&DatoDos = &XMLReader.Value
&XMLReader.ReadType(1,"TAG3 SERVICIO")
&DatoTres = &XMLReader.Value
&XMLReader.Close()