miércoles, 15 de agosto de 2012

Consumir un Web Service desde Oracle

Hace algún tiempo tuve la oportunidad (a petición de mi jefe) de investigar una forma de consumir un servicio web elaborado con .NET desde un procedimiento o función de Oracle.

Como apenas estaba conociendo esta base de datos y el tan interesante PL/SQL, imaginé que sería algo difícil de conseguir, pero eso es lo que me gusta, así que acepté el reto.

Busqué y encontré varias formas, pero definitivamente lo que más me convenció fué un paquete de oracle llamado SOAP API.

http://www.oracle-base.com/dba/script.php?category=miscellaneous&file=soap_api.sql

Con este paquete, se puede crear una función o procedimiento con el cual se pueda invocar el servicio web; tenemos un ejemplo del uso de este paquete en el siguiente enlace:

http://www.oracle-base.com/articles/9i/consuming-web-services-9i.php

Ahora bien, a veces lo que cuesta con esto es comprender qué es cada cosa, así que vamos en orden.


CREATE OR REPLACE FUNCTION add_numbers (p_int_1  IN  NUMBER,
                                        p_int_2  IN  NUMBER)
  RETURN NUMBER
AS
  l_request   soap_api.t_request;
  l_response  soap_api.t_response;
  l_return    VARCHAR2(32767);
  
  l_url          VARCHAR2(32767);
  l_namespace    VARCHAR2(32767);
  l_method       VARCHAR2(32767);
  l_soap_action  VARCHAR2(32767);
  l_result_name  VARCHAR2(32767);
BEGIN
  l_url         := 'http://www.oracle-base.com/webservices/server.php';
  l_namespace   := 'xmlns="http://www.oracle-base.com/webservices/"';
  l_method      := 'ws_add';
  l_soap_action := 'http://www.oracle-base.com/webservices/server.php/ws_add';
  l_result_name := 'return';


El anterior bloque de código es únicamente para definir variables:

  • l_url es la url real donde se puede acceder al web service.
  • l_namespace es el espacio de nombres del web service. Más información sobre namespaces en este enlace.
  • l_method es el nombre del método del web service que se va a utilizar.
  • l_soap_action es la acción que se requiere en la petición SOAP. Por lo que he visto en el caso de los web services hechos con .NET, suele ser un URI formado por el valor del namespace (el valor de "xmlns") y el nombre del método.
  • l_result_name es el nombre del resultado que nos da el web service. En el caso de web services desarrollados con .NET, el nombre de esta respuesta suele ser el nombre del método seguido por "Result". Ejemplo: "MiMetodoWebResult " si el nombre del metodo es "MiMetodoWeb".



l_request := soap_api.new_request(p_method       => l_method,
                                    p_namespace    => l_namespace);


En esta llamada creamos el requerimiento al web service, noten que le pasamos unicamente el nombre del método y el espacio de nombres.


soap_api.add_parameter(p_request => l_request,
                         p_name    => 'int1',
                         p_type    => 'xsd:integer',
                         p_value   => p_int_1);

  soap_api.add_parameter(p_request => l_request,
                         p_name    => 'int2',
                         p_type    => 'xsd:integer',
                         p_value   => p_int_2);


En este bloque, añadimos los parámetros a nuestro requerimiento. Se debe hacer una llamada por parámetro, indicándole el request, el nombre del parámetro, el tipo del parámetro y el valor del mismo. Para más información acerca de los tipos de parámetros, puede ir a este enlace.


l_response := soap_api.invoke(p_request => l_request,
                                p_url     => l_url,
                                p_action  => l_soap_action);


Con esto ya se invoca el método del web service que vamos a consumir. Es el momento en el que se envía la petición y se obtiene la respuesta por parte del servicio web.


l_return := soap_api.get_return_value(p_response  => l_response,
                                        p_name      => l_result_name,
                                        p_namespace => NULL);


Esta función get_return_value es la encargada de darnos las respuestas que nos da el web service. Nótese que a diferencia de los métodos anteriores, en lugar de la petición, ahora le pasamos como parámetro la "response".

El parámetro p_name se refiere al nombre del resultado; aquí deseo aclarar que, en el caso de .NET, cuando se establecen parámetros en el método web como "ByRef", es que son parámetros pasados por referencia, por lo que cualquier cambio que tengan será reflejado.Así, si por ejemplo, el parámetro int1 estuviera como ByRef en la firma del método ws_add, entonces se puede obtener un valor de esa variable utilizando el método get_return_value, indicándole como p_name el nombre del parámetro tal como en la llamada a la función add_paramenter.

El parámetro p_namespace normalmente no lleva nada o puede llevar también el valor de la variable l_namespace.

Por último, ¿Que tal si al menos uno de los parámetros es un XML? Sencillo, todos los textos con formato XML han de enviarase encerrado por la etiqueta <![CDATA[ ]]>, así:


soap_api.add_parameter(p_request => l_request,
                         p_name    => 'v_xml',
                         p_type    => 'xsd:string',
                         p_value   => '<![CDATA[' || p_xml || ']]>');


Esta es una llamada de muestra, en caso el método web tuviera un parámetro llamado "v_xml" que requiriera un xml pero es tipo string.

Y así, de esta manera, pueden estar realizando una función que consuma un servicio web en unos cuantos minutos.

Espero esto les sea de ayuda y esté lo bastante claro. Saludos.

sábado, 11 de agosto de 2012

FTP y SFTP con Visual Basic .NET

Bien amigos, en esta oportunidad traigo algo interesante que aportar.

Estuve un buen tiempo investigando cómo se pueden hacer transferencias por medio de FTP con VB .NET, cosa que pude encontrar fácilmente en toda la red utilizando la clase FtpWebRequest de .NET.

Sin embargo, la cosa cambia cuando te encuentras en la situación en la que te dan un servidor que no funciona con el FTP simple, sino con una forma más nueva, el cual es el SFTP, y entonces ves cómo cae la ilusión de ver casi terminado tu proyecto.

Bueno, después de un par de maldiciones y mi respectivo vaso con agua, comencé a buscar información del SFTP, y alguna forma de lograr una transferencia con código nativo de Visual Basic .Net.

Lastimosamente, es algo no muy simple de hacer... bueno, NADA SIMPLE.

Finalmente opté por lo más práctico y rápido (por el tiempo, jeje): buscar una librería que me ayudara a realizar transferencias hacia un servidor SFTP, y después de algunos minutos de búsqueda, finalmente...  ¡¡¡la encontré!!!

Lo mejor, es que viene con todo y ejemplo de aplicación. Pueden ver la información en el siguiente enlace:

http://www.brudvik.org/2009/06/sshsftp-client-in-vbnet-with-sources/

Este ejemplo hace uso de las siguientes librerías:

Tamir's SharpSSH: http://www.tamirgal.com/blog/page/SharpSSH.aspx

Librería Crypto de Mentalis.org (esta es dependencia de la anterior): http://www.mentalis.org/soft/projects/crypto/

Ambas librerías están escritas en C#. En las respectivas páginas podrán encontrar el código fuente de ambas, por si quieren echar un vistazo de cómo se logra la conexión y transferencia de archivos con SFTP utilizando código nativo de .NET.

Espero les sea de ayuda.

Un abrazo y saludos.

martes, 8 de mayo de 2012

Incrustar imagen en correo HTML

¡Vaya que esto de escribir es más difícil de lo que pensaba! Mis respetos para todos los bloggers que se dedican a esto.

Bien, directo al punto: Esta vez tuve la necesidad de encontrar una forma de insertar una imagen en el cuerpo de un mensaje de correo electrónico, pero, ésta no debe ser importada de otra ubicación y tampoco debe ser un adjunto del mensaje.

¿Cómo lograr esto?

Investigando un poco dí con este artículo en www.variablenotfound.com donde se muestra cómo se puede realizar esta azaña (jeje); cabe mencionar que el código que allí publicaron está hecho en C#, y yo me tomé la libertad de pasarlo a Visual Basic .NET.

El código es el siguiente:


' Necesitaremos estos namespaces...
Imports System.Net.Mail
Imports System.Net.Mime

Module Module1

   Sub Main()
   
  ' Crearé algunas variables aquí para facilitar las pruebas:
   Dim MiDireccionDeCorreo as String = ""
   Dim DireccionCorreoDestino as String = ""
   Dim DireccionSMTP as String = "" 'Puede ser una IP o una URL
   Dim PuertoSMTP = 25
   Dim Imagen as String = "" 'Ruta completa y nombre de la imagen.
  
       Try
           ' Montamos la estructura básica del mensaje...
           Dim mail As MailMessage = New MailMessage()
           mail.From = New MailAddress(MiDireccionDeCorreo)
           mail.To.Add(DireccionCorreoDestino)
           mail.Subject = "Mensaje con imagen"

           ' Creamos la vista para clientes que
           ' sólo pueden acceder a texto plano...

           Dim text As String = "Hola, ayer estuve disfrutando de " & _
                                   "un paisaje estupendo."

           Dim plainView As AlternateView = AlternateView.CreateAlternateViewFromString(text, System.Text.Encoding.UTF8, MediaTypeNames.Text.Plain)


           ' Ahora creamos la vista para clientes que
           ' pueden mostrar contenido HTML...

           Dim html As String = "<h2><b>¡¡¡Hola!!!</b> Mira dónde estuve ayer:</h2>" & _
                               "<img src='cid:wbtestimagenbg' />"

           Dim htmlView As AlternateView = AlternateView.CreateAlternateViewFromString(html, System.Text.Encoding.UTF8, MediaTypeNames.Text.Html)

           ' Creamos el recurso a incrustar. Observen
           ' que el ID que le asignamos (arbitrario) está
           ' referenciado desde el código HTML como origen
           ' de la imagen

           Dim img As LinkedResource = New LinkedResource(Imagen, MediaTypeNames.Image.Jpeg)
           img.ContentId = "wbtestimagenbg"

           ' Lo incrustamos en la vista HTML...

           htmlView.LinkedResources.Add(img)

           ' Por último, vinculamos ambas vistas al mensaje...

           mail.AlternateViews.Add(plainView)
           mail.AlternateViews.Add(htmlView)

           ' Y lo enviamos a través del servidor SMTP...
           Console.Out.WriteLine("Empiezo a crear el cliente smtp...")
           Dim smtp As SmtpClient = New SmtpClient(DireccionSMTP, PuertoSMTP)
           Console.Out.WriteLine("Y envio el correo...")
           smtp.Send(mail)
           Console.Out.WriteLine("Correo enviado")
       Catch ex As Exception
           Console.Out.WriteLine(ex.ToString)
           Threading.Thread.Sleep(60000)
       End Try
   End Sub

End Module


Este código me funcionó con un smtp que no requería autenticación. Si ya han hecho pruebas exitosas de envío de correo, se puede simplemente reemplazar la definición de mi cliente smtp con el que hayan utilizado.

Espero que sea de utilidad; saludos y hasta la próxima.

martes, 21 de febrero de 2012

Comprimir archivos a ZIP en Visual Basic .NET

En estos días me he visto en la necesidad de buscar una forma de comprimir a un ZIP un archivo de texto, lo cual es algo no muy simple, por lo que he podido ver.

Me puse manos a la obra y exploré las soluciones que se me ofrecían (la mayoría, de pago), pero, como todos sabemos, "... el que buscare, encontrará".

La solución que encontré se llama DotNetZip Library, y no es más que una librería y set de herramientas gratuito publicado por la comunidad de open source CodePlex, la cual se rige por la licencia Microsoft Public License.

Entonces, vamos a lo que nos interesa: ¿Cómo se comprime un archivo?

Con esta librería he encontrado que se hace de una forma muy simple; lo primero que necesitamos es bajarnos la librería DotNetZip, y luego, vamos a buscar dentro del zip que bajamos, el siguiente archivo: zip-v1.9\Release\Ionic.Zip.dll, el cual descomprimiremos en cualquier lugar de nuestro sistema.

Hecho esto, en Visual Studio hemos de crear un nuevo proyecto, nombrarlo como deseemos y hacer lo siguiente:

  1. Añadir una referencia a Ionic.Zip.dll: En el explorador del proyecto, click derecho y seleccionar la opción "Agregar referencia" o "Add reference" en el caso de que esté en inglés.
  2. Importar el namespace: Tecleamos en el area de imports de nuestro proyecto lo siguiente: Imports Ionic.Zip
Ahora, el código:


Imports Ionic.Zip

    Private Sub Comprimir()
       Using zip As ZipFile = New ZipFile()
           zip.AddFile("rutaarchivo\nombrearchivo1.ext","")
           zip.AddFile("rutaarchivo\nombrearchivo2.ext","")
           zip.Save("rutazip\nombrezip.zip")
       End Using
    End Sub

Como podrán ver, la forma de hacerlo es muy sencilla, simplemente se utiliza el método "AddFile" del objeto zip de tipo ZipFile para añadir cuantos archivos necesitemos comprimir, y luego se guarda el Zip con el método "Save"; ahora bien, podemos observar que AddFile tiene un segundo parámetro el cual es un string en blanco. ¿Qué siginifica? Pues, simplemente es una ruta que se utilizará dentro del ZIP; por ejemplo, si la instrucción fuera:

           zip.AddFile("rutaarchivo\nombrearchivo.ext","test\")

entonces, al abrir el zip resultante, tendríamos primero una carpeta llamada "test" dentro de la cual estaría almacenado el archivo.
Por lo tanto, como el segundo parámetro es una cadena vacía, se le indica a la clase que quiere que no haya ninguna estructura de directorios dentro del Zip, simplemente el archivo en cuestión; por defecto, si no se especifica este parámetro, el método creará la estructura de directorios original del archivo dentro del ZIP.

Para más información de cómo utilizar esta librería, pueden visitar su documentación oficial (en inglés), donde podrán encontrar la referencia de los espacios de nombres, clases, etc. y una sección con bastantes ejemplos (como comprimir de forma simple o incluso agregando una contraseña, descomprimir, etc.) en cada lenguaje con el que se puede utilizar.

 Espero les sea de utilidad esta información.

Saludos.

domingo, 19 de febrero de 2012

Libros de programación web gratuitos

Una de las cosas que más me costó mientras aprendía a programar con lenguajes para web, era encontrar contenidos de calidad, al menor costo posible.

Sabemos que todo cuesta en esta vida, pero hay algunos colaboradores que realizan un trabajo de primera, y lo distribuyen sin fines de lucro por la red.

LibrosWeb.es es un sitio donde se han publicado varias obras que, a mi criterio, tienen un valor incalculable, puesto que los conocimientos que están plasmados en ellos son de mucha utilidad para desarrolladores web de cualquier nivel.

¿Que tipo de libros encontraré aquí? Podemos mencionar que son libros didácticos para aprender lenguajes, frameworks y tecnologías como:

  • XHTML
  • JavaScript
  • CSS
  • Symphony
  • AJAX
¿Que es lo interesante del sitio? Lo que más me gusta es que en sus publicaciones, hay una referencia muy completa acerca de cada lenguaje, además de ejemplos muy claros y ejercicios, pero algo que pesa mucho, es que todos son ¡totalmente gratuitos! Incluso, la mayoría tiene versión en pdf que puede ser descargada para ser impresa, y esto también sin costo alguno... todas las obras están publicadas bajo la licencia Creative Commons Reconocimiento No Comercial - Sin Obra Derivada 3.0

Yo personalmente he leído "Introducción a Ajax", y es simplemente genial, todo está muy bien explicado, y cubre la mayoría de los aspectos a considerar tanto en JavaScript como utilizando Ajax, así que se las recomiendo.

Enlace: LibrosWeb.es

lunes, 13 de febrero de 2012

Hablando de algoritmos


Hablando de algoritmos...

En general, podríamos definir a un algoritmo como cualquier conjunto de instrucciones detalladas que resultan en un "estado final predecible", partiendo de un "inicio conocido".
La calidad de los algoritmos está basada en la calidad de las instrucciones dadas, en tanto sean correctamente ordenadas y estructuradas, así como oportunas, de lo contrario, se corre el riesgo de que el resultado sea incorrecto.

Ahora, después de esta definición algo formal, ¿cuales son las ideas que necesito para entender mejor este concepto? cuestionemos entonces la definición:

Lo primero que se me ocurre es, ¿A que tipo de "inicio conocido" y "estado final predecible" se refiere la definición?
Bien, podría tomarme bastante tiempo explicando y ejemplificando esto, pero vamos al grano:
Estos conceptos tienen su relación en lo que conocemos como RESOLUCION DE PROBLEMAS, donde, a partir de un enunciado y datos iniciales, se realiza un procedimiento para poder resolver un problema y llegar al resultado deseado.

Entonces, de la forma más sencilla, se podría decir de un algoritmo que es... UN CONJUNTO DE INSTRUCCIONES CON LAS QUE SE RESUELVE UN DETERMINADO PROBLEMA.

Ahora bien, ¿Que tipo de instrucciones? Lo explicaré con un ejemplo:

Antonio viene por primera vez a la ciudad, pero no sabe cómo llegar al museo de historia. Le pregunta a una persona de la localidad, la cual conoce cómo hacerlo, y le da las siguientes INSTRUCCIONES:


  • Camine derecho hasta 4 calles y doble a la derecha, luego camine derecho 3 cuadras, y doble hacia la izquierda.
  • Camine derecho otras 6 calles, y a su lado izquierdo podrá observar el museo; buen día.


Si analizamos este escenario, encontraremos muchas cosas interesantes...

Lo primero que observamos son los siguientes hechos:

  1. Condicion inicial: Donde está ubicado.
  2. Resultado deseado: Llegar al museo de historia.
Lo siguiente que podemos ver es lo claro, ordenado y sencillo que se da cada instrucción.
Lo tercero que se puede observar es algo interesante y parte de lo abstracto de todo esto: el dato de que la persona sea alguien que no conozca la ciudad, lo cual ayuda mucho a elegir la forma en la que daremos las instrucciones.

En la siguiente entrega sobre este tema profundizaré sobre estos, para que podamos entender y aprender el abstraccionismo de todo esto.