Mostrando entradas con la etiqueta Web. Mostrar todas las entradas
Mostrando entradas con la etiqueta Web. Mostrar todas las entradas

martes, 22 de agosto de 2017

Imagen tipo blob desde una imagen agregada en Genexus

Buenas con todos.

Bueno después del respectivo saludo, explico un poco a que debe el nombre de la entrada. Estoy mostrando en un web panel los registros ingresados que tienen una imagen tipo blob en uno de sus campos, adicionalmente necesito mostrar una imagen por defecto para aquellos que no tenían configurada una.

Bueno entonces lo que necesito es poder cargar una imagen tipo blob ya no desde los campos de mi base sino con una imagen que yo decida. Tuve algunos inconvenientes, por ejemplo use la función FromBase64String y convertí mi imagen a este formato, peno no funcionó.

Así que la solución fue usar la función FromString que recibe la Url de la imagen, y para ello utilice una imagen ya cargada en el IDE de Genexus y la Función Link, quedando de este modo.

&ImageVarBlob.FromString(MyGenexusImage.Link())

viernes, 23 de junio de 2017

Encrypt URL parameters: Cifrado Manual de Parámetros con Site Key

Bueno en la anterior entrada revisamos la configuración para Cifrar los parámetros de la URL mediante Site Key y una forma automática de generar dichos enlaces. Para los que no, revisen el enlace aquí.

Pero si les paso lo que a mí, se deben de haber topado con la necesidad de generar esta URL de forma manual.

Bueno aquí corresponde una breve explicación de como Genexus realiza este cifrado de la URL.

Genexus utiliza el algoritmo TwoFish el cual está contenido en las funciones:

GetEncryptionKey, para obtener una llave o key de cifrado válida.
Encrypt64, para el cifrado en base a dicha llave.
Decrypt64, para el descifrado en base a una llave.

Genexus no solo cifra los parámetros sino que arma un string específico para el cifrado de los parámetros de la URL unido a un CheckSum de seis cifras, en el enlace pueden ver la documentación respectiva, aunque es del 2004, por lo que no ayudó mucho ya que ha habido un pequeño cambio en como se arma el String a cifrar.

Como vieron en la entrada anterior se mostró cómo configurar el Application.Key para administrar nuestras propias llaves. Gracias a esto se puede descifrar una URL y ver como está armada. Para mi caso actual usando Genexus Evolution 3 Upgrade 9. El cifrado de la URL corresponde a:

?objeto.aspxParametrosCheckSum

Siendo:

Objeto, nombre del web panel o transacción en minúsculas.
Parametros, los parámetros necesarios recibidos por el objeto separados por coma.
CheckSum, check sum del string formado por el objeto y los parámetros.

Entonces para cifrar correctamente de forma manual los parámetros de la url necesitamos armar dicho string y cifrarlo con las funciones ya mencionadas.

El código sería:

//cifrar parametros de url con Site Key
CSHARP [!&tempkey!] = Crypto.GetSiteKey( );
&toEnc = "webpanel" + '.aspx' + "param1" + ',' + "param2"
CSHARP [!&chkSum!] = Crypto.CheckSum( [!&toEnc!], 6);
&URL= &DominioSitio + '/webpanel.aspx?' + encrypt64(&toEnc+&chkSum, &tempkey)


Nótese que debemos usar las funciones Crypto.GetSiteKey() para obtener la llave usada en el cifrado y CryptoCheckSum() para generar el check sum de seis dígitos (por ello el parámetro de 6) con código Nativo C#.

Encrypt URL Parameters: Site Key para compartir enlaces con parámetros cifrados basados en Web Panel

Bueno hoy el objetivo fue cifrar los parámetros usados en los Web Panels de Genexus para evitar la manipulación de los mismos y adicionalmente poder compartir estos enlaces (Ej: Por un correo electrónico como un enlace).

Así que a buscar y probar. Basándonos en la Wiki de Genexus (enlace) respecto a este tema tenemos que existen dos formas de cifrar los parámetros:
  1. Basado en Web Session (Session Key): es decir que se usan características de la sesión del usuario para cifrar los parámetros. En la wiki recalca que es el más seguro pero ya que depende de los valores de la sesión y cookies del usuario el cifrado es diferente para cada sesión.
  2. Basado en una key por el sitio (Site Key): menos segura pero permite poder compartir los enlaces generados ya que el mismo cifrado es usado en todo la aplicación Web.
Para cifrar los parámetros use la segunda opción configurándola de la siguiente manera:
  1. En las propiedades del Ambiente de la KB se usa la propiedad Encrypt URL Parameters usando la opción Site Key.


  2. Rebuild de toda la KB para que se compile el uso de parámetros cifrados en todos los objetos pertinentes.
Para generar mi propia "key" y brindar mayor seguridad y administración a mi site y no usar la key por defecto de Genexus se usó los siguientes pasos:
  1. Generar un llave o dos (según la documentación de Genexus, ver SAC 29369, una es usada para cifrar los parámetros de conexión a la Base de datos y la otra para el cifrado de los parámetros) mediante la función GetEncryptionKey() (ver doc respectivo de la función para más detalles). 
  2. Crear el archivo de texto plano Application.Key (ubicarla en la raiz de la KB, del proyecto, para que el archivo web.config pueda ser actualizado con los parámetros respectivos cifrados y en la carpeta Web del modelo generado para que las clases respectivas puedan descifrar los parámetros).
  3. Editar el archivo creado con las "keys" generadas.


  4. Compilar y probar, si observan el archivo web.config tendrá un nuevo cifrado ya que se alteraron las "keys respectivas" y ya no se usan las que genera Genexus por defecto.
Para generar de forma automática los enlaces cifrados para poder compartirlos, se usó el método Link del objeto recibiendo los parámetros respectivos.

&Var = &urlsite + Link(WebPanel, &param1, &param2)

o

&Var = &urlsite + WebPanel.Link(&param1, &param2)

En la captura pueden observar el cifrado de los parámetros llamando una Transacción.


Quedó pendiente para una próxima entrada el cifrado manual de los parámetros (ver enlace).

Si desean configurar una clase (dll) y no un archivo que controle las "keys" ver el SAC 29874.

lunes, 8 de agosto de 2016

Aplicación Java no despliega sobre Tomcat 8 en Genexus

Bueno hoy tocó hacer algunas pruebas sobre Java y Tomcat 8 con Genexus y me encuentro con la sorpresa de qué no se desplegaba mi app en el servidor de aplicaciones.

Tengo el servicio de tomcat levantado en forma manual asi que debo ingresar a la página de administración y arrancar la aplicación, al hacerlo me doy cuenta de un error en la app que no permite arrancarla:



Revisando el log de Tomcat ([path de instalación]/logs) me encuentro con un error relacionado con el GAM de Genexus, el cual no estoy usando:


Caused by: java.lang.NoClassDefFoundError: artech/security/api/gamrefreshtoken

pero googleando un poco me topo con el SAC#31566 que explica las configuraciones pertinentes para Tomcat 7, asi que a probar un poco las mismas para ver si funcionan sobre Tomcat 8.

Se editó justo lo que piden las configuraciones:
  • Asegurarse que la propiedad "use annotations for servlet definition" en web information se habilita (valor "Yes"). Propiedad ubicada en el Generador del ambiente Java correspondiente.

  • Utilizar la propiedad Java Package name y especificar un valor. (Por defecto ya venía configurada)


Y arrancando la app y accediendo al path correspondiente ya se despliega correctamente.

PD: Antes tocó solucionar otro error de clases no encontradas para la libreria gxscanner.jar:

java.lang.ClassNotFoundException: com.genexus.webpanels.GXJarScanner

o

Caused by: java.lang.ClassNotFoundException: com.genexus.webpanels.GXJarScanner

Que se solucionó incorporando la librería correspondiente en la carpeta lib de la aplicación en Tomcat descargada del site oficial de Genexus. Download. Les dejó tambien el acceso al SAC#36031  correspondiente (deben estar registrados en el site de Genexus para su descarga)

martes, 14 de junio de 2016

Generar Web Services SOAP y RESTful en Genexus y Consumirlos desde Cliente Nativo Android y App Web Genexus

Cabe mencionar que los ejemplos mostrados a continuación quieren mostrar la creación y el consumo de servicios Web, nada complejo en seguridad ni adicionales como Login en los servicios o manejo sobre protocolo https o cualquier otra cosa por el estilo.

Para está entrada se creará dos tipos de servicios (SOAP y RESTful) desde el IDE de Genexus en Ambiente Web para C# (C sharp). Adicionalmente se creará sus respectivos Clientes que consuman dichos servicios tanto desde Genexus como desde un Cliente Nativo Android.

Servidor

Para ambos servicios se usará el objeto "Procedure" de Genexus más ciertas configuraciones adicionales para establecer el servicio necesitado. Se tiene una "Transacción" Application con tres campos Id (Numeric), Name (VarChar), ClientId (VarChar) (Figura 1.), ClientSecret (VarChar). Se ha creado un objeto "SDT" basado en estos tres campos (Figura 2).

Fig 1. Transsacción

Fig 2. SDT


Servicio Web Tipo SOAP

Como ya se mencionó para habilitar los servicios Web se usa el objeto "Procedure". Así que crearemos un objeto de dicho tipo del nombre "getApplications" para el servicio SOAP.

En el código correspondiente al objeto tendremos una consulta mediante "For each" a la Tx Creada. Observesé la condición "where ApplicationId = &ApplicationId" que nos permitirá filtrar la información a obtener de la Tx y a ser almacenada en la variable SDT correspondiente.

for each
where ApplicationId = &ApplicationId
&sdtApplication =  new()
&sdtApplication.ApplicationName = ApplicationName
&sdtApplication.ApplicationClientId = ApplicationClientId
&sdtApplication.ApplicationClientSecret = ApplicationClientSecret
endfor


Posteriormente, en la sección de parámetros tenemos como entrada la variable "ApplicationId" y como salida la variable "sdtApplication".

parm(in: &ApplicationId, out:&sdtApplication);

En las propiedades del objeto configuramos las opciones:
  • Call Protocol: SOAP
  • Main Program: True
Para probar la generación del servicio se puede acceder a la url:

http://[localhost o ip local]/[Nombre de la la KB].[Ambiente Web de la KB]/a[nombre del procedure].aspx


Fig 3. URL de Servicio SOAP

Para unas pruebas más exhaustivas se puede instalar "SOA Client" en mi caso el add-On para el Navegador Firefox (Descarga Aquí) y añadiendo en la ruta anterior el parámetro ?wsdl usar directamente el servicio Web como se puede observar en la figura 4.

Fig 4. Consumo de SOAP mediante SOA Client

Servicio Web Tipo RESTful

De manera similar podemos usar un objeto "Procedure" para un servicio tipo RESTful, Para mantener el código y parámetros anteriores podemos hacer un Save As del objeto anterior (Poniendo por default las configuraciones cambiadas anteriormente) o usar un nuevo "Procedure" con el mismo código y parámetros. El nombre del procedure será "getApplicationsRest".

Pero en el cual configuramos las siguientes opciones de las propiedades:
  • Expose as a web Service: True
  • Rest Protocol: True
Para probar la generación del servicio se puede acceder a la url:

http://[localhost o ip local]/[Nombre de la la KB].[Ambiente Web de la KB]/rest/[nombre del Procedure]

De manera similar para otro tipo de pruebas se puede instalar el Add-On "Rest Client" sobre el Navegador Firefox (Descarga Aquí) ver la figura 5.

Fig 5. Consumo de REST mediante Rest Client


Cliente

Cliente Web Genexus para servicio SOAP

Bueno si recuerdan la Url del servicio SOAP, aquella compuesta por la terminación wsdl, pues esta misma url es vital para construir el Cliente para el consumo del servicio. Esta url si la abrimos en el navegador como muestra la figura 6, nos muestra en formato xml principalmente:

  • El NameSpace en el que se ejecuta el Servicio, en este caso el nombre de la KB.
  • El nombre del método o Acción a llamar.
  • Los parámetros de entrada y el tipo de dato.
  • Los parámetros de salida y su tipo de dato.

Fig 6. WSDL del servicio SOAP construido en Genexus.

Toda esta información es usada por Genexus en un Wizard para construir un "External Object" y un "SDT", que consuma el servicio y lo almacene respectivamente.

Podemos usar una nueva KB, o la misma si se desea, y nos ubicamos en la opción del menú Tools / Application Integration / WSDL Import

Fig 7. Acceso al WSDL Import.

Obtendremos la pantalla correspondiente donde ingresaremos la url respectiva. Ver figura 7.

Fig 8. WSDL Import.

Una vez realizado el import del WSDL, podemos observar que se ha creado un External Object para la llamada al servicio SOAP y un SDT para su almacenamiento.

Fig 9. External Object creado por WSDL Import.


Fig 10. SDT creado por WSDL Import.

Para consumir los mismos podemos hacer una llamada desde una pantalla Web mediante el uso de una variable basada en el External Object creado por el wizard y almacenándolo en el SDT respectivo:

&getAppsdtApplication = &getApplications.Execute(&ApplicationId)

Nótese que mediante el método Execute del External Object se pasan los parámetros del web Service, en este caso recibe la variable &ApplicationId de tipo Numeric. Otra cosa a notar es que para Genexus es transparente el uso de xml para el intercambio de información, tanto para el servidor al momento de enviar los datos por el servicio como para el cliente al momento de consumir el mismo.

Cliente Web Genexus para servicio RESTful

Bueno para consumir un servicio Rest en Genexus es un poco más complicado ya que no existe ningún wizard como en el caso de Soap, pero se puede usar un tipo de objeto llamado HttpClient para realizar la llamada al mismo y capturar la respuesta del servidor.

Adicionalmente en el HttpClient, se debe configurar:
  • El Servidor al cual se va a acceder.
  • La Url base del Servicio Rest.
  • El puerto usado para la conexión.
  • El cuerpo o body, es decir los parámetros de entrada en formato JSON.
  • La cabecera como tipo 'Content-type' y 'application/json'.
  • El nombre del servicio (en este caso el nombre del procedure) y el Método Http a usar (en base a la documentación de la Wiki de Genexus se debe usar siempre el método POST).
Todas estas configuraciones son visibles en el siguiente código:

&httpclient.Host = "localhost" //Servidor
&httpclient.Port = 80 //Puerto
&httpclient.BaseUrl = "/IAMEV3.NetEnvironment/rest/" //Url Base
&httpclient.AddHeader('Content-type','application/json') //Cabecera
&httpclient.AddString('{"ApplicationId":1}') // body o parámetros de entrada en formato JSON

Para ejecutar el cliente http se usa el método Execute especificando el método Http y el nombre del procedure.

&httpclient.Execute('POST','getapplicationsrest')

Para la captura de la respuesta simplemente se puede hacer un String del HttpClient.

&httpclient.ToString()

Y para la visualización de Errores se puede usar los métodos ErrCode y ErrDescription del HttpClient.


&httpclient.ErrCode
&httpclient.ErrDescription


Cliente Nativo Android para servicio SOAP y RESTful (Ver Aquí)

miércoles, 27 de noviembre de 2013

Imprimir un string en varias lineas de un reporte PDF

Bueno no se si les haya pasado, pero en mi caso me ocurrió que tenía un string o varchar o como le llamen de un tamaño de 500 caracteres, y que al momento de enviarlo a imprimir a un reporte PDF se salía de los márgenes del mismo y no como uno esperaba que se recorra automáticamente hacia abajo. Así que a buscar la manera de solucionar el inconveniente. (Me olvidaba, aclaro estaba trabajando en ambiente Web para el Generador Java)

Es aquí cuando me enteré de la función GXGetMLi, y en base a un poco de programación se consiguió que se imprima todo el string hacia abajo sin que salga de los márgenes del reporte PDF.

La función GXGetMLi recibe el string, el número de línea y el número de caracteres a imprimir por esa línea y devuelve el resto del string especificado por los parámetros mencionados. Todo esto más un contador y un for y una que otra validación con un if y listo.

For &contadorlinea = 1 to 5
    &lineaImprimir = GXGetMLi(&Descripcion, &contadorlinea, 100)
    if NOT &lineaImprimir.IsEmpty() AND &contadorlinea = 1
        print LineaDescripcion
    else
        if NOT &lineaImprimir.IsEmpty()
            print LineaDescripcion1
        endif
    endif
Endfor

A tomar en consideración:
  1. No es lo mismo imprimir minúsculas que Mayúsculas, por lo que recomiendo tomar en cuenta la impresión como si se lo estuviera haciendo solo con mayúsculas para no llevarse sorpresas cuando el usuario ingrese solo este tipo de caracteres.
  2. Tomar en cuenta el número de caracteres a imprimir, porque puede ser el caso de tener varias descripciones a imprimir y en forma de columna. Por lo que se debe tomar en cuenta el ancho y por ende el número de caracteres que calzarán en ese ancho de columna.
  3. Si se dieron cuenta el número de repeticiones del for por el número de caracteres enviado a la función explicada es igual a 500 que es el tamaño del string.
  4. Y me olvidaba si tienen saltos de línea la función hará los saltos de línea correspondiente así que esto puede alterar el número de líneas a imprimir por lo que al menos yo elimino los saltos de lìnea del string ( para saber cómo eliminar saltos de línea de un string click aquí ).
Nota:

Para .Net me dijeron, pero ustedes pueden comprobarlo, que no hace falta esta codificación sino simplemente configurar en las propiedades de la variable a imprimir en la pestaña de Layout aquella que dice Alignment y colocar MiddleJustify. Si no les funciona ya saben que hacer.

lunes, 25 de noviembre de 2013

Eliminando Saltos de línea de un String

Aquí una pequeña guía para eliminar el salto de línea de un string. Se van a usar funciones propias de la herramienta como son Chr y StrReplace.

Primero creamos una variable tipo Varchar para almacenar el salto de línea. En mi caso la nombrare &LF

Después almacenamos el valor del salto de línea mediante la función CHR, recibe como parámetro el código decimal del carácter (Código ASCII), el código decimal del salto de línea es 10.

&LF = CHR(10)

Por último usamos la función STRReplace para reemplazar el salto de línea por cualquier carácter deseado. La función recibe como parámetros el String, el carácter a reemplazar y el carácter que lo reemplazará (ya parece trabalenguas).

&String = STRReplace(&String, &LF.Trim(), " ")

Descarga Export para Genexus EV2

domingo, 24 de noviembre de 2013

Abrir Web Panel en una nueva pestaña

Trabajando con este bendito Genexus me encontré con la necesidad de abrir un WebPanel en otra pestaña del navegador desde una acción de la línea de un Grid. Adicionalmente necesitaba pasar unos parámetros que construía en un Sub. Así que con estas condiciones a googlear, y me encontré con algunas opciones en varios foros y blogs, las mismas que serán mostradas a continuación.

Cabe mencionar, no se si debería, que estoy trabajando con la versión Evolution 2. Esto lo menciono por si acaso no más.

Bueno principalmente encontré tres opciones:

La primera mediante la propiedad Link y el Evento Load del Grid, la segunda mediante código JavaScript y la propiedad Link y la tercera que no es más que abrirla en un popup especificando las propiedades para su apertura. Ahora si empecemos con las respectivas codificaciones de cada ejemplo:
  1. Como mencione se debe codificar en el evento Load del Grid. Donde se tiene una variable tipo imagen agregada en las columnas del grid, la misma que posee la propiedad "Link" que es a la que vamos a igualar a la propiedad "Link" del web panel a abrir en una nueva pestaña.

  2. Event Load
           &NuevaVentana.LinkTarget = "_blank"
           &NuevaVentana.Link = WebPanel.Link(&Parametro)
    EndEvent

  3. Está es la opción que utilice. Se crea un Texblock en el Web Panel y se especifica como Foramato "HTML" y mediante código JavaScript  se realiza la llamada pertinente al Web Panel con su propiedad "Link" en el Evento "Click" de la variable correspondiente pasando los parámetros y llamando a los Subs respectivos.

  4. Event &NuevaVentana.Click
           do 'LlamadaSub'
           TextBlock.Caption='<script>window.open("'+WebPanel.Link(&Parametro)+'","Pagina Nueva");</script>'
    EndEvent

    Se debe tomar en cuenta las comillas dobles y simples usadas en el JavaScript.

  5. Esta opción solo abre en una pantalla emergente conocida como Pop Up, pero con la peculiaridad de que se pueden especificar ciertos parámetros para su apertura. Esta operación se realiza mediante una variable tipo "Window"

  6. Event &NuevaVentana.Click
           &InWindow.Url = WebPanel.Link(&Parametro)
           &InWindow.Open()
    EndEvent
Descarga Export para Genexus EV2