tag:blogger.com,1999:blog-45698381934334828162024-03-13T10:32:01.351-05:00Trabajando con GenexusUnknownnoreply@blogger.comBlogger14125tag:blogger.com,1999:blog-4569838193433482816.post-82557511596298141342018-02-09T10:36:00.000-05:002018-02-09T10:37:43.649-05:00Despedida del blogBuenas días con tod@s,<br />
<br />
<div style="text-align: justify;">
Siendo las 10 horas con 35 minutos de la mañana del día 09 de febrero del año 2018, me despido de este blog. Y aunque quedaron muchas cosas pendientes de las que publicar y comentar, las mismas ya no podrán ser realizadas ya que estoy cambiando de ambiente de trabajo y por ende de algunas herramientas a ser usadas. Ya que dejaré de trabajar con Genexus y me pasaré a otros IDEs más clásicos.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Así que está es la despedida de al menos este blog (aclarando que las entradas no serán eliminadas, ni nada de eso, aunque posiblemente ya no se responda a los comentarios ya que no poseeré de la herramienta respectiva para solventar ciertas dudas). Aunque si desean seguir leyendo algunas publicaciones tengo otros tres blogs para temas diferentes.</div>
<br />
<ol>
<li style="text-align: justify;">Blog técnico para Software Libre y Sistemas informáticos, un poco abandonado por el momento. Pero en el cambio de ambiente esperamos retomar el mismo con nuevas entradas. Ej: Código Limpio, TDD, buenas prácticas de desarrollo, etc. <a href="https://aprendiendoconswlibre.blogspot.com/" target="_blank">Ver blog Aprendiendo con Sw Libre</a>.</li>
<li style="text-align: justify;">Blog personal sobre todo tipo de inquietudes: poesía, libros, música, guitarra, etc. <a href="https://enbuscadeidentidad.blogspot.com/" target="_blank">Ver blog En Busca de Identidad</a>.</li>
<li style="text-align: justify;">Blog de Arte, Cultura y Guitarra Popular: a tratar temas de educación, arte, cultura, herramientas y guitarra de la cultura popular. <a href="https://gitaroblog.wordpress.com/" target="_blank">Ver Gitaro Blog</a>.</li>
</ol>
<div style="text-align: justify;">
Y quién sabe tal vez por ahí algún día vuelva Genexus y retomemos este blog.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Saludos y pasen un excelente día.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDYQoIBKvrQwUv8V-qeTPGgIl6MlYSOHKWUMxQmEWgBXYc2PpRYnrVBGsUBO36gdtZRUuGokhCJp1509Y25nb1lK_e3DSEoQ0TeA_glH4vxu1be9LyEsw8scCzajDc_qxWdXTcPj_ejw/s1600/firma.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="104" data-original-width="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDYQoIBKvrQwUv8V-qeTPGgIl6MlYSOHKWUMxQmEWgBXYc2PpRYnrVBGsUBO36gdtZRUuGokhCJp1509Y25nb1lK_e3DSEoQ0TeA_glH4vxu1be9LyEsw8scCzajDc_qxWdXTcPj_ejw/s1600/firma.png" /></a></div>
<div style="text-align: right;">
<br /></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4569838193433482816.post-27241532027071092032017-08-22T15:04:00.001-05:002017-08-22T16:50:00.433-05:00Imagen tipo blob desde una imagen agregada en Genexus<div style="text-align: justify;">
Buenas con todos.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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 <a href="https://wiki.genexus.com/commwiki/servlet/wiki?6704,Blob+data+type," target="_blank">blob </a>en uno de sus campos, adicionalmente necesito <i><b>mostrar una imagen por defecto</b></i> para aquellos que no tenían configurada una.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Bueno entonces lo que necesito es poder <b><i>cargar una imagen tipo blob</i></b> ya no desde los campos de mi base sino <i><b>con una imagen</b></i> que yo decida. Tuve algunos inconvenientes, por ejemplo use la función <a href="https://wiki.genexus.com/commwiki/servlet/wiki?7374,Blobs+in+Base64," target="_blank">FromBase64String </a>y convertí mi imagen a este formato, peno no funcionó.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<div style="text-align: center;">
<code>
<span style="font-size: small;">&ImageVarBlob.FromString(MyGenexusImage.Link())</span>
</code>
</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4569838193433482816.post-24518307203406399662017-06-23T17:25:00.002-05:002017-06-26T10:25:54.090-05:00Encrypt URL parameters: Cifrado Manual de Parámetros con Site KeyBueno 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 <a href="http://trabajandocongenexus.blogspot.com/2017/06/encrypt-url-parameters-site-key-para.html" target="_blank">aquí</a>.<br />
<br />
Pero si les paso lo que a mí, se deben de haber topado con la necesidad de generar esta URL de forma manual.<br />
<br />
Bueno aquí corresponde una breve explicación de como Genexus realiza este cifrado de la URL.<br />
<br />
Genexus utiliza el algoritmo <a href="https://es.wikipedia.org/wiki/Twofish" target="_blank"><b>TwoFish </b></a>el cual está contenido en las funciones:<br />
<br />
<span class="WikiName" id="VIEWTITLE"><a href="https://wiki.genexus.com/commwiki/servlet/wiki?8385,GetEncryptionKey+Function," target="_blank"><b><i>GetEncryptionKey</i></b></a>, para obtener una llave o key de cifrado válida.</span><br />
<a href="https://wiki.genexus.com/commwiki/servlet/wiki?8386,Encrypt64+Function,"><b><i>Encrypt64</i></b></a>, para el cifrado en base a dicha llave.<br />
<a href="https://wiki.genexus.com/commwiki/servlet/wiki?8382,Decrypt64+function,"><b><i>Decrypt64</i></b></a>, para el descifrado en base a una llave.<br />
<br />
<i>Genexus no solo cifra los parámetros sino que arma un <b>string específico</b> para el cifrado de los parámetros de la URL unido a un CheckSum de seis cifras,</i> en el <a href="http://library.gxtechnical.com/gxdlsp/pub/SAC/hsac_16510,S.html" target="_blank">enlace</a> 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.<br />
<br />
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 <b><i>Genexus Evolution 3 Upgrade 9</i></b>. El cifrado de la URL corresponde a:<br />
<br />
<div style="text-align: center;">
<b>?objeto.aspxParametrosCheckSum</b></div>
<br />
Siendo:<br />
<br />
<b><i>Objeto</i></b>, nombre del web panel o transacción en minúsculas.<br />
<i><b>Parametros</b></i>, los parámetros necesarios recibidos por el objeto separados por coma.<br />
<b><i>CheckSum</i></b>, check sum del string formado por el objeto y los parámetros.<br />
<br />
Entonces para cifrar correctamente de forma manual los parámetros de la url necesitamos armar dicho string y cifrarlo con las funciones ya mencionadas.<br />
<br />
El código sería:<br />
<br />
<code>
//cifrar parametros de url con Site Key<br />
<span style="font-size: small;">CSHARP [!&tempkey!] = Crypto.GetSiteKey( );</span><br />
<span style="font-size: small;">&toEnc = "webpanel" + '.aspx' + "param1" + ',' + "param2"</span><br />
<span style="font-size: small;">CSHARP [!&chkSum!] = Crypto.CheckSum( [!&toEnc!], 6);</span><br />
<span style="font-size: small;">&URL= &DominioSitio + '/webpanel.aspx?' + encrypt64(&toEnc+&chkSum, &tempkey)</span><br />
</code>
<br />
<br />
Nótese que debemos usar las funciones<b> Crypto.GetSiteKey() </b>para obtener la llave usada en el cifrado y <b>CryptoCheckSum() </b>para generar el <i><b>check sum de seis dígitos</b></i> (por ello el parámetro de 6) con <b>código Nativo C#</b>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4569838193433482816.post-7564980399710433412017-06-23T15:24:00.001-05:002017-06-23T17:28:51.014-05:00Encrypt URL Parameters: Site Key para compartir enlaces con parámetros cifrados basados en Web PanelBueno 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).<br />
<br />
Así que a buscar y probar. Basándonos en la Wiki de Genexus (<a href="https://wiki.genexus.com/commwiki/servlet/wiki?8068,Encrypt+URL+Parameters+property," target="_blank">enlace</a>) respecto a este tema tenemos que existen dos formas de cifrar los parámetros:<br />
<ol>
<li>Basado en Web Session (<b>Session Key</b>): 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.</li>
<li>Basado en una key por el sitio (<b>Site Key</b>): menos segura pero permite poder compartir los enlaces generados ya que el mismo cifrado es usado en todo la aplicación Web.</li>
</ol>
<div>
Para <b><u>cifrar los parámetros</u></b> use la segunda opción configurándola de la siguiente manera:</div>
<div>
<ol>
<li>En las propiedades del Ambiente de la KB se usa la propiedad Encrypt URL Parameters usando la opción Site Key.</li>
<br /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjluGU3dtaVZ0BXQdBiTJS0gwT6fk-pwRnXCR4kTpblAT-HnSBUyuaq8GuYKl13KGT3FsgLWcjNI9RacDSWoAlP9hX-3zzXEgy4nw2qIjuuXhlHEBaGxvi2BT70t4PKOZ6eDFcqb9F0fA/s1600/kbconf.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="379" data-original-width="629" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjluGU3dtaVZ0BXQdBiTJS0gwT6fk-pwRnXCR4kTpblAT-HnSBUyuaq8GuYKl13KGT3FsgLWcjNI9RacDSWoAlP9hX-3zzXEgy4nw2qIjuuXhlHEBaGxvi2BT70t4PKOZ6eDFcqb9F0fA/s400/kbconf.PNG" width="400" /></a></div>
<br />
<li>Rebuild de toda la KB para que se compile el uso de parámetros cifrados en todos los objetos pertinentes.</li>
</ol>
<div>
Para <b><u>generar mi propia "key"</u></b> y brindar mayor seguridad y administración a mi site y no usar la key por defecto de Genexus se usó los siguientes pasos:</div>
</div>
<div>
<ol>
<li>Generar un llave o dos (según la documentación de Genexus, ver <a href="https://www.genexus.com/developers/websac?en,,,29369;;" target="_blank">SAC 29369</a>, 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 <b>GetEncryptionKey() </b>(ver <a href="https://wiki.genexus.com/commwiki/servlet/wiki?8385,GetEncryptionKey+Function," target="_blank">doc</a> respectivo de la función para más detalles). </li>
<li>Crear el <b>archivo de texto plano Application.Key</b> (ubicarla en la<i><b> raiz de la KB, del proyecto</b></i>, para que el archivo<b> web.config</b> pueda ser actualizado con los parámetros respectivos cifrados y en la <i><b>carpeta Web del modelo generado</b></i> para que las clases respectivas puedan descifrar los parámetros).</li>
<li>Editar el archivo creado con las "keys" generadas.</li>
<br /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP1WCrspu_hrutqO670Zg_MomBDMS_wSvI_0V5Ms4oVKDX9iYph3xz321S9IFgkcr3TnzgeyQynTU4K_aGmb3tCCf4a-J6DsxCNTb72R0LAs58dO8e8PNDDU2qKHwXMM4rdbGFbREJpQ/s1600/appkey.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="157" data-original-width="458" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP1WCrspu_hrutqO670Zg_MomBDMS_wSvI_0V5Ms4oVKDX9iYph3xz321S9IFgkcr3TnzgeyQynTU4K_aGmb3tCCf4a-J6DsxCNTb72R0LAs58dO8e8PNDDU2qKHwXMM4rdbGFbREJpQ/s400/appkey.PNG" width="400" /></a></div>
<div style="text-align: center;">
<br /></div>
<li>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.</li>
</ol>
</div>
Para <b><u>generar de forma automática los enlaces cifrados</u></b> para poder compartirlos, se usó el método Link del objeto recibiendo los parámetros respectivos.<br />
<br />
<code>
<span style="font-size: small;">&Var = &urlsite + Link(WebPanel, &param1, &param2)</span><br />
</code><br />
o<br />
<br />
<code>
<span style="font-size: small;">&Var = &urlsite + WebPanel.Link(&param1, &param2)</span>
</code><br />
<br />
En la captura pueden observar el cifrado de los parámetros llamando una Transacción.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnnF-QsL3kin3fqbKrrMtdC5nx9DUtQYTVyFTTwuN32LkFc040ajvfbR_-mMrzMuA7L5wcCBZq0z-WPPhzWfWwLFJAKoqrzaq6S_A0S6B2-I-goBUrR_vWvH21kDXKpjzJ9RyAgzWtfQ/s1600/txencrypt.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="279" data-original-width="760" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnnF-QsL3kin3fqbKrrMtdC5nx9DUtQYTVyFTTwuN32LkFc040ajvfbR_-mMrzMuA7L5wcCBZq0z-WPPhzWfWwLFJAKoqrzaq6S_A0S6B2-I-goBUrR_vWvH21kDXKpjzJ9RyAgzWtfQ/s640/txencrypt.PNG" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
Quedó pendiente para una próxima entrada el <b>cifrado manual de los parámetros </b><a href="http://trabajandocongenexus.blogspot.com/2017/06/encrypt-url-parameters-cifrado-manual.html" target="_blank">(ver enlace).</a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Si desean<b> configurar una clase (dll)</b> y no un archivo <b>que controle las "keys"</b> ver el <a href="https://www.genexus.com/developers/websac?en,,,29874;;" target="_blank">SAC 29874</a>.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4569838193433482816.post-70133328594718600672016-08-11T16:13:00.000-05:002016-08-11T16:34:00.827-05:00 Modificar un tag específico de un Archivo XML en GenexusBueno entre idas y venidas las necesidades apremian, por hoy modificar un tag específico de un Archivo XML.<br />
<br />
Ahora si manos a la obra.<br />
<br />
Primero obtener el contenido del tag que necesitamos modificar. Para ello leyendo un poco del Data Type <a href="http://wiki.genexus.com/commwiki/servlet/wiki?6928,XMLReader+Data+Type," target="_blank">XMLReader </a>notamos que podemos usar la función <a href="http://wiki.genexus.com/commwiki/servlet/wiki?7048,ReadType+Method," target="_blank">ReadType </a>para obtener el contenido del tag especificado y mediante la función <b><i>Value </i></b>obtener su valor.<br />
<br />
<code>
<span style="font-size: small;">&XMLReader.Open(&filePath)</span><br />
<span style="font-size: small;">&XMLReader.ReadType(1,"tag")</span><br />
<span style="font-size: small;">&tagValue = &XMLReader.Value</span><br />
<span style="font-size: small;">&XMLReader.Close()</span><br />
</code>
<br />
En segundo lugar necesitamos obtener el contenido del archivo mediante el DataType <a href="http://wiki.genexus.com/commwiki/servlet/wiki?6915,File%20data%20type" target="_blank">File </a>(más información del manejo de archivos <a href="http://wiki.genexus.com/commwiki/servlet/wiki?24070,File+data+type%3A+Text+file+handling," target="_blank">aquí</a>) y almacenar su contenido en un Varchar, en mi caso en la variable de nombre <i><b>&XML</b></i>.<br />
<br />
<code>
<span style="font-size: small;">&File.Source = &filePath</span><br />
<span style="font-size: small;">&File.OpenRead()</span><br />
<span style="font-size: small;">&XML = &File.ReadAllText()</span><br />
<span style="font-size: small;">&File.Close()</span><br />
</span></code>
<br />
Tercero, armar dos Strings o Varchar, uno para <i><b>búsqueda </b></i>y otro para <i><b>reemplazo </b></i>dentro del String o Varchar obtenido anteriormente, que usaremos con la función <a href="http://wiki.genexus.com/commwiki/servlet/wiki?8505,StrReplace%20function" target="_blank">StrReplace</a>.<br />
<br />
<code>
<span style="font-size: small;">&search = "<tag>" + &tagValue + "</tag>"</span><br />
<span style="font-size: small;">&replace = "<tag>"+ &newTagValue.ToString().Trim()+"</tag>"</span><br />
<span style="font-size: small;">&XMLModified = StrReplace(&XML, &search, &replace)</span><br />
</code>
<br />
Por último <i><b>sobreescribimos </b></i>el <i><b>archivo XML</b></i> con el nuevo contenido.<br />
<br />
<code>
<span style="font-size: small;">&File.OpenWrite(&filePath)</span><br />
<span style="font-size: small;">&File.WriteAllText(&XMLModified)</span><br />
<span style="font-size: small;">&File.Close()</span><br />
</code>
<br />
<b>PD</b>: Para control de errores<br />
<br />
sobre el XMLReader<br />
<br />
<code>
<span style="font-size: small;">&XMLReader.ErrCode</span><br />
<span style="font-size: small;">&XMLReader.ErrDescription</span><br />
</code>
<br />
sobre el Data Type File<br />
<br />
<code>
<span style="font-size: small;">&File.ErrCode</span><br />
<span style="font-size: small;">&File.ErrDescription</span><br />
</code>
<br />
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4569838193433482816.post-55697041541745757802016-08-08T12:06:00.000-05:002016-08-09T09:19:36.933-05:00Aplicación Java no despliega sobre Tomcat 8 en Genexus<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJG8gs8C2SPNkAO8lqenNpGLrFjLWsTcQ3Sm3CVIbB_YAA6V8N7uLGhXziRw1-eYt1rQJbNimx9106R1eL8Tr_LK1jIOPJJiYwrn3TV2OxyU9rpQCa87Ue0vjPHQwvCTrwgV7yf1m2BQ/s1600/tomcatManager.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJG8gs8C2SPNkAO8lqenNpGLrFjLWsTcQ3Sm3CVIbB_YAA6V8N7uLGhXziRw1-eYt1rQJbNimx9106R1eL8Tr_LK1jIOPJJiYwrn3TV2OxyU9rpQCa87Ue0vjPHQwvCTrwgV7yf1m2BQ/s640/tomcatManager.PNG" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<br />
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:<br />
<b><i><br /></i></b>
<br />
<div>
<b><i>Caused by: java.lang.NoClassDefFoundError: artech/security/api/gamrefreshtoken</i></b><br />
<br />
pero googleando un poco me topo con el <a href="http://www2.gxtechnical.com/main21/hscver21.aspx?S%3B15%3B4%3B61%3B2%3B1%3BO%3B,2,31566" target="_blank">SAC#31566</a> que explica las configuraciones pertinentes para Tomcat 7, asi que a probar un poco las mismas para ver si funcionan sobre Tomcat 8.<br />
<br />
Se editó justo lo que piden las configuraciones:<br />
<ul>
<li>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.</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKMbVPlppt0nnluyFgIihVpeTSaA1eXAqcTGy4Txr76tMOQQyhQ-0QqUTlIUe0GNTFAvzPIcyifC5ZXY36Ll1bkfEkQzumPiJHuQqU9GETS7sRLbwkdGq0yIkgOkOCwut1yV49UkJ6DQ/s1600/genexus+conf.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKMbVPlppt0nnluyFgIihVpeTSaA1eXAqcTGy4Txr76tMOQQyhQ-0QqUTlIUe0GNTFAvzPIcyifC5ZXY36Ll1bkfEkQzumPiJHuQqU9GETS7sRLbwkdGq0yIkgOkOCwut1yV49UkJ6DQ/s640/genexus+conf.PNG" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
</div>
<ul>
<li>Utilizar la propiedad Java Package name y especificar un valor. (Por defecto ya venía configurada)</li>
</ul>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilHdSVX8Yj29QSYcGZNFhUDvPOZwoImzotRxSg3kEiDQ4GXRIYH8oQGjPJNZ9Qp4ZeqnGNESkK_9MJtDydLW1ZHSUrbw4vjUoF-nNxhk1z3S13CmWnlk7E4iiQOPQFZV32iWxkfV9Btw/s1600/packagename.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilHdSVX8Yj29QSYcGZNFhUDvPOZwoImzotRxSg3kEiDQ4GXRIYH8oQGjPJNZ9Qp4ZeqnGNESkK_9MJtDydLW1ZHSUrbw4vjUoF-nNxhk1z3S13CmWnlk7E4iiQOPQFZV32iWxkfV9Btw/s640/packagename.PNG" width="640" /></a></div>
<br /></div>
<div>
<br /></div>
<div>
Y arrancando la app y accediendo al path correspondiente ya se despliega correctamente.</div>
<div>
<br /></div>
<div>
<i><b>PD: </b></i>Antes tocó solucionar otro error de clases no encontradas para la libreria gxscanner.jar:</div>
<div>
<br />
<i><b>java.lang.ClassNotFoundException: com.genexus.webpanels.GXJarScanner</b></i><br />
<br />
o<br />
<br />
<i><b>Caused by: java.lang.ClassNotFoundException: com.genexus.webpanels.GXJarScanner</b></i></div>
<div>
<br /></div>
<div>
Que se solucionó incorporando la librería correspondiente en la carpeta lib de la aplicación en Tomcat descargada del site oficial de Genexus. <a href="https://www.genexus.com/developers/DownloadCenter?E,,,4458;;" target="_blank">Download</a>. Les dejó tambien el acceso al <a href="https://www.genexus.com/developers/websac?en,,,36031;;" target="_blank">SAC#36031</a> correspondiente (deben estar registrados en el site de Genexus para su descarga)</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4569838193433482816.post-35083018582083086172016-06-16T13:21:00.001-05:002016-07-01T17:17:43.042-05:00Cliente Nativo Android para consumir Servicios Web SOAP y Restful generados en Genexus<div style="text-align: justify;">
De manera similar a la usada en Genexus con el HttpClient para configurar la llamada al servicio (Ver Entrada Anterior para <a href="http://trabajandocongenexus.blogspot.com/2016/06/generar-web-services-soap-y-restful-en.html" target="_blank">Consumir y Generar Servicios desde Genexus</a>), de la misma forma se usará un tipo de objeto específico para esta tarea en Android. </div>
<br />
<div style="text-align: justify;">
Antes se usaban las clases de la biblioteca de Apache como el HttpClient, HttpRequest y HttpRespose para manejar las solicitudes al Servidor, pero a partir del Android 6.0 (API 23) se ha cambiado (<a href="https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html" target="_blank">ver cambios de la API 23</a>) al uso de la Clase HttpURLConnection, más eficiente en el uso de la red y el manejo de la caché. La misma que usaremos en el presente ejemplo para los clientes de los servicios que creamos en Genexus anteriormente.<br />
<br /></div>
<h3>
Cliente Nativo Android para servicio REST de Genexus</h3>
<div style="text-align: justify;">
Bueno ahora si vamos con la implementación del Cliente para el servicio REST construido en Genexus, El código a explicar no fue implementado desde cero sino adaptado principalmente de <a href="http://www.hermosaprogramacion.com/2015/01/android-httpurlconnection/" target="_blank">Aquí</a> y otras cositas traídas desde <a href="https://ihofmann.wordpress.com/2012/08/09/restful-web-services-with-json-in-android/" target="_blank">Aquí</a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Así que lo que haré es proceder a explicar un poco la lógica del código y las Clases usadas. Para posteriormente dejarlos con el código completo implementado en la clase respectiva.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Como mencionábamos ahora se usará la clase HttpURLConnection que mediante un cast desde un objeto url permite configurar todas las opciones de la conexión como son tiempo de timeout, entre otras. Principalmente nos interesa las opciones setRequestMethod como POST y setReuqestProperty como “Content-Type” application/json“ ya que son los parámetros con los que Genexus construye el servicio Web.</div>
<pre class="brush: plain; gutter: false; toolbar: false;">HttpURLConnection urlConnection = null;
URL urlToRequest = new URL(serviceUrl);
urlConnection = (HttpURLConnection) urlToRequest.openConnection();
urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
urlConnection.setReadTimeout(DATARETRIEVAL_TIMEOUT);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
</pre>
<span style="text-align: justify;">Otro punto importante es no olvidar setear las configuraciones necesarias para permitir el envio de parametros y la recepcion de una respuesta.</span><br />
<pre class="brush: plain; gutter: false; toolbar: false;">urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);}
</pre>
<div>
<div style="text-align: justify;">
Por último para manejar el parámetro a enviar al servicio web se usa el Formato JSON, basándonos en el nombre del parámetro del procedure (ApplicationId) y en la respuesta obtenida en el cliente construido en Genexus anteriormente en formato JSON, construimos a mano en un String el parámetro a Enviar. Adicionalmente configuramos el tamaño del cuerpo a enviar en la petición.</div>
<pre class="brush: plain; gutter: false; toolbar: false;">String body = "{\"ApplicationId\":1}";
urlConnection.setFixedLengthStreamingMode(body.getBytes().length);</pre>
<div style="text-align: justify;">
Para enviar el parámetro respectivo al servidor en nuestra petición se debe usar un OutputSteam que se encargara de esta tarea.</div>
<pre class="brush: plain; gutter: false; toolbar: false;">byte[] outputInBytes = body.getBytes("UTF-8");
OutputStream os = new BufferedOutputStream(urlConnection.getOutputStream());
os.write(outputInBytes);
os.flush();
os.close();
</pre>
<div class="MsoNormal">
<span style="text-align: justify;">Por último de manera similar para manejar la respuesta del server se usa un objeto de la Clase InputStream obtenido del objeto urlConnection. El mismo que ya puede ser usado para convertirlo a un String o JSON.</span></div>
<pre class="brush: plain; gutter: false; toolbar: false;">InputStream in = new BufferedInputStream(urlConnection.getInputStream());
</pre>
<div class="MsoNormal">
<span style="text-align: justify;">Bueno ahora si la Clase completa como se prometió anteriormente.</span></div>
<div class="MsoNormal">
<br />
<a href="https://drive.google.com/uc?export=view&id=0B1m-etNRM2Gtdk9FUUZaWWh4N1k" target="_blank">Descarga Aquí.</a></div>
<div class="MsoNormal">
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">Y uso estas líneas para imprimir el resultado obtenido del servicio Rest en consola pasando como parámetro la url del Servicio Rest construido en Genexus:</span></div>
<pre class="brush: plain; gutter: false; toolbar: false;">JSONObject response = restservice.requestWebService("http://192.168.2.128/IAMEV3.NetEnvironment/rest/getapplicationsrest");
if (response.length() == 0){
Log.i("MyHttpClientLibrary", "is null");
}else {
Log.i("MyHttpClientLibrary", response.toString());
}
</pre>
<div style="text-align: justify;">
Importando la librerías respectivas</div>
<pre class="brush: plain; gutter: false; toolbar: false;">import org.json.JSONObject;
import android.util.Log;
</pre>
<div class="MsoNormal">
<br /></div>
<h3>
Cliente Nativo Android para servicio SOAP de Genexus</h3>
<h2>
<o:p></o:p></h2>
<div style="text-align: justify;">
De manera similar al Cliente Rest construido anteriormente se usará el objeto HttpUrlConnection un OutputStream para enviar el body construido mediante un String con la única diferencia que en este caso será con estructura xml, y un ImputStream para manejar la respuesta del servidor. El código base usado lo pueden ver <a href="http://stackoverflow.com/questions/6929180/rest-and-soap-webservice-in-android" target="_blank">Aquí</a>.</div>
<br />
<div style="text-align: justify;">
Si revisan el código básicamente es el mismo salvo la requestProperty “Content-Type” que ahora es “text/xml”</div>
<pre class="brush: plain; gutter: false; toolbar: false;">httpURLConnection.setRequestProperty("Content-Type", "text/xml");
</pre>
<div style="text-align: justify;">
y las funciones createSoapHeader y getReqData que construyen el parámetro o body a enviar el server en fomato xml recibido por el Servicio Soap de Genexus. De manera similar al servicio explicado anteriormente, para construir el body o parámetro a enviar al servidor, se uso el wsdl del servicio, y las pruebas por Genexus para conocer como estructura Genexus la respuesta y el SOAClient mencionado en la entrada anterior para ver la trama cruda devuelta y configurar la cabecera y el cuerpo a enviar.</div>
<br />
<div style="text-align: justify;">
Se recomienda observar principalmente la línea o el tag siguiente que contiene como namespace el nombre de la KB usada y el nombre de la función a usar “getApplications.Execute”</div>
</div>
<div>
<pre class="brush: plain; gutter: false; toolbar: false;"><getApplications.Execute xmlns="IAMEV3"> </getApplications.Execute>
</pre>
<div style="text-align: justify;">
Observar el tag ApplicationId que acogen el parámetro usado en el servicio.</div>
<pre class="brush: plain; gutter: false; toolbar: false;"><Applicationid xmlns="IAMEV3">1</Applicationid>
</pre>
<span style="text-align: justify;">Y por último los tags que acogen el cuerpo y los tags internos</span><span style="text-align: justify;"> respectivos.</span><br />
<pre class="brush: plain; gutter: false; toolbar: false;"><SOAP-ENV:Body> </SOAP-ENV:Body>
<SOAP-ENV:Envelope> </SOAP-ENV:Envelope>
</pre>
</div>
<span style="text-align: justify;">A continuación se muestra el código completo de la clase creada.</span><br />
<div style="text-align: justify;">
<br />
<a href="https://drive.google.com/uc?export=view&id=0B1m-etNRM2GtQjlkXzZqYnZOZEk" style="text-align: start;" target="_blank">Descarga Aquí.</a></div>
<br />
Por último para llamar a la clase correspondiente usamos:<br />
<pre class="brush: plain; gutter: false; toolbar: false;">SoapConsumer soapConsumer = new SoapConsumer();
String response = soapConsumer.callSOAPWebService("http://192.168.2.128/IAMEV3.NetEnvironment/agetapplications.aspx?wsdl");
Log.i("Soap Service: " , response);
</pre>
Obsérvese que se envía como url el wsdl creado en Genexus.<br />
<br />
<div style="text-align: justify;">
Todo el código mostrado es solo un ejemplo básico de como consumir los servicios Web creados en Genexus usando las nuevas clases del API de Android y enfocándose en el formato que debe tener los parámetros de entrada principalmente.</div>
<br />
<div style="text-align: justify;">
Adicionalmente se podría usar clases especializadas para crear el body o los parámetros a usar para la petición al servidor ya sean XML o JSON, o incluso manejar unos parsers adecuados para tratar la respuesta del Servidor.</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4569838193433482816.post-45260883915062441032016-06-14T09:48:00.000-05:002016-06-17T16:15:04.315-05:00Generar Web Services SOAP y RESTful en Genexus y Consumirlos desde Cliente Nativo Android y App Web Genexus<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br />
Para está entrada se creará dos tipos de servicios (SOAP y RESTful) desde el IDE de Genexus en <b>Ambiente Web</b> para <b>C#</b> (C sharp). Adicionalmente se creará sus respectivos Clientes que consuman dichos servicios tanto desde Genexus como desde un Cliente Nativo Android.</div>
<div style="text-align: justify;">
<span style="font-size: small; font-weight: normal;"><br /></span></div>
<h2 style="text-align: center;">
<span style="font-size: large;">Servidor</span></h2>
<div style="text-align: justify;">
Para ambos servicios se usará el objeto <b>"Procedure"</b> de Genexus más ciertas configuraciones adicionales para establecer el servicio necesitado. Se tiene una <b>"Transacción"</b> Application con tres campos Id (Numeric), Name (VarChar), ClientId (VarChar) (Figura 1.), ClientSecret (VarChar). Se ha creado un objeto <b>"SDT" </b>basado en estos tres campos (Figura 2).<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaIFpnrZcBexYY3tfvclg-goOwRPSUGaAF8J-vOx6g7UlbBxMdlzYXNbHttdkEiQAehTSb22r1V2nZ3bD185a7e6rQMn1EMvAiKX-1h660XDbZCJuBDtF4zxcJelJp-2IJcOSo5l51bw/s1600/Tx_WS.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="115" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaIFpnrZcBexYY3tfvclg-goOwRPSUGaAF8J-vOx6g7UlbBxMdlzYXNbHttdkEiQAehTSb22r1V2nZ3bD185a7e6rQMn1EMvAiKX-1h660XDbZCJuBDtF4zxcJelJp-2IJcOSo5l51bw/s400/Tx_WS.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><b>Fig 1. Transsacción</b></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh103mI5907BTwId6ySOWu63xS5ZIJ64tEVU4SvXUK_iyMSAX5aLy9y2A28YbPZ98fwdb4b36kL_Ol6d3NuTsn40tWW3vtPcB5iCQVbo6_STa4S1YdqpVJRsEPp-gAO9hlX32uy4ycFYw/s1600/SDT.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh103mI5907BTwId6ySOWu63xS5ZIJ64tEVU4SvXUK_iyMSAX5aLy9y2A28YbPZ98fwdb4b36kL_Ol6d3NuTsn40tWW3vtPcB5iCQVbo6_STa4S1YdqpVJRsEPp-gAO9hlX32uy4ycFYw/s400/SDT.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;"><b>Fig 2. SDT</b></span></div>
<h4>
</h4>
<div>
<br /></div>
<h4>
Servicio Web Tipo SOAP</h4>
<div style="text-align: justify;">
Como ya se mencionó para habilitar los servicios Web se usa el objeto <b>"Procedure"</b>. Así que crearemos un objeto de dicho tipo del nombre <b>"getApplications"</b> para el servicio SOAP.</div>
<br />
<div style="text-align: justify;">
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.</div>
<br />
<code>
<span style="font-size: small;">
for each</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="font-size: small;"> where ApplicationId = &ApplicationId</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="font-size: small;"> &sdtApplication = new()</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="font-size: small;"> &sdtApplication.ApplicationName = ApplicationName</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="font-size: small;"> &sdtApplication.ApplicationClientId = ApplicationClientId</span><br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="font-size: small;"> &sdtApplication.ApplicationClientSecret = ApplicationClientSecret</span><br />
<span style="font-size: small;">endfor</span><span class="Apple-tab-span" style="white-space: pre;"> </span>
</code><br />
<br />
<div style="text-align: justify;">
Posteriormente, en la sección de parámetros tenemos como entrada la variable "ApplicationId" y como salida la variable "sdtApplication".</div>
<br />
<div style="text-align: center;">
<code>
<span style="font-size: small;">parm(in: &ApplicationId, out:&sdtApplication);</span></code></div>
<br />
En las propiedades del objeto configuramos las opciones:<br />
<ul>
<li>Call Protocol: SOAP</li>
<li>Main Program: True</li>
</ul>
Para probar la generación del servicio se puede acceder a la url:<br />
<div style="text-align: center;">
<br />
<span style="text-align: center;">http://[localhost o ip local]/[Nombre de la la KB].[Ambiente Web de la KB]</span><b style="text-align: center;">/a[nombre del procedure].aspx</b><br />
<b style="text-align: center;"><br /></b>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoBjwndmVUzVlwrP7VYdV8CZPIC2aAu1fbbiywq4TKSnlpTZMDSX1S79brrPwXlOWzHClQZglLoW6_5DlhLG4HmZ-4G4Po6eLzqM7GZNBodDSWRpo3NSKCPnceo2WELX9WwQqxDGwfwQ/s1600/testsoap.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="93" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoBjwndmVUzVlwrP7VYdV8CZPIC2aAu1fbbiywq4TKSnlpTZMDSX1S79brrPwXlOWzHClQZglLoW6_5DlhLG4HmZ-4G4Po6eLzqM7GZNBodDSWRpo3NSKCPnceo2WELX9WwQqxDGwfwQ/s400/testsoap.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<b><span style="font-size: x-small;">Fig 3. URL de Servicio SOAP</span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
Para unas pruebas más exhaustivas se puede instalar <b>"SOA Client"</b> en mi caso el add-On para el Navegador Firefox (<a href="https://addons.mozilla.org/en-US/firefox/addon/soa-client/?src=api" target="_blank">Descarga Aquí</a>) y añadiendo en la ruta anterior el parámetro <b>?wsdl</b> usar directamente el servicio Web como se puede observar en la figura 4.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggwgOjL8p_ywNZyatYpISnVeA3zqQRGiCsLrHakj6S5GiXtL9W0RAMcLImfBxddFMZ4IrQQenqYexGjcHuOFxflcVEcw8uzM9Lc1Ep2YyCqgs2LYPQBONJWZPAxJ-Bl1ygyI0c1tYZzg/s1600/soaclient.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="328" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggwgOjL8p_ywNZyatYpISnVeA3zqQRGiCsLrHakj6S5GiXtL9W0RAMcLImfBxddFMZ4IrQQenqYexGjcHuOFxflcVEcw8uzM9Lc1Ep2YyCqgs2LYPQBONJWZPAxJ-Bl1ygyI0c1tYZzg/s640/soaclient.PNG" width="640" /></a></div>
<b style="text-align: center;"><b><span style="font-size: x-small;">Fig 4. Consumo de SOAP mediante SOA Client</span></b></b></div>
<br />
<h4>
</h4>
<h4>
Servicio Web Tipo RESTful</h4>
<div style="text-align: justify;">
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á <b>"getApplicationsRest"</b>.</div>
<br />
Pero en el cual configuramos las siguientes opciones de las propiedades:<br />
<ul>
<li>Expose as a web Service: True</li>
<li>Rest Protocol: True</li>
</ul>
Para probar la generación del servicio se puede acceder a la url:<br />
<br />
<div style="text-align: center;">
<span style="text-align: center;">
http://[localhost o ip local]/[Nombre de la la KB].[Ambiente Web de la KB]<b>/rest/[nombre del Procedure]</b></span><br />
<br />
<div style="text-align: justify;">
De manera similar para otro tipo de pruebas se puede instalar el Add-On "Rest Client" sobre el Navegador Firefox (<a href="https://addons.mozilla.org/fr/firefox/addon/restclient/" target="_blank">Descarga Aquí</a>) ver la figura 5.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfxcVTyxqhNVNEyD4oMeNJ819gC2NWqz6rW5GVRdqK4frm6HGqEBNqXI0cNf2upYfkLlIZRkqSauxZiv3vOCN-YTTFfyyNWamr4XpdSQaqukeb_KPn_8_usS_zAWMWuIEQZqn9ZDxb-A/s1600/testres.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfxcVTyxqhNVNEyD4oMeNJ819gC2NWqz6rW5GVRdqK4frm6HGqEBNqXI0cNf2upYfkLlIZRkqSauxZiv3vOCN-YTTFfyyNWamr4XpdSQaqukeb_KPn_8_usS_zAWMWuIEQZqn9ZDxb-A/s640/testres.PNG" width="640" /></a></div>
<div style="text-align: center;">
<b style="text-align: center;"><b><span style="font-size: x-small;">Fig 5. Consumo de REST mediante Rest Client</span></b></b></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;"><br /></span></b></div>
</div>
<h2 style="text-align: center;">
<span style="font-size: large;">Cliente</span></h2>
<h4>
Cliente Web Genexus para servicio SOAP</h4>
<div style="text-align: justify;">
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:</div>
<br />
<ul>
<li>El NameSpace en el que se ejecuta el Servicio, en este caso el nombre de la KB.</li>
<li>El nombre del método o Acción a llamar.</li>
<li>Los parámetros de entrada y el tipo de dato.</li>
<li>Los parámetros de salida y su tipo de dato.</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB_Fzgf7xQ3k8lYYXc_0CE-HLHEeTxBQ1b0m1tzL6r1lodVasB8X3FmHJcOJRnf2X0hdPhnfHKlj3bDWlVp59JeYCibpB9HWLR6e5AkYlPTmTen3FNP2LoevYkNPH9xoiL_yUDd6NxEQ/s1600/wsdl.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB_Fzgf7xQ3k8lYYXc_0CE-HLHEeTxBQ1b0m1tzL6r1lodVasB8X3FmHJcOJRnf2X0hdPhnfHKlj3bDWlVp59JeYCibpB9HWLR6e5AkYlPTmTen3FNP2LoevYkNPH9xoiL_yUDd6NxEQ/s400/wsdl.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: center;"><b><span style="font-size: x-small;">Fig 6. WSDL del servicio SOAP construido en Genexus.</span></b></b></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: justify;">
Toda esta información es usada por Genexus en un <b>Wizard </b>para construir un <b>"External Object"</b> y un <b>"SDT"</b>, que consuma el servicio y lo almacene respectivamente.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Podemos usar una nueva KB, o la misma si se desea, y nos ubicamos en la opción del menú <b>Tools / Application Integration / WSDL Import</b></div>
<div style="text-align: justify;">
<b><br /></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAJWP7s9Ph8oG3Y2g4iY0A5cdQSAELRn8i1_8fN93Lqh5tnQW-xf59iH9e10LRuOYhqW1DIdG8ndirwHhsLzot8QN23TRkBEHncZth7XDy3MVY49ZtgBqJjiWMqLA2VX3NvR7lhdTKaw/s1600/wizars+menu.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAJWP7s9Ph8oG3Y2g4iY0A5cdQSAELRn8i1_8fN93Lqh5tnQW-xf59iH9e10LRuOYhqW1DIdG8ndirwHhsLzot8QN23TRkBEHncZth7XDy3MVY49ZtgBqJjiWMqLA2VX3NvR7lhdTKaw/s320/wizars+menu.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: center;"><b><span style="font-size: x-small;">Fig 7. Acceso al WSDL Import.</span></b></b></div>
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: center;"><b><span style="font-size: x-small;"><br /></span></b></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;">Obtendremos la pantalla correspondiente donde ingresaremos la url respectiva. Ver figura 7.</span></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYjZTv0K7EXZcWE-TrkKDDeUdZ12CxmsW3WjkXd2oP7XpOAq4F2Z1KI7C3aoIB0uaXLyZnM3eug9Lyf7KqTOPh7wp52KvE3OEStbrlfk-wQ3izYS9p8HHrlMBsw96wfoBjYwprHIttCA/s1600/wsld+import.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="260" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYjZTv0K7EXZcWE-TrkKDDeUdZ12CxmsW3WjkXd2oP7XpOAq4F2Z1KI7C3aoIB0uaXLyZnM3eug9Lyf7KqTOPh7wp52KvE3OEStbrlfk-wQ3izYS9p8HHrlMBsw96wfoBjYwprHIttCA/s400/wsld+import.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: center;"><b><span style="font-size: x-small;">Fig 8. WSDL Import.</span></b></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;">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.</span></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW6vtPpppoowG8wPuD12BrUBd4xXEIfjO8CTe2pVSEFdBDAA5Q_65qbc-Xazbc56jLvhNk7L9yF1KNOoxHA-b8piCBd8IMqXoicA3qOqgl6NaigFKI5kCLkXtU0fXSbjtXid7ZtCWeTg/s1600/EOSoap.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW6vtPpppoowG8wPuD12BrUBd4xXEIfjO8CTe2pVSEFdBDAA5Q_65qbc-Xazbc56jLvhNk7L9yF1KNOoxHA-b8piCBd8IMqXoicA3qOqgl6NaigFKI5kCLkXtU0fXSbjtXid7ZtCWeTg/s640/EOSoap.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: center;"><b><span style="font-size: x-small;">Fig 9. External Object creado por WSDL Import.</span></b></b></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD3WLe1-4cTaeQcvaj30QypfLtwBdfh4hSZUsRfkFOehKZGOYdzxYS_KxFRR_8FncYHFMYdECh4jpCkEQ0xFtaZVkAmqmFivWp8fJaSkP8yTyPk_uzdn-n0GsR7roVAH1Y0gMH2IJlBQ/s1600/stdsoap.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD3WLe1-4cTaeQcvaj30QypfLtwBdfh4hSZUsRfkFOehKZGOYdzxYS_KxFRR_8FncYHFMYdECh4jpCkEQ0xFtaZVkAmqmFivWp8fJaSkP8yTyPk_uzdn-n0GsR7roVAH1Y0gMH2IJlBQ/s640/stdsoap.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<b style="text-align: center;"><b style="text-align: center;"><b><span style="font-size: x-small;">Fig 10. SDT creado por WSDL Import.</span></b></b></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="text-align: center;"><span style="text-align: start;">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:</span></span></div>
<div class="separator" style="clear: both; text-align: justify;">
<b style="text-align: center;"><span style="font-weight: normal; text-align: start;"><br /></span></b></div>
<div style="text-align: center;">
<code>
<span style="font-size: small;">&getAppsdtApplication = &getApplications.Execute(&ApplicationId)</span>
</code></div>
<div style="text-align: center;">
<b><br /></b></div>
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.<br />
<br />
<div>
<h4>
</h4>
<h4>
Cliente Web Genexus para servicio RESTful</h4>
<div style="text-align: justify;">
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 <b>HttpClient </b>para realizar la llamada al mismo y capturar la respuesta del servidor.</div>
<br />
Adicionalmente en el HttpClient, se debe configurar:<br />
<ul>
<li>El <b>Servidor </b>al cual se va a acceder.</li>
<li>La <b>Url base</b> del Servicio Rest.</li>
<li>El <b>puerto</b> usado para la conexión.</li>
<li>El cuerpo o <b>body</b>, es decir los parámetros de entrada en formato <b>JSON</b>.</li>
<li>La <b>cabecera </b>como tipo 'Content-type' y 'application/json'.</li>
<li>El <b>nombre del servicio</b> (en este caso el nombre del procedure) y el <b>Método Http</b> a usar (en base a la documentación de la Wiki de Genexus se debe usar siempre el método POST).</li>
</ul>
<div>
Todas estas configuraciones son visibles en el siguiente código:</div>
<br />
<code>
<span style="font-size: small;">
&httpclient.Host = "localhost" //Servidor</span><br />
<span style="font-size: small;">
&httpclient.Port = 80 //Puerto</span><br />
<span style="font-size: small;">
&httpclient.BaseUrl = "/IAMEV3.NetEnvironment/rest/" //Url Base</span><br />
<span style="font-size: small;">
&httpclient.AddHeader('Content-type','application/json') //Cabecera</span><br />
<span style="font-size: small;">
&httpclient.AddString('{"ApplicationId":1}') // body o parámetros de entrada en formato JSON
</span>
</code>
<br />
<div style="text-align: justify;">
Para ejecutar el cliente http se usa el método Execute especificando el método Http y el nombre del procedure.</div>
<br />
<div>
<code><span style="font-size: small;">&httpclient.Execute('POST','getapplicationsrest')</span></code></div>
</div>
<div>
<br /></div>
<div style="text-align: justify;">
Para la captura de la respuesta simplemente se puede hacer un String del HttpClient.</div>
<br />
<div>
<code><span style="font-size: small;">&httpclient.ToString()</span></code></div>
<br />
<div style="text-align: justify;">
Y para la visualización de Errores se puede usar los métodos ErrCode y ErrDescription del HttpClient.</div>
<br />
<br />
<div>
<code><span style="font-size: small;">
&httpclient.ErrCode</span><br /><span style="font-size: small;">
&httpclient.ErrDescription
</span></code>
</div>
<br />
<div>
<br /></div>
<div>
<h4>
</h4>
<h4>
Cliente Nativo Android para servicio SOAP y RESTful (Ver <a href="http://trabajandocongenexus.blogspot.com/2016/06/cliente-nativo-android-para-consumir.html" target="_blank">Aquí</a>)</h4>
</div>
Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-4569838193433482816.post-63257188890735186452016-02-22T13:10:00.000-05:002016-02-22T15:12:36.481-05:00Leer XML desde un String <div style="text-align: justify;">
Bueno el objetivo de esta entrada es permitir leer un XML desde un string (que puede ser obtenido mediante un Archivo o un Web Service, que no será tratado en la misma) y mediante el uso del Data type XMLReader procesarlo para que pueda ser usado en un SDT y todas las ventajas que este ofrece. Sin más que acotar empecemos.</div>
<br />
Se declaran las variables:<br />
<ul>
<li><b><i>mensaje</i></b> de tipo <i><b>Varchar(200)</b></i> o <i>LongVarChar (2M)</i> dependiendo del tamaño del texto. Esta variable contendrá el XML en forma de cadena de caracteres o de String.</li>
<li><b><i>XMLReader</i></b> de tipo <i><b>XMLReader</b></i>. Este tipo de objeto permitirá crear un lector para el procesamiento del formato XML. <a href="http://wiki.genexus.com/commwiki/servlet/wiki?6928,XMLReader+Data+Type," target="_blank"><span id="goog_1726265869"></span>click aquí<span id="goog_1726265870"></span></a> para más información.</li>
<li><b><i>XML</i></b> de tipo <i><b>Varchar(200)</b></i> o <i><b>LongVarChar (2M</b>) </i>dependiendo del tamaño del texto, esta variable almacenará el XML crudo como String o cadena.</li>
<li><b><i>SDT</i></b> de tipo del <i><b>SDT</b></i> especialmente construido para guardar la información del XML.</li>
</ul>
<br />
Y mediante el código fuente a explicar:<br />
<br />
<div style="text-align: justify;">
Básicamente en las variables anteriores ya se definió el funcionamiento del siguiente código salvó la merecida explicación de las funciones <i><b>Read()</b></i> que permite procesar la información desde el string hacia el objeto <b>XMLReader</b>; y la función <i><b>ReadRawXML()</b></i> que permite enviar el contenido del lector como XML hacia una variable, para que esta pueda ser usada en el llenado del <b>SDT</b> con la función <i><b>FromXML().</b></i></div><br />
<code>
<div style="text-align: justify;">
<span style="font-size: small;">
&XMLReader.OpenFromString(&mensaje)</span></div>
<div style="text-align: justify;">
<span style="font-size: small;">
&XMLReader.Read()</span></div>
<div style="text-align: justify;">
<span style="font-size: small;">
&XML = &XMLReader.ReadRawXML()</span></div>
<div style="text-align: justify;">
<span style="font-size: small;">
&SDT.FromXml(&XML)</span></div>
</code>Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-4569838193433482816.post-73408399719680692662016-02-19T10:39:00.002-05:002022-09-21T14:16:49.307-05:00Atajos de Teclado IDE GenexusAquí dejo un listado de los atajos de teclado que al menos yo uso más para el IDE de Genexus.<br />
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
F12</h4>
<div>
Permite navegar directo y abrir el objeto sobre el cual se encuentra ubicado el cursor.</div>
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
F4</h4>
<span style="font-weight: normal;">Permite desplegar la vista de propiedades del objeto.</span><br />
<span style="font-weight: normal;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKnUQwCwnq5CbSy1Inuqu95P3OqdwmO1e0TUs3dtXPWWT4sH3RtYKPA2_vXYveURQaZlthE1lUbqpEMGn8HgCfwKz6Ukq5MU2pWwyDJg5SlTSSm00JnaZJ7fCceDsczwi_D15V7CC_Ng/s1600/properties.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKnUQwCwnq5CbSy1Inuqu95P3OqdwmO1e0TUs3dtXPWWT4sH3RtYKPA2_vXYveURQaZlthE1lUbqpEMGn8HgCfwKz6Ukq5MU2pWwyDJg5SlTSSm00JnaZJ7fCceDsczwi_D15V7CC_Ng/s400/properties.PNG" width="271" /></a></div>
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
F5</h4>
<span style="font-weight: normal;">Permite Ejecutar la base de conocimiento (Run).</span><br />
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Ctrl + F</h4>
<span style="font-weight: normal;">Permite desplegar un cuadro de diálogo para hacer búsquedas de texto sobre el código.</span><br />
<span style="font-weight: normal;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSZHjVwLfixr4d0vd9t9NF-8ct8Xp_a2AUn1kWc1pzDtIIr7dy-J4bDfxLviel_aSH16Sb-KMRCDfSsRW3jvG3NRqViFFCYgPHgY_LUTz4NB2r08X0laR1KO__b-KAjhxefyihozS3mQ/s1600/find.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSZHjVwLfixr4d0vd9t9NF-8ct8Xp_a2AUn1kWc1pzDtIIr7dy-J4bDfxLviel_aSH16Sb-KMRCDfSsRW3jvG3NRqViFFCYgPHgY_LUTz4NB2r08X0laR1KO__b-KAjhxefyihozS3mQ/s400/find.PNG" width="400" /></a></div>
<div>
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Ctrl + H</h4>
<span style="font-weight: normal;">Permite desplegar un cuadro de diálogo para hacer reemplazos de texto sobre el código.</span><br />
<span style="font-weight: normal;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9AiYMWTjBT0lB0SBkiuP8fI4_wi-nUZnmuJajhoU2WV1S8oHEYOJXCS-IiEEZjUTgg09K9T7PP02n5O3w_EUqcW9uff020iPQcDjzErbgOmkqC3nstRWD-M_1jMbeqaQlSvNOhCRi7Q/s1600/Replace.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9AiYMWTjBT0lB0SBkiuP8fI4_wi-nUZnmuJajhoU2WV1S8oHEYOJXCS-IiEEZjUTgg09K9T7PP02n5O3w_EUqcW9uff020iPQcDjzErbgOmkqC3nstRWD-M_1jMbeqaQlSvNOhCRi7Q/s400/Replace.PNG" width="400" /></a></div>
<h4>
<div>
</div>
<div>
<br />
<br />
Ctrl + S</div>
</h4>
<span style="font-weight: normal;">P</span><span style="font-weight: normal;">ermite guardar los cambios del objeto sobre el que se está trabajando.</span><br />
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Ctrl + J</h4>
Permite desplegar la pestaña Work With Objects.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDsBMBFc3vKDEFvsZBhUsfwl0KshrvNlv3kd0UAiK3NkxB0CItBLiqbyOxrAHNsUKOAOkrV4tX6tqzGIqH9SqNwbLLpaidrY1E9xmHLN27nzxG9XJgs5-rllbvmsnJAIKwOBgWrXg4Lw/s1600/wwO.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="327" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDsBMBFc3vKDEFvsZBhUsfwl0KshrvNlv3kd0UAiK3NkxB0CItBLiqbyOxrAHNsUKOAOkrV4tX6tqzGIqH9SqNwbLLpaidrY1E9xmHLN27nzxG9XJgs5-rllbvmsnJAIKwOBgWrXg4Lw/s400/wwO.PNG" width="400" /></a></div>
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Ctrl + F12</h4>
<div>
Permite desplegar la pestaña de References (Referencias) del objeto.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimGmgZEU8hm5RUri3Z1y9I9uLzCJ9Vm5yJ4Tg950_q68KC0c_elHpMg18dXoVKyrgS_8DFEu6metCc2QUBi44ek9T9CR10SYF9kISQZG0SAgLXa3TdMThhLixisaAgCGZ3rZ4eHQy_KQ/s1600/references.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimGmgZEU8hm5RUri3Z1y9I9uLzCJ9Vm5yJ4Tg950_q68KC0c_elHpMg18dXoVKyrgS_8DFEu6metCc2QUBi44ek9T9CR10SYF9kISQZG0SAgLXa3TdMThhLixisaAgCGZ3rZ4eHQy_KQ/s400/references.PNG" width="400" /></a></div>
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Ctrl + Shift + H</h4>
<div>
Permite desplegar la pestaña de History (Histórico de cambios) del objecto.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9qN8eSkzGxYWK9GMeq4U2Yyf83jt05dgji1ct8D_L1G1anjoqVPG4lzDFliYLn181PpPpb3-xSeIp33YfYO06end89Rz9EbHAc0ZptWyFI7vnKOVqna3eO0UAY7TtAFMqUYL0ajUegg/s1600/history.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9qN8eSkzGxYWK9GMeq4U2Yyf83jt05dgji1ct8D_L1G1anjoqVPG4lzDFliYLn181PpPpb3-xSeIp33YfYO06end89Rz9EbHAc0ZptWyFI7vnKOVqna3eO0UAY7TtAFMqUYL0ajUegg/s400/history.PNG" width="400" /></a></div>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Ctrl + Shift + S</h4>
Permite guardar los cambios de todos los objetos que están siendo editados.<br />
<h4>
<br /></h4>
<h4>
Nota</h4>
<div style="text-align: justify;">
Adicionalmente los atajos ya conocidos de<b> Ctrl + C</b>, <b>Ctrl + V</b>, <b>Ctrl + X</b> (copy, paste and cut). Algunos de estos nos sirven solo para copiar, pegar o cortas objetos o código sino incluso para <i><b>trabajar con variable</b></i>s en el paso de un objeto a otro.<br />
<br /></div>
<div style="text-align: justify;">
Y obviamente los infaltables <b>Ctrl + Z</b> (deshacer un cambio) y <b>Ctrl + Y</b> (rehacer un cambio).</div>
<h4>
</h4>
<h4>
</h4>
<h4>
<br /></h4>
<h4>
Referencia Completa de los comandos</h4>
Genexus, Wiki,<a href="http://wiki.genexus.com/commwiki/servlet/wiki?5057,GeneXus+IDE%2FShortcuts," target="_blank"> site</a>.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4569838193433482816.post-24872554409080163082013-11-27T21:38:00.001-05:002016-02-19T11:36:10.940-05:00Imprimir un string en varias lineas de un reporte PDF<div style="text-align: justify;">
Bueno no se si les haya pasado, pero en mi caso me ocurrió que tenía un <b><i>string </i></b>o <i style="font-weight: bold;">varchar </i>o<i style="font-weight: bold;"> </i>como le llamen de un tamaño de <b><i>500 caracteres</i></b>, y que al momento de enviarlo a imprimir a un <i><b>reporte PDF</b></i> 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)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Es aquí cuando me enteré de la función <b><i>GXGetMLi</i></b>, 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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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 <b><i>contador </i></b>y un <b><i>for </i></b>y una que otra validación con un <b><i>if </i></b>y listo.</div>
<div style="text-align: justify;">
<br /></div>
<code>
<div style="text-align: justify;">
<span style="font-size: small;">For &contadorlinea = 1 to 5</span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> &lineaImprimir = GXGetMLi(&Descripcion, &contadorlinea, 100)</span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> if NOT &lineaImprimir.IsEmpty() AND &contadorlinea = 1</span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> print LineaDescripcion</span><br />
<span style="font-size: small;"> else</span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> if NOT &lineaImprimir.IsEmpty() </span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> print LineaDescripcion1</span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> endif</span></div>
<div style="text-align: justify;">
<span style="font-size: small;"> endif</span></div>
<div style="text-align: justify;">
<span style="font-size: small;">Endfor</span></div>
</code>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A tomar en consideración:</div>
<div style="text-align: justify;">
</div>
<ol>
<li style="text-align: justify;">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.</li>
<li style="text-align: justify;">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.</li>
<li style="text-align: justify;">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.</li>
<li style="text-align: justify;">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 <a href="http://trabajandocongenexus.blogspot.com/2013/11/eliminando-saltos-de-linea-de-un-string.html" target="_blank">click aquí</a> ).</li>
</ol>
<div>
<b><u>Nota:</u></b></div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
Para <b><i>.Net</i></b> me dijeron, pero ustedes pueden comprobarlo, que no hace falta esta codificación sino simplemente configurar en las <b><i>propiedades </i></b>de la variable a imprimir en la pestaña de Layout aquella que dice <b><i>Alignment </i></b>y colocar <i style="font-weight: bold;">MiddleJustify. </i>Si no les funciona ya saben que hacer.</div>
</div>
<div>
<br /></div>
<div>
<a href="https://drive.google.com/file/d/0B1m-etNRM2GtVkdIWGl6VG5WUnc/edit?usp=sharing" target="_blank">Descargar Ejemplo para Genexus EV2</a></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4569838193433482816.post-8400827207782607002013-11-25T21:27:00.002-05:002016-02-22T13:23:18.434-05:00Eliminando Saltos de línea de un String<div style="text-align: justify;">
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 <i><b>Chr</b> </i>y <b><i>StrReplace</i></b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Primero creamos una variable tipo Varchar para almacenar el salto de línea. En mi caso la nombrare<b><i> &LF</i></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Después almacenamos el valor del salto de línea mediante la función <b><i>CHR</i></b>, recibe como parámetro el código decimal del carácter (<i><b>Código ASCII</b></i>), el código decimal del salto de línea es <b><i>10</i></b>.</div>
<div style="text-align: justify;">
<br /></div>
<code>
<div style="text-align: justify;">
<span style="font-size: small;">&LF = CHR(10)</span></div>
</code>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Por último usamos la función <b><i>STRReplace </i></b>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).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<code>
<span style="font-size: small;">&String = STRReplace(&String, &LF.Trim(), " ")</span><br />
</code>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><a href="https://drive.google.com/file/d/0B1m-etNRM2GteVBIeUR3MUhBdEU/edit?usp=sharing" target="_blank">Descarga Export para Genexus EV2</a></span>
</div>
Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-4569838193433482816.post-66052286601611829632013-11-24T14:25:00.003-05:002017-05-22T14:05:39.997-05:00Abrir Web Panel en una nueva pestaña<div style="text-align: justify;">
Trabajando con este bendito Genexus me encontré con la necesidad de <b><i>abrir un WebPanel en otra pestaña del navegador desde una acción de la línea de un Grid</i>.</b> Adicionalmente necesitaba pasar unos<i> <b>parámetros</b></i> que construía en un<b> <i>Sub</i></b>. 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.</div>
<br />
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Bueno principalmente encontré tres opciones:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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:</div>
<ol>
<li style="text-align: justify;">Como mencione se debe codificar en el evento <i><b>Load</b></i> del Grid. Donde se tiene una <i><b>variable tipo imagen</b></i> agregada en las columnas del grid, la misma que posee la propiedad "<i><b>Link</b></i>" que es a la que vamos a igualar a la propiedad "<i><b>Link</b></i>" del <i><b>web panel</b></i> a abrir en una nueva pestaña.</li>
<br />
<code>
<div style="text-align: justify;">
<span style="font-size: small;">Event Load</span><br />
<span style="font-size: small;"> &NuevaVentana.LinkTarget = "_blank"</span><br />
<span style="font-size: small;"> &NuevaVentana.Link = WebPanel.Link(&Parametro)</span><br />
<span style="font-size: small;">EndEvent</span></div>
</code>
<br />
<li style="text-align: justify;">Está es la opción que utilice. Se crea un <i><b>Texblock</b></i> en el Web Panel y se especifica como Foramato "<i><b>HTML</b></i>" y mediante código <i><b>JavaScript</b></i> se realiza la llamada pertinente al Web Panel con su propiedad "<i><b>Link</b></i>" en el <i><b>Evento "Click"</b></i> de la variable correspondiente pasando los parámetros y llamando a los <i><b>Subs</b></i> respectivos.</li>
<br />
<code>
<div style="text-align: justify;">
<span style="font-size: small;">Event &NuevaVentana.Click</span><br />
<span style="font-size: small;"> do 'LlamadaSub'</span><br />
<div style="text-align: left;">
<span style="font-size: small;"> TextBlock.Caption='<script>window.open("'+WebPanel.Link(&Parametro)+'","Pagina Nueva");</script>'</span></div>
<span style="font-size: small;">EndEvent</span></div>
</code>
<div style="text-align: justify;">
<br />
<i><b>Se debe tomar en cuenta las comillas dobles y simples usadas en el JavaScript</b></i>.
</div>
<br />
<li style="text-align: justify;">Esta opción solo abre en una pantalla emergente conocida como <i><b>Pop Up</b></i>, pero con la peculiaridad de que se pueden<b><i> especificar</i></b> ciertos <b><i>parámetros</i></b> para su apertura. Esta operación se realiza mediante una variable tipo "<i><b>Window</b></i>"</li>
<br />
<code>
<div style="text-align: justify;">
<span style="font-size: small;">Event &NuevaVentana.Click</span><br />
<span style="font-size: small;"> &InWindow.Url = WebPanel.Link(&Parametro)</span><br />
<span style="font-size: small;"> &InWindow.Open()</span><br />
<span style="font-size: small;">EndEvent</span></div>
</code>
</ol>
<a href="https://drive.google.com/file/d/0B1m-etNRM2GtTklEa1N4R29kWms/edit?usp=sharing" target="_blank">Descarga Export para Genexus EV2</a><br />
<br />Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-4569838193433482816.post-56963018086038905862013-04-13T20:31:00.003-05:002013-04-13T20:41:39.953-05:00Muy pronto<h2 style="-webkit-font-smoothing: antialiased; border-bottom-color: rgb(204, 204, 204); border-bottom-style: solid; border-width: 0px 0px 1px; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 24px; margin: 0px 0px 10px; padding: 0px;">
Trabajando con Genexus</h2>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-bottom: 15px; margin-top: 10px; padding: 0px;">
Este blog será dedicado a mi <strong style="border: 0px; margin: 0px; padding: 0px;"><em style="border: 0px; margin: 0px; padding: 0px;">poca experiencia</em></strong> que vengo trabajando con la herramienta <strong style="border: 0px; margin: 0px; padding: 0px;">Genexus</strong>. Soluciones a ciertos problemas o errores medio comunes, uso de algunos user controls útiles, y otras cosas más.</div>
<div style="border: 0px; color: #333333; font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 22px; margin-top: 15px; padding: 0px;">
Muy pronto espérenme.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.genexus.com/media/design/style000001/00000001740000003700.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.genexus.com/media/design/style000001/00000001740000003700.png" /></a></div>
<br /></div>
<br />Unknownnoreply@blogger.com1