Perfil de GabrielBiztalk Blandengue (http...FotosBlogListasMais Ferramentas Ajuda

Blog


29/6/2008

Un PAR de días mejorando mis deployments Biztalk - Parte 4

Voy a incluir un Setup de Visual Studio para mi deployment y ver si lo puedo integrar con la implementación con Nant.

Para esto, agregué un proyecto de Setup a mi proyecto y agregué los Project Outputs para orquestaciones, esquemas, transformaciones y assemblies utilitarias. Es importante que los agregue con la información de Debug (porque así está configurado).

Agrego los archivos que no forman parte de solución:

    • Los 6 .bat que empiezan con Server
    • InstallWizard.xml y UninstallWizard.xml
    • BizatalkDeploymentInclude.Nant, NombreSolucion.PortBindings.Xml, NombreSolucion.sln.deploy.build y CopyDeployResults.nant
    • Los archivos de EnvironmentSettings (dentro de su folder)
    • Los archivos de Deploytools (dentro de su folder) con sus sub-folders y sus contenidos

La estructura de directorios debe quedar como se ve debajo

image

Luego creé shortcuts para los wizards de deploy/redeploy/undeploy

image

y moví los shortcuts al User Program y les cambié los nombres para que fueran más "user-friendly" dentro de un folder.

image

 

Hago el Build y luego de instalar tengo el mismo comportamiento que con WiX (pero sin WiX). Estoy más que contento.

Ahora a ver qué más puedo mejorar del resto de la instalación.

28/6/2008

Un día mejorando mis deployments Biztalk - Parte 3

Una de las cosas que normalmente pasa en los proyectos es que los settings de los diferentes artefactos en el binding es diferente. Para experimentar con esto, decidí usar el EnvironmentSettingManager que se aplica dentro del deploymentframework.

La primera cosa que ví es que a pesar de que la documentación expresa que al cerrar la planila se actualizan los archivos (por una macro), esto no sucede, pero es fácilmente subsanable usando el utilitario EnvironmentSettingsExporter.exe que está en el subdirectorio DeployTools.

Con esto quedé conforme pero dejaré esta configuración para más adelante, dado que ahora quiero crear un instalador con WiX

Creando el instalador con WiX 

Lo primero es copiar el directorio BizTalkSample.WiXSetup y renombrarlo con NombreProyecto delante en nuestra solución, luego renombrar el BiztalkSample.WiXSetup.build con NombreProyecto delante y yo lo incluí en el directorio "Solution Items" por comodidad.

Hay que masajear un poco el archivo, no olvidar generar los GUIDs diferentes para el installer.

Luego hay que ejecutar nant en el directorio setup debajo de WixSetup (no hay path, pero está donde nosotros mismos lo copiamos ;)), y no encontrará los archivos:

        • InstallWizard.xml
        • UnInstallWizard.xml
        • CopyDeployResults.nant

que deben copiarse del directorio raíz de la solución de ejemplo a nuestro directorio raíz.

corriendo Nant luego de esto, generó el MSI.

El MSI solamente instala los archivos, y genera entradas en el menú Start para que se pueda implementar la versión. Corrí el MSI, pero no generó las entradas de implementar/desimplementar, por lo que solo me quedó ir al panel de control y desinstalar el producto, y a empezar a pensar por qué no quedó bien instalado.

Round 1- Verificar que el BtsSample funciona: Generé el instalador y lo instalé, quedando correctamente instalado.

image

Round 2 - Por qué no quedó instalado: . Toqué el BizTalk.WiXSetup.nant comentando la línea debajo relacionada a DeploymentTest dado que en mi ejemplo no tengo.

image

pero eso no ayudó, dado que provocó otro error. Creo que el error es que siempre intenta invocar con un deploymentTest aunque en el archivo NombreProyecto.sln.deploy.build yo tengo esa variable en false.

image

Creé entonces una solución NombreProyecto.DeploymentTest con un test que siempre de correcto. Hay que crear también un app.config con los valores que tiene el app.config de la solución de ejemplo. Creado el archivo .config, copiarlo en la raíz del proyecto.

Hecho todo esto, los errores desaparecieron, sin importar lo que hayas puesto en IncludeDeploymentTest genera el "Verify Deployment" y nada más. Esto para mí es un bug, pero tengo que investigarlo más adelante.

Lo que sí encontré es por qué no me genera el resto, es porque (y tuve que buscarlo bastante), el script generate-install-script.js de WiX modificado que está en el directorio WiXSetup\Setup, busca en la raíz del proyecto los archivos:

        • ServerDeployWizard.bat
        • ServerUnDeployWizard.bat
        • ServerRedeployWizard.bat
        • y si hay algún CHM

Para incluirlos en el menú. Estos .bat están en la raíz del directorio de la aplicación de ejemplo (junto con otros .bat que hay que copiar para que estos funcionen).

El final de la búsqueda - ¿vale la pena?

No quiero caer en la disonancia cognitiva que es lo que hace que mis amigos del pinguino piensen que "si es tan difícil, seguro que debe valer la pena, no es que soy un tarado masoquista, es que realmente vale la pena :)".

El problema al que nos enfrentamos cuando tenemos que hacer una distribución Biztalk, hoy, es que las alternativas no son buenas. Normalmente en cualquier distribución tenemos los siguientes requerimientos:

      • Crear un MSI para distribuir la aplicación: esto lo realiza correctamente para Biztalk, pero nuestras assemblies personalizadas no van en el MSI para ponerlas en la GAC. Además, siempre la distribución es desde una instalación completa, no de mis propios fuentes, lo que debe ejecutarse de otra manera.
      • Instalar en el ambiente: a través de la "importación" en biztalk y la distribución de los bindings, que obliga a que el operador haga la operación directamente sobre el servidor.
      • Tener configuraciones personalizadas para cada ambiente: aquí la mejor opción es editar el xml de los bindings para cada caso, el uso del configurador a partir de la plantilla excel es una buena opción, dado que normalmente en otro caso lo que hacemos es dar un documento detallado de instalación para resolverlo.

Por lo anterior, pareciera que vale la pena tener toda esa infraestructura, sobretodo teniendo en cuenta la cantidad de utilitarios y casos que comprende el instalador.

Además, por lo que vi, hay dos complejidades conceptuales:

a) La complejidad conceptual de los bindings: esta complejidad es solo complejidad de comprensión, pero en la ejecución se mostró bastante simple, y la complejidad de comprensión es por dos motivos: el primero es porque el tema es complejo si no se conoce (diferentes tipos de artefactos, vinculación entre ellos, pero esto es Biztalk en sí) y el segundo es porque el encapsulamiento no está completamente terminado (y esto es porque no es un producto).

b) La complejidad grande de usar WiX para generar el MSI: aquí me encantaría saber por qué se usó WiX para este deployment en particular, dado que entiendo que por la complejidad media que tiene no sería necesario usarlo

Haciéndolo fácil, sustituyendo WiX

¿Podemos hacer esto con un proyecto de setup? Lo que necesito es:

      • Generar un instalador que haga la implantación de los assemblies: esto es simple y la única ventaja que tiene el instalador actual es que puedo indicar qué quiero que se implemente y qué no y el los toma automáticamente, pero me obliga a tener los nombres de una cierta manera (lo cual a mí me parece una buena idea pero entiendo que no a todos les parezca).
      • Generar los ítems de de menú para implementación: esto debería ser simple porque son puntos "semi-dinámicos" dado que solamente debo tener en cuenta si debo o no generar de cinco puntos posibles.
      • Generar el script adecuado para que el instalador funcione correctamente, pero eso es simple porque eso sí es lo que se usa con Nant para implementar, esa es la parte que propongo mantener.

Así que voy a mi parte 4 y luego cuento cómo me fue.

27/6/2008

Un día mejorando mis deployments Biztalk - Parte 2

Para comenzar a mejorar, tomé uno de mis proyectos y lo primero que he hecho es cambiar los .btproj para que donde dice Development diga Debug y donde dice Deployment diga Release. Luego fui a la solución y en clic derecho/configuration manager cambié todos a Debug.

Cambié mi solución .Maps a .Transforms e hice lo mismo con el directorio correspondiente, además, modifiqué el nombre del assembly generado, aunque no el namespace (para no tener que cambiar referencias y re-hacer el deployment. Copié el directorio DeployTools de la solución de ejemplo a un subdirectorio en mi solución y creé el directorio DeployResults.

Creé una nueva "Solution Folder" y la nombré "Solution Items" poniendo dentro los archivos BizTalkDeploymentInclude.nant y BizTalkSample.sln.deploy.build (renombrado como NombreSolucion.sln.deploy.build) que copié de la solución de ejemplo al directorio raíz de la solución.

Preparar algo de trabajo, realizar el deployment de la solución

Ahora debemos realizar el deployment de la solución (si ya no lo tenemos hecho) y generar el archivo de binding directamente con el Biztalk Deployment Wizard con el nombre NombreSolucion.PortBinding.xml en la raíz de la solución. Agregamos el archivo a la solución dentro del folder "Solution Items".

Modificar el archivo de build

Abrí el NombreSolucion.sln.deploy.build y modifiqué los siguientes datos:

      • ProjectName
      • En los include, solamente dejé en true: includeSchemas, includeOrchestrations, includeTransforms, includeComponents
      • Como tenía más de un componente, agregué una línea como se ve debajo, prestando especial atención a quitar el overwrite ="false" y a que no queden espacios entre los assemblies separados por coma.image 

Nótese que uno de los assemblies no tiene prefijo.

Comenté el customDeployTarget y el applyFilePerms dado que no lo necesitaba. Comenté el environmentsettings aunque es algo que realmente me va a servir pero quiero seguir avanzando.

La prueba

Luego de hacer todo lo anterior, simplemente eliminé la aplicación del servidor completamente y di Tools/BT-Biztalk Deploy en mi solución. Falla, porque no alcanza con comentar el environmentsetting, igualmente llama para generar los parametros de modo que hay que copiar el directorio EnvironmentSettings de la solución de ejemplo a nuestra solución.

Siguiendo con la prueba, lo siguiente que cae es cuando quiere hacer el xmlpreprocess de NombreSolucion.PortBindingsMaster.xml esto es algo que esperaba, dado que el usingmasterbindings está en true, lo volví a false junto con la propiedad applyXmlEscape

image

Y ahora sí, estamos listos para más.

Un día mejorando mis deployments Biztalk - Parte 1

Luego de mucho tiempo y diferentes alternativas, he decidido comenzar a usar el Biztalk Deployment Framework http://www.codeplex.com/biztalkdeployment del amigo Scott Colestock.

Lo primero es bajar los todos los paquetes de Release de codeplex y descompactar el que tiene el Sample en la máquina donde tenemos Biztalk 2006 R2.

El documento "BT2006DeployWithNantDocs.doc" parece destilar toda la información que necesitamos, al menos para comenzar.

Hallazgo 1 : nombre de los assemblies

Los assemblies deben tener una forma específica para que el deployment por defecto de Nant que está incluido (BizTalkDeploymentInclude.nant) los tome y esa estructura es NombreProyecto.TipoAssembly, donde TipoAssembly puede tomar los valores:

    • Components
    • Schemas
    • Pipelines
    • Transforms (lógico, pero yo usaba Maps :( )
    • PipelineComponents
    • CustomFunctoids
    • Orchestrations
    • DeploymentTest
    • PortBindings.xml: Bindings del proyecto
    • PortBindingsMaster.xml: ídem al anterior pero con xml "unescaped" para mejor legibilidad, es lo que usa el sample.
    • VDirList.txt: Lista de directorios virtuales que deben crearse. La lista es una línea por directorio con la estructura [virtual directory, physical directory, app pool name]

Continuando la búsqueda

Lo siguiente a mirar es el archivo BizTalkSample.sln.deploy.build, donde está una instancia de uso del BiztalkDeploymentInclude.nant (está incluído). Además, las propiedades applyXmlEscape y usingMasterBindings están en true para indicar que se usa PortBindingsMaster.xml

Un apartado especial en este archivo es la sección customDeployTarget que permite ejecutar comandos específicos que no son atendidos por el Core.

image

En el ejemplo se usa para dar permisos a directorios al usuario con el que corre el servicio Biztalk Server que aloja al host.

A probar (pero primero a terminar de instalar)

Después de leer la introducción, lo siguiente es empezar a probar. Para esto lo que sigue es seguir los pasos del apéndice A del documento.

Lo primero es instalar NUnit, la versión recomendada en el documento que yo tengo es la 2.2.8, pero la que está disponible en el sitio es la 2.4.0, hay que bajar el que dice win .net 2.0. No me coincidieron la cantidad ni los nombres de los assemblies de test pero funcionó, por lo que supongo debo seguir adelante.

Ahora me bajo el Nant, que es la 0.85 pero full ya no es Rc, hay que bajar la nant-0.85-bin.zip y descompactarlo en c:\program files\Nant, luego bajar el NantContrib y descompactar los directorios haciendo el merge de los directorios (no debajo de bin como dice el doc).

Lo que se necesita de ahí en adelante forma parte del Core por lo que llegó la hora de descompactar el BTS2006DeployWithNantCore en un directorio (que yo llamé con ese mismo nombre) y copiar el BizTalk.NAnt.Tasks.dll en el bin de Nant. En el nant.exe.config quité todos los supportedRuntime excepto el de la versión v2.0.50727.

Luego de esto, es necesario instalar las herramientas para visual studio que están en un .zip diferente (BT2006DeployWithNAntExtraTools) y correr el script MakeBizTalkExternalTools_VS2005.vbs en la carpeta MakeBizTalkExternalTools_VS2005 (y esto ya parece la instalación de una distribución de nuestro amigo el pinguino :), espero que esto sí valga la pena).

Aquí, si tenemos abierto Visual Studio, debemos cerrarlo y abrirlo, abriendo nuevamente la solución de ejemplo, hacemos el Rebuild All y luego Tools/BT-Biztalk Deploy y .... hay que mirar bien!

Deberíamos tener en la consola de Administración, la aplicación Biztalksample con orquestaciones, mapas, esquemas y pipelines, en la GAC debiéramos ver 5 assemblies con prefijo BiztalkSample. Creo el directorio c:\temp\BizTalkSample_OutDir y agrego la cuenta IWAM al grupo BizTalk Isolated Host users group (yo uso W2003)

Levante Nunit para correr el test que abrí de la carpeta recién compilada bin\debug y lo que obtuve fue un error de archivo no encontrado buscando testfiles debajo del directorio. Caí en la cuenta que hay que probar con la dll que ya viene en la raíz del src, pero al intentar cargarla no encuentra nunit.framework que copié junto con el xml del bin\debug donde intenté inicialmente.

Ahora lo probé y todo funciona bien como prueba la figura debajo, aunque no gané todavía el entendimiento global de la solución, un par de horas después de comenzar, mi infraestructura está funcionando

image

24/6/2008

Como recibir un string desde el MQSC Adapter (receive string mqsc adapter)

En realidad esta solución funciona para cualquier caso donde tenga que recibir un string y llevarlo a una orquestación donde el mensaje en el receive shape queramos que sea un string.

En el caso particular del adapter para MQSeries (o WebSphere MQ), de tipo cliente (que se instala con el CD de HIS), lo que recibo del adaptador es lo que está en el mensaje, con todos los datos de lo que sería el contexto del MQMessage en el contexto del mensaje Biztalk.

El problema es que si ingreso con un pipeline passthrough, Biztalk no procesará la suscripción, no entraré en detalles pero si les interesa lo que sucede se explica en el artículo de la Kb a continuación http://support.microsoft.com/kb/837860/en-us 

Una posible solución es usar un RawString para la entrada como se explica en esta entrada http://www.traceofthought.net/CommentView,guid,c5418f3d-2ea7-4530-ab9c-ae4c49154fcb.aspx el único tema con esto es que hay que hacer el deployment no solamente del ContextAdder (ContextAdder) , sino del RawString, y usarlo en la orquestación. Asumiendo que entienda el artículo y cómo hacerlo, no es una mala solución.

La otra solución es tener un ContextAdder que además de agregar al contexto la propiedad MessageType como se ve debajo al tipo string, agregue al string raw que viene, el xml <string></string> alrededor del string original que entra.

image

Aquí ContextAdderModificado subo la solución con un ContextAdder modificado que hace lo anterior.

Igualmente persiste, si necesitamos escribir WebSphere MQ via el MQSC Adapter la necesidad de usar un RawString por lo que en el mismo proyecto está incluida la clase RawString del SDK.

Hay una orquestación que asume que están los artefactos correctamente implementados para probar y recibe un string y envía un string (con una lógica de dominio que puede quitarse si quieren probarse strings simples).

Ya que estamos, comento un par de cosas importantes para interactuar con MQSC.

1) en el Receive, los siguientes parámetros son mandatorios: Channel Name, Queue y Queue Manager

image

2) en el Send los párámetros mandatorios son: Channel Name, Connection Name, Queue y Queue Manager

image

Si estos parámetros no están, los errores 2058 con una descripción como Reason code 2058 Failure encountered while attempting to open queue pueden sucederse sin que esto nos indique exactamente qué está sucediendo.

Por qué no creo en EF (Entity Framework) ni L2S (Linq To Sql)

Realmente el título debería reflejar que no creo en ORM (Object -Relation Mapping), porque en mi opinión ORM refleja siempre una lógica CRUD, y CRUD es permitir que la base de datos dirija el diseño técnico y arquitectural del software (en lugar de los requerimientos de negocio). Y no creo que eso sea una buena idea

Tomemos un ejemplo.

Un típico ejemplo de una transacción sería hacer que un joven cambie su tutor en la facultad; otra podría ser cambiar su sexo para convertirse en una joven. Resolvemos las dos transacciones de la misma manera. Leemos el registro del joven en la base de datos, lo traemos a la interfaz de usuario, dejamos que el usuario cambie los campos que deben ser cambiados, enviamos el registro modificado al servidor, actualizamos la fila de la tabla usando control de concurrencia optimista. Eso es todo CRUD, y sería una correlación perfecta para el software ORM. Pero este diseño está dirigido por la base de datos y no por el negocio.

Estas dos transacciones no tienen ninguna relación. Si hay un cambio de tutor al mismo tiempo que la persona se está cambiando el sexo, es una "pura coincidencia". Una mejor manera de exponer esto es con dos operaciones separadas:

- CambiarTutor(IdPersona, idNuevoTutor)

-CambiarSexo(IdPersona, Fecha) [Aquí se podría argumentar que es necesario tener el NuevoSexo pero no quiero entrar en ese detalle ahora)

Lo anterior no es CRUD, y podría permitir crear un joural de transacciones. De hecho, la mejor manera para que los componentes de acceso a datos lo manejen sería realizar un insert SQL en el journal, y dejar que la base de datos afecte correctamente las filas en las tablas correspondientes. En ambientes de alta contención esto sería muy saludable, dado que diferentes usuarios con diferentes conexiones competirían solamente por Insert, que es mucho menos serio en términos de lock que si estuvieran compitiendo por updates como sucede en las situaciones CRUD.

Entiendo que CRUD es a veces necesario y lo correcto, pero sostengo que está lejos de ser siempre la mejor cosa. Me da mucho miedo que usando software ORM, los desarrolladores estén tentados de usar CRUD cuando no deberían. No solamente esto, sino que, dado que resolver todos los problemas de ORM es complejo, los programadores más "osados" (y muchas veces sin experiencia), de analizar el código fuente de algunos de estos ORM, concluyan que es la mejor manera de construir software, y terminemos encontrando (ayer encontré algo de esto y por eso me motivo a escribir) monstruos de siete cabezas para resolver funcionalidad trivial.

Por otro lado el SQL necesario es casi siempre trivial. Se que no todos los programadores pueden ser expertos en el arte de escribir SQL, pero no tienen por qué. De la misma manera es cierto que no todos los programadores son expertos en crear interfaces de usuario (mi caso), pero tampoco tenemos por qué ser. Debería ser posible en cualquier proyecto no trivial, usar las personas buenas para cada cosa en la misma.

En esta línea de pensamiento está SOA, yo creo en SOA y no veo que ORM haga viable el "mindset" necesario para que estos suceda, no porque sea inútil como herramienta (aunque de hecho, en mi opinión no sirve, porque genera un overhead enorme para operaciones triviales), sino porque mina desde las raíces el pensamiento conceptual de los diseñadores y programadores del software.