lunes, abril 28, 2014

Configurando Eclipse con MAVEN



Creación de un WebService desde Cero con CXF y Maven

Introducción
En la presente guía construiremos un Web Service básico desde cero, utilizando Maven y un framework open source para la construcción de servicios: Apache CXF.
CXF se para sobre el estándar de Java para Web Services: JAX-WS, que, a su vez, hace uso de otros estándares, como, por ejemplo, JAXB para el proceso de Binding (la asociación entre una clase Java y su correspondiente definición en el XML de los mensajes a transmitir).
Como siempre, podemos utilizar directamente JAX-WS para nuestros servicios web (como también podríamos usar JDBC si quisiéramos acceder a una base de datos en la forma más básica, o la especificación de Servlets/JSP para crear aplicaciones web), sin embargo CXF nos facilita varias cuestiones, y está integrado con otros Frameworks, como Spring, que mencionaremos en apartados posteriores, y que aceleran procesos tediosos, como la publicación y la generación de clientes.
Para realizar la guía necesitaremos una instalación activa de Maven en nuestra máquina, emplearemos Eclipse como IDE y Apache Tomcat, como Web Server.
A su vez, se sugiere tener instalado el plugin de Maven: m2Eclipse, ya que facilitará muchas de las acciones que llevemos a cabo por medio de esta herramienta.

En esta URL recuperamos donde esta el repositorio de MAVEN
http://eclipse.org/m2e/download/






Installing Apache CXF in Eclipse

Paso 1: Descargar y descomprima la ultima version de CXF.
Paso 2: Inicie Eclipse -> abrir Window -> Preferences
Paso 3: Ubique y expanda “Web Services” del menu izquierdo -> Seleccione “CXF 2.x “Preferences”
Step 4: Click en el boton Add
Step 5: Revisar la carpeta donde se ubica CXF para asignar “CXF Home”, este asigna automaticamente la “Version” and “Type”, luego damos click en “Finish”
Step 6: Check the check-box for CXF version
Step 7: Go to other tabs and check that the tabs are not empty, if step 5 is not done then all the tabs will remain empty
Step 8: Click OK, the installation is done

Update Sites


Latest m2e release (recommended)

http://download.eclipse.org/technology/m2e/releases   

En el ECLIPSE, seleccionamos HELP, INSTALL NEW SOFTWARE, click boton ADD, colocamos un nombre pueder: MAVEN , en la URL :
http://download.eclipse.org/technology/m2e/releases 
Click en el boton Select All.
Luego click boton Next y Finish.

Esperar que se actualice y reiniciar el ECLIPSE.

Aqui tenemos otro tutorial de como realizar un servicio web con CXF.
Tutorial para configurar ECLIPSE Y CXF, practica crear un servicio web



 Servicio web con CXF utilizando Maven.

Que es CXF:

Apache CXF is an open source, fully featured Web services framework, its name CXF is originated from two projects (Celtix and XFire) combined work together to Apache. CXF supports JAX-WS, Binding, DataBinding and Transport implementation, the nice feature is its embeddable Web service component.

We look though a step-by-step configuration for maven, tomcate with CXF to start the first web service project.

We will basically go through the following steps:
1) Download and install the required tools.
2) How do I configure Eclipse to develop and run web services with maven?
3) Develop a simple Hello World Web Service?
4) How to deploy your Web Service?
5) How to test your Web Service?


Download and install the required tools.


1) JDK ( Click Here) Download the latest version of JDK.
2) Apache Tomcat ( Click Here ) Download Binary Distributions ZIP.
3) Maven ( Click Here ) Download LINK (Binary zip).
4) Apache CXF ( Click Here ) Download FILE (Binary distribution) ZIP.
5) Eclipse IDE for Java EE version ( Click Here )
6) Eclipse Maven Plugin.
  • Start Eclipse create new Workspace.
  • Goto HELP >> Install New Software
  • Add URL ( http://m2eclipse.sonatype.org/sites/m2e ) and check "Maven Integration for Eclipse"
  • Click on Finish.

How do I configure Eclipse to develop and run web services with maven


1) Configure Default JDK
Open Eclipse and follow below instructions

  • Goto Window >> Preference
  • Select Java >> Installed JREs
  • Click on "Add", select "Standard VM".
  • Click on "Directory" and select JDK Home path where you have installed JDK.
  • Finish >> Now select the JDK we have added recently and click on OK.


2) Configure Tomcat

  • Goto Window >> Preference
  • Select Servers >> Runtime Environments
  • Click on "Add", select "Tomcate version" you have downloaded >> Next.
  • Click on Brows and provede the home directory of Tomcate.
  • Select JDK which we recently setup in above steps.
  • Click on Finish >> OK.


3) Configure Maven Local Repository

  • Goto Window >> Preference
  • Select Maven >> User Settings
  • click on "Brows" and select "settings.xml" from conf directory of maven ( e.g. D:\apache-maven-3.0.4\conf\settings.xml).
  • Once you provide the "settings.xml" you can see the Local Repository is read only, to change the location click on "open file" link provided beside the User Settings label.
  • Now go to "settings.xml" and Un-comment the Tag localRepository and provide your own local repository, where you want all JARs will be downloaded. ( e.g. D:\MavenRepository)
  • Verify the same path in "User Settings" and click on "Update Settings". It will downlod some Jars in Local Repository.


4) Configure CXF

  • Goto Window >> Preference
  • Select Web Services >> CXF 2.x Preferences (This option will be available in Eclipse 3.6 or above)
  • Click on "Add", we have downloaded CXF so we need to "Brows" the home directory of CXF. click on OK >> Finish.
  • Select the default CXF and click on OK.


Finally I also need to configure Tomcate to use the CXF Runtime. By default tomcate uses the Axis so i need to change it to CXF.

  • Goto Window >> Preference
  • Select Web Services >> Server and Runtime
  • Change the "Web service runtime" to Apache CXF 2.x.
  • Click OK to finalize the setup.


Develop a simple Hello World Web Service with Maven Project


Lets begin, First we will create a new Maven project.


  • Goto File >> New >> Other >> Maven >> Maven Project >> Click Next.

  • In "Select project name and location" wizard, hit "Next" to continue with default values, make sure that "Create a simple project (skip archetype selection)" option is UNCHECKED.

  • In "Select an Archetype" wizard, keep default selection "All Catalogs" at the "Catalog" drop down list, After the archetypes selection area is refreshed, select the "Artifact Id" as "maven-archetype-webapp" archetype and hit Next.

  • In the "Enter a group id for the artifact" wizard, you can define the name and main package of your project. We will set the "Group Id" as "com.b4interview.ws.provider" and the "Artifact Id" as "WSProvider".

  • Hit "Finish" to exit the wizard and to create your project.


Maven will create below folder structure.

1) /src/main/java : contains source files for the application.
2) /src/test/java : contains all source files for unit tests.
3) /src/main/webapp : contains essential files for creating a valid web application. (WEB-INF/web.xml)
4) /target : contains the compiled and packaged deliverable
5) The "pom.xml" is the project object model (POM) file, that contains all project related configuration.


NOTE : In above case a new maven web project is created, but still we will not be able to deploy the same on tomcat.
There is a bit confusion here to use the same project as Eclipse web project we must add WTP facet (follow the below instruction).

  • Right click on maven project >> Build Path >> Configure Build Path...
  • Select "Project Facets" >> Convert to faceted form...
      • OR
  • Right click on maven project >> Configure >> Convert to faceted form...
  • Select "Dynamic Web Module", by selecting the same you will be able to see the link "Further configuration available...".

  • Now click on "Further configuration available..." and change the location of "Content directory" ( WebContent ) as per the maven structure.

  • Then check "CXF 2.x Web Services" in Project Facets Dialog.
  • Click OK, project structure will be as below. Now we will be able to run project as "Run on Server".



Done! You're ready for the code. Let's code for a web service provider example.

1) First we will create some base by creating Model and Exception class.

Entity.java
package com.b4interview.ws.model;

public class Entity {
private String id;
private String desc;

// getter / setter Methods.
}

GenericException.java

package com.b4interview.ws.exception;

import javax.xml.ws.WebFault;

@WebFault(name="genericException") //Indicates a generic exception that the operation/web service method can throw.
public class GenericException extends Exception {
private static final long serialVersionUID = 1L;

private GenericException(){}
public GenericException(String message){
super(message);
}
public GenericException(String message, Throwable cause){
super(message, cause);
}
}
2) Write your Service Endpoint Interface (SEI), (a java interface) that will be exposed as a webservice.

EntityService.java

package com.b4interview.ws.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.b4interview.ws.exception.GenericException;
import com.b4interview.ws.model.Entity;

@WebService //Indicates its a webservice.
public interface EntityService {

@WebMethod(operationName="getEntityData") //Indicates a webservice method.
public Entity getEntityData(@WebParam(name="id")String id) throws GenericException; //Indicates a parameter used in the operations, argument to be displayed on the WSDL.
}

3) Create a Service Implementation as a webservice.

EntityServiceImpl.java

package com.b4interview.ws.service.impl;

import javax.jws.WebService;
import com.b4interview.ws.exception.GenericException;
import com.b4interview.ws.model.Entity;
import com.b4interview.ws.service.EntityService;

@WebService(endpointInterface="com.b4interview.ws.service.EntityService", serviceName="entityService")
public class EntityServiceImpl implements EntityService {

public Entity getEntityData(String id) throws GenericException {
Entity entity = new Entity();
entity.setId("123");
entity.setDesc("Hello World, Web Services");
return entity;
}
}

4) create a beans.xml, Configuration file for a webservices.
We will create it in a new package ( com.b4interview.ws.conf ).

beans.xml


5) Finally Its time to configure web.xml for CXF.

web.xml

6) Start the server, and access http://localhost:8080/WSProvider/services
You should be able to see the list of services. by clicking on it, WSDL will be displayed.



















sábado, abril 19, 2014

Recomendaciones con UpLoadify

Para copiar archivos se debe tener las siguientes recomendaciones:

1- Cuando se archivo el archivo a donde copiar siempre debe tener el PATH completo INCLUIDO el nombre del archivo nuevo.

2.- El Tipo de Dato UploadifyOutput dispone de una propiedad TemporalFileName, es la que debemos utlizar para asignarle al Tipo de Dato FILE del Genexus, de la siguiente forma:

  &ArchivoTipoDatoGX.Source = &ArchivoTipoDatoUploadFy.TemporalFileName.

La siguiente instruccion para copiar:

&ArchivoDestino = 'c:\temporal\' + &ArchivoTipoDatoUpLoadFy.OriginalName
&ArchivoTipoDatoGX.Copy(&ArchivoDestino)

Para renombrar si ya existe:

&ArchivoOriginal = &ArchivoTipoDeDatoUploaFy.OriginalFileName
&ArchivoDestino  = &ArchivoOriginal + ".jpg")
&ArchivoTipoDatoGx.Rename(&ArchivoDestino) 



Podemos copiar a otro ubicación.
 

&ArchivoTipoDeDatoGX.Copy("c:\datos\" + &ArchivoDestino)

El  &ArchivoTipoDatoUploadFy.OriginalFileName nunca devuelve la extensión del archivo.

viernes, abril 04, 2014

Monitorear servicio web

  Es posible verificar si el SERVICIO WEB esta o no en linea, mediante este codigo en GENEXUS es posible verficiar aquello, es necesario utilizar la variable HTTPCLIENT

// Verificadon que SW esta en Linea
&HttpClient.Execute("GET", "http://miaplicacion:8080/serviciowew/servlet/consultas?wsdl")
&EstaOk  =  iif(&HttpClient.ErrCode=0, 1, 0)
// Se está ok, consummos el SW
if &WsOk
&WebService.Execute()
        Else 
             Msg(' SERVICIO WEB NO DISPONIBLE...')
endif
 
Gracias al aporte de Gabriel Mota:  gmotta86@gmail.com

miércoles, abril 02, 2014

Genexus Obtener Coordenadas

// En el evento start capturo información  para mostrar en el punto de referencia
Event Start
&datdireccion           = &empresa.EmpDireccion  // &datdireccion => variable a la que cargo 
&datinfadicional        = &empresa.EmpInfAdicional
&datinfowinlink         = &empresa.EmpInfowinLink         // url
&datpointinfowinlinkdsc = &empresa.EmpPointInfowinLinkDsc // texto para mostrar en el url al que apunta el link
&datpointinfowinimg     = &empresa.EmpUrlImgInicio // mostrar el logo
&dattelefonos           = &empresa.EmpTelefonos
&datemail               = &empresa.EmpEmail
do 'Geocod'
EndEvent

// en el sub
Sub 'Geocod'
&httpclient.Host = 'maps.google.com'
&httpclient.BaseUrl = '/maps/api/geocode/'
&postvar = 'xml?address=' + &datdireccion + '&sensor=false'  // acá uso la variable con la dirección
&httpclient.Execute('GET',&postvar)
&var = &httpclient.ToString()
&xmlreader.OpenFromString(&var)
&xmlreader.Read()
&xmlreader.ReadType(1,'lat')
&lat = &xmlreader.Value                          // obtiene latitud
&xmlreader.ReadType(1,'lng')
&long = &xmlreader.Value                  // obtiene longitud
GoogleMapControl1.Latitude = &lat
GoogleMapControl1.Longitude = &long

// utilizo las variables de latitud y longitud para marcar el punto y mostrar la información leída desde mi base de datos
&GxMapPoint.PointLat = &lat  /
&GxMapPoint.PointLong = &long
&GxMapPoint.PointInfowinTit = &datnombre
&GxMapPoint.PointInfowinDesc = &datinfadicional
&GxMapPoint.PointInfowinLink = &datinfowinlink
&GxMapPoint.PointInfowinLinkDsc = &datpointinfowinlinkdsc
&GxMapPoint.PointInfowinImg = &datpointinfowinimg 
&GxMapData.Points.Add(&GxMapPoint) 
EndSub

Consumir Servicio web bajo Https en Java


La ubicación de los certificados puede variar según la distribución de Linux.
Por ejemplo en CentOS está en: "/etc/pki/java/cacerts"
Y lo único que tenés que hacer es importar el certificado allí mediante keytool.

En otras distribuciones la ruta puede variar, he incluso podés encontrar un cacerts por instalación de Java.
Ejemplos:
/usr/lib/jvm/openjdk-1.7.0-.../security/lib/cacerts
/usr/java/openjdk-1.7.0-.../security/lib/cacerts

Pero creo que en general apuntan a usar uno centralizado como el /etc/pki/...

Consumir Servicio web bajo Https en Java

Permalink
 
Importar el certificado y manejo del almacén de certificado (keystore) en Java.
 
Este proceso consta de dos etapas: 
 
1)      Guardar el certificado del servidor en un keystore
2)      Consumir el web service indicándole a la aplicación dónde está el keystore con el certificado.
 
 
1)      Guardando el certificado del servidor en un keystore
 
En primera instancia, es necesario esclarecer que para poder comunicarse con un recurso bajo https es necesario tener instalado el certificado del servidor con el cual nos queremos comunicar. Este certificado contiene la clave pública con la cual se encripta la información que se envía y que solo el servidor sabe desencriptar con su clave privada (más información aquí). Por lo tanto, a la hora de consumir un servicio bajo https necesitaremos el certificado del servidor para poder establecer la comunicación.
 
Una vez que obtenemos el certificado debemos guardarlo en un keystore. Un keystore es básicamente un ?almacén de certificados? que nos permite agregar nuevos certificados o eliminarlos (entre otras cosas). Una manera de manipular/administrar estos keystores es mediante la herramienta "Keytool.exe" que trae el JDK.
 
En resumen, lo anterior se reduce a 2 pasos simples:
 
1.1)   Obtener el certificado
 
Con el IExplorer ir al servidor del cual quiero obtener su certificado (https://www.dominio.com/webservice). Luego ir a File->Properties->Certificates. Allí en 'Details' ir por 'Copy to File...' y elegir por ejemplo 'Base-64 encoded X.509'. Con esto se guarda el certificado en un archivo.
 
Image:Web service seguro/autenticación - wsdl certificado
  
 1.2)   Agregar el certificado en un keystore
 
Agregamos el certificado (ej) "certif.cer" en el keystore MiKeystore:
 
C:\>"c:\Program Files\Java\jdk1.5.0_05\bin\keytool.exe" -import -file certif.cer -keystore c:\MiKeystore -storepass MiPassword
 
Nota: En algun caso puede suceder que de el error siguiente en la invocación del webservice:
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to findvalid certification path to requested target
Es porque se recorrió toda la jerarquía pero no encontró una Autoridad Certificadora en la que se pueda confiar. Es decir, el certificado, fue firmado por una firma en la cual no se confia (es decir, no esta en el keystore). En ese caso, ver todos los certificados del sitio, y agregarlos todos al keystore, usando una alias distinto para cada caso (opcion -alias de la opcion -import)
 
2)      Indicando la ubicación del keystore en la aplicación java
 
Cumplidos los pasos anteriores solo queda indicarle a la aplicación la ubicación del keystore para que al momento de establecer la comunicación sepa de donde tomar el certificado. Para esto se deben configurar las "system properties": javax.net.ssl.trustStore y  javax.net.ssl.trustStorePassword. Algo que se hace comúnmente es agregar dichas propiedades en la instancia de la máquina virtual lo cual se puede hacer en las Interpreter Options de GX si la aplicación es win o agregando estas entradas a las java options del tomcat si la aplicación es web.
 
En caso contrario se pueden configurar por código agregando las siguientes líneas en la rutina que consume el servicio (o en cualquier otra parte de la aplicación que se ejecute antes de consumir el servicio):
 
java System.setProperty("javax.net.ssl.trustStore", "C:\\MiKeystore");
java System.setProperty("javax.net.ssl.trustStorePassword", "MiPassword");




Consumir Servicio Web con HttpClient

Gracias por la respuesta, ahi logre consumir el webservice.
Basicamente lo unico que modifique fue comentar el writer.Open(&Archivo),
este lo ocupaba para ver si se escribía correctamente el XML, al
comentarlo me hiso el request de consumir el webservices sin
problemas.

&HttpClient.AddHeader('
Content-type','text/xml; charset=UTF-8')
&HttpClient.AddHeader('SOAPAction','' )
&HttpClient.Port=80
&HttpClient.Host="sve-piloto.zofri.cl"
&writer.OpenRequest(&HttpClient)
//&writer.Open('comosoapui.xml')
&writer.WriteStartElement('SOAP-ENV:Envelope')//<SOAP-ENV:Envelope
&writer.WriteAttribute('xmlns:SOAP-ENV','http://schemas.xmlsoap.org/
soap/envelope/
') //xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/
envelope/
"
......
....
..
.
&writer.Close()
&HttpClient.Execute('POST','sveConsultasWSN/
ConsultasResultadosVisacion') 
__________________________________________________________________
Un Ejemplo de como consumir Servicios web con HTTPCLIENT
Parm(in:&CURP,out:&ErrDscr,out:&ErrNum,out:&String);
/*
&client = tipo httpclient
&writer = tipo xmlwriter
&reader = tipo xmlreader
*/

/* Este es el XML que genera el strom para consumir el ws
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<consultarPorCurp xmlns="http://microsoft.com/webservices/wsRENAPO/wsCURPS">
<aCveCurp>oemg630113mdflld04</aCveCurp>
</consultarPorCurp>
</soap:Body>
</soap:Envelope>
*/

// Estas son las instrucciones que se usaron con Genexus para crear un XML igual al del storm
&client.host = "bse.seg.gto.gob.mx"
&client.addHeader("Content-Type", "text/xml")
&client.addHeader("SOAPAction", "http://microsoft.com/webservices/wsRENAPO/wsCURPS/consultarPorCurp")

&writer.openRequest(&client) // si se quiere generar un archivo plano para ver como queda el xml cambiar esta linea por &writer.Open('C:/NombreArchivo.xml')
&writer.WriteStartDocument("utf-8")
&writer.WriteNSStartElement("soap:Envelope")
&writer.WriteAttribute("xmlns:soap","http://schemas.xmlsoap.org/soap/envelope/")
&writer.WriteAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")
&writer.WriteAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema")
&writer.WriteStartElement("soap:Body")
&writer.WriteNSStartElement("consultarPorCurp")
&writer.WriteAttribute("xmlns","http://microsoft.com/webservices/wsRENAPO/wsCURPS")
&writer.WriteRawText('<aCveCurp>' + trim(&CURP) + '</aCveCurp>' )
&writer.WriteEndElement()
&writer.WriteEndElement()
&writer.WriteEndElement()
&writer.Close()

&client.Execute("POST", "/SCE/alumno/Renapo")

if &client.statuscode >= 300 // error
&ErrDscr = &client.reasonline
&errNum = &client.StatusCode
Else // consumió el ws sin problemas
/*Procesa la respuesta
este es un ejemplo de la respuesta xml que devuelve el ws
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<consultarPorCurpResponse xmlns="http://microsoft.com/webservices/wsRENAPO/wsCURPS">
<consultarPorCurpResult>VEOB931113HJCNLR02|VENEGAS|OLVERA|BRANDON EFREN|H|13/11/1993|MEX|14|JC</consultarPorCurpResult>
</consultarPorCurpResponse>
</soap:Body>
</soap:Envelope>
*/
&reader.openResponse(&client)
Do While &reader.ReadType(1, 'consultarPorCurpResponse') = 1
&reader.read()
do while &reader.name <> 'consultarPorCurpResponse'
if &reader.Name = 'consultarPorCurpResult'
&string = &reader.Value
exit
endif
&reader.read()
Enddo
If not &String.IsEmpty()
exit
Endif
Enddo
Endif
&reader.close()

Return 

Como enviar y recibir datos a través de formularios POST (httpclient httpresponse)

Estimados, quiero compartir mi experiencia en este tema:


Hacer un formulario POST a una web .asp y mostrar datos al usuario:

//Cargar los datos de un HttpClient, ejemplo:
&HttpClient.host = "www.miweb.com"
&HttpClient.base_url = "/form/"

//Cargar las variables en el formulario
&HttpClient.AddVariable('VARIABLE_Cualquiera', 'Valor_de_la_variable')
&HttpClient.AddVariable('VARIABLE_Cualquiera2',
'Valor_de_la_variable2')

//Ejecutar
&HttpClient.Execute('POST', 'pagina.asp')

//Si tengo que mostrar el resultado en pantalla o si el usuario tiene
que interactuar con pagina.asp:
//Inserto un textblock con la propiedad Format:HTML en el webform (el
webform solo va a tener este textblock, nada mas)

TextBlock.Caption = &HttpClient.ToString()


//acá toma el control el main.asp con las variables cargadas

//una vez que el main.asp nos devuelve el control (mediante otro
método POST), debemos capturarlo, para eso, main.asp debe llamar a una
de nuestras páginas, por ejemplo, respuesta.aspx pasandole los
parámetros de respuesta.
//Para eso hacemos un nuevo webpanel con nombre respuesta, y
simplemente en el método start usamos el httprequest

//en respuesta.aspx...
Event Start

        &VARIABLELOCAL =
&httprequest.GetVariable("VARIABLEQUEDEVUELVEELPOST")
        &VARIABLELOCAL2 =
&httprequest.GetVariable("VARIABLEQUEDEVUELVEELPOST2")

EndEvent

Gracias a Cristian Barreto

________________________________________________________________________________

Tipo de Datos HttpClient, HttpResponse y HttpRequest

Introducción

Esta funcionalidad provee a los usuarios GeneXus una forma de poder utilizar el protocolo HTTP en sus programas. Para ello se crearon los tipos de datos HttpClient, HttpResponse y HttpRequest.

Alcance

Objetos: HttpClient (Transacciones, Work Panels, Web Transactions, Web Panels, Reportes, Procedimientos), HttpResponse y HttpRequest (Procedimientos y Reportes con el valor http en la propiedad call protocol, Web Panels y WebTransactions).
Lenguajes: Java – Visual Basic – Visual Fox– C/SQL – C#. 
Interfaces: Web Form, Win Form.

Descripción

Los tres tipos de datos que se definen para interactuar con http son:

HttpClient
Permite armar un request, enviarlo a una URL y leer los resultados.

HttpResponse y HttpRequest
Permiten leer los datos del request y grabar el response. Son objetos disponibles solo en WebProcs.

HttpClient

Este objeto refleja una conexión http. Puede usarse desde cualquier objeto GeneXus.

Propiedades:

      Host
       Define el nombre del host.
      Tipo- String

      Port
      Define el puerto del host.
      Tipo- String

      Secure
      Indica si el protocolo es http o https. 
      Tipo- Boolean

      Timeout
      Determina el Timeout de la conexión.
      Tipo- Integer

      BaseURL
       Indica la URL base de los request que se hagan al host.
      Tipo- String
     
      StatusCode
       Retorna el código de error HTTP.
      Tipo- Integer

      ReasonLine
       Retorna el texto del error HTTP.
      Tipo- String

      ErrCode
Retorna si ocurrió algún error en algún comando, en cuyo caso retorna un valor distinto de cero.
Tipo- Integer

ErrDescription
Retorna el menaje del error si ocurrió alguno en algún comando.
Tipo- String

Basic y Digest
Son constantes que determinan un tipo de autenticación. Se utilizan en el método AddAuthentication.
Basic=0 : Para autentificar se envía el usuario y password sin encriptar.
Digest=1: Para autentificar se envía el usuario y password encriptados.

ProxyHost y ProxyPort
Permiten especificar un proxy http. En ambiente windows se utiliza automáticamente el que esta configurado en la máquina.
ProxyHost- String
ProxyPort- Integer


Métodos

       AddHeader(<Name>, <Value>)
       Agrega un header con el valor dado.
      Ejemplo: AddHeader(“User-Agent”, “GeneXus”)
      <Name>-      String
      <Value>-      String

       AddVariable(<Name>,<Value>)
            Agrega una variable al ‘form’.
Ejemplo: AddVariable(“CliCod”, &CliCod)
      <Name>-      String
      <Value>-      String

       AddString(<Value>)
       Agrega el contenido del string al buffer de datos a enviar.
      <Value>-      String

       AddFile(<Value>)
       Agrega el contenido del archivo al buffer de datos a enviar.
      <Value>-      String

       Execute(<Method>,<URL>)
Ejecuta un método en la URL definida. Se pondría solo la parte final de la URL
Ejemplo: execute("POST", "/servlet/awebproc")
<Method>-        String
<URL>-        String

ToString()
Retorna un String con todo el ‘cuerpo’ del response.

ToFile(<FileName>)
Graba en un archivo el contenido del stream.
<FileName>-        String

GetHeader(<Name>,<Value>)
Retorna en <Value> el valor del header convertido al tipo de la variable.
<Name>-        String
<Value>-         Anytype

AddAuthentication(<Method>, <Realm>, <User>, <Password>)
Se autentifica con <User> y <Password> al dominio <Realm> utilizando el tipo de autenticación <Method>
<Method>- Integer (Pueden utilizarse las propiedades Basic y Digest)
<Realm>- String
<User>- String
<Password>- String

HttpRequest

Este objeto permite leer el request http. Puede instanciarse solo en el contexto de un WebProc.

PROPIEDADES

      Method
       Retorna el método HTTP.
      Tipo- String

      ServerHost
          Retorna el nombre del servidor
          Tipo- String

      ServerPort
       Retorna el puerto en el servidor
      Tipo- Integer

      Secure
Indica si se esta utilizando HTTPS. Si el valor retornado es 1, se esta utilizando HTTPS; si es 0, se esta utilizando http.
Tipo- Integer

ScriptPath
Retorna la porción de URL correspondiente el nombre del directorio virtual.
Tipo- String

ScriptName
Retorna el nombre del objeto con la extensión correspondiente que se esta ejecutando, tal como aparece en la URL
Tipo- String

Referrer
Retorna la URL del llamador
Tipo-String

QueryString
Retorna la porción de la URL que está después del signo “?”; o sea los parámetros.
Tipo- String

RemoteAddress
Devuelve la dirección del cliente.
Tipo- String

      ErrCode
Retorna si ocurrió algún error en algún comando, en cuyo caso retorna un valor distinto de cero.
Tipo- Integer      

ErrDescrption
Retorna el menaje del error si ocurrió alguno en algún comando.
Tipo- String

Métodos


            GetVariable(<Variable>)
Retorna en un String el valor con el que viene cargada la <Variable> en el post.
<Variable>-        String

GetHeader(<Header>)
Retorna un String con el valor del header <Header>.
<Header>-        String

ToString()
Retorna un String con todo el ‘cuerpo’ del request.

ToFile(<FileName>)
Graba en un archivo el contenido del stream.
<FileName>-        String

HttpResponse

Este objeto permite escribir el response http. Puede instanciarse solo en el contexto de un WebProc. 

PROPIEDADES


      ErrCode
Retorna si ocurrió algún error en algún comando, en cuyo caso retorna un valor distinto de cero.
Tipo- Integer      

ErrDescrption
Retorna el menaje del error si ocurrió alguno en algún comando.
Tipo- String
  

Metodos

       AddHeader(<Name>,<Value>)
       Agrega un header con el valor dado.
      Ejemplo: AddHeader(“User-Agent”, “GeneXus”)
      <Name>-      String
      <Value>-      String

       AddString(<Value>)
       Agrega el contenido del string al buffer de datos a enviar.
      <Value>-      String

       AddFile(<Value>)
       Agrega el contenido del archivo al buffer de datos a enviar.
      <Value>-      String

Interacción con XML

Estos objetos permiten la interacción con los objetos XMLReader y XMLWriter. Para ello existen los siguientes métodos:

XMLReader.openRequest(HttpRequest)
Se utiliza en un WebProc para leer un xml que viene en el body del http request.

XMLReader.openResponse(HttpClient)
Se utiliza en cualquier objeto para leer como XML lo que devolvió un request.

XMLWriter.openRequest(HttpClient)
Se utiliza para enviar un XML en el body de un http request.

XMLWriter.openResponse(HttpResponse)
Se utiliza en un WebProc para escribir un xml que se retornara en el body del http response. 

Ejemplo 

Este ejemplo muestra como un objeto GeneXus llama a otro vía http, pasándole parámetros en un XML y recibiendo los mismos también en un XML.

El XML a enviar tiene la forma

<parameters>
          <a>valor</a>
<b>valor</b>
</parameters>

El XML que se devuelve es igual, con los valores de ‘A’ y ‘B’ modificados.


El programa ‘cliente’ sería:

&Client de tipo HttpClient
&Writer de tipo XMLWriter
&Reader de tipo XMLReader

          // Determino el host y el puerto a donde hacer el request
              &client.host = "localhost"
              &client.port = 88 

          // Agrego el XML al request
&writer.openRequest(&client)
&writer.WriteStartElement("parameters")
&writer.WriteElement("a", &A)
&writer.WriteElement("b", &B)
&writer.WriteEndElement()
&writer.close()

          // Hago el POST al webproc
&client.execute("POST", "/servlet/awebproc")
   
          // Leo el XML que devuelve y lo cargo en las variables internas

&reader.openResponse(&client)
&reader.read()

&reader.read()
&a = val(&reader.value)

&reader.read()   
&b = val(&reader.value)

&reader.close()


El programa ‘servidor’ seria el siguiente WebProc:

&Request de tipo HttpRequest
&Response de tipo HttpResponse
&Writer de tipo XMLWriter
&Reader de tipo XMLReader

          // Leo los parámetros del XML
&reader.openRequest(&Request)
&reader.read()
&reader.read()
&a = val(&reader.value)
&reader.read()   
&b = val(&reader.value)
&reader.close()

// Le sumo uno a cada valor
&a = &a + 1
&b = &b + 1
       
// Grabo los parámetros en el response

&writer.openResponse(&Response)
&writer.WriteStartElement("parameters")
      &writer.WriteElement("a", &A)
      &writer.WriteElement("b", &B)
&writer.WriteEndElement()
&writer.close()

Consideraciones para el generador Java

En el caso de que se ejecute el motor de servlet en Windows, la aplicación obtendrá automáticamente la configuración del proxy http y la lista de hosts para los que no se debe utilizar el proxy.

En caso de que se ejecute en otra plataforma, es necesario especificar el proxy como una ‘System Property’ desde la línea de comandos del intérprete, por ej:

java -Dhttp.proxyHost=your.proxy.com -Dhttp.proxyPort=XX <mainclass>



 (Consideraciones Generales)

La propiedad secure del tipo de datos HTTPClient en el generador C/SQL solo puede ser utilizada en clientes Microsoft.



Correo con WebPanel Adjunto

Nosotros utilizamos este código:

&Message.SetEmpty()
&Error = 0

//Obtener Parámetros - Esto lo tengo en la base de datos para poder parametrizarlo
&From = ObtienePreferenciaValCadena.Udp('EmailFrom')
&Name = ObtienePreferenciaValCadena.Udp('EmailName')
&Host = ObtienePreferenciaValCadena.Udp('EmailHost')
&UserName = ObtienePreferenciaValCadena.Udp('EmailUsuario')
&Password = ObtienePreferenciaValCadena.Udp('EmailPassword')
&Puerto = ObtienePreferenciaValNumerico.Udp('EmailPuerto')

//Envio de Email
&MailRecipient.Address = &From
&MailRecipient.Name = &Name
&SMTPSession.Host = &Host
&SMTPSession.Port = &Puerto
&SMTPSession.UserName = &UserName
&SMTPSession.Password = &Password
&SMTPSession.Sender = &MailRecipient
&SMTPSession.Authentication = 1
&SMTPSession.Login()

if &SMTPSession.ErrCode <> 0
       &Error = 1
       &Message = 'Error en login de la cuenta de correo:' + &SMTPSession.ErrDescription
endif

&MailMessage.To.New(&NombreContacto, &EmailContacto)

&MailMessage.Subject = &Subject
&MailForm.Object = EmailFormato.Create(&Mensaje) //EmailFormato es mi webpanel


&MailMessage.HTMLText = &MailForm.GetResponse()
&SMTPSession.Send(&MailMessage)

if &SMTPSession.ErrCode <> 0
       &Error = 1
       &Message = 'Error al enviar el correo: ' + &SMTPSession.ErrDescription
endif

&SMTPSession.Logout()
if &SMTPSession.ErrCode <> 0
       &Error = 1
       &Message = 'Error al cerrar la cuenta de correo: ' + &SMTPSession.ErrDescription
endif


En el web panel tengo dos imágenes que cargo en el evento Start así:

Event Start
       TBMensaje.Caption = &Mensaje
       Image1.FromURL(&URLImagen)
       Image7.FromURL(&URLImagen)
EndEvent

En donde &URLImagen debe ser la URL en donde se encuentra la imagen, claro que esa URL debe estar accesible desde internet. Otra opción es adjuntar las imágenes al mail pero yo tuve algunos inconvenientes con esa segunda opción.

Gracias a j.acosta@alphasoluciones.com