February 2008 - Posts
Resumen
En la primer parte vimos cómo crear los esquemas necesarios para leer los archivos de texto plano de nuestra tienda. Vimos también cómo configurar un pipeline de recepción que incluya los esquemas creados para poder desensamblar los archivo correctamente. En este artículo continuaremos con el escenario y juntaremos todas las piezas del rompecabezas.
Creación de la Orquestación
El siguiente paso es crear la orquestación dentro de nuestro proyecto. Para realizar esto hagamos clic derecho sobre nuestro proyecto y seleccionemos Add New Item. A la orquestación le asignaremos el nombre Tienda_Orchestration.odx tal y como lo muestra la siguiente figura:
Ahora necesitamos un puerto de recepción por medio del cuál podamos obtener los archivos de texto plano. Agreguemos el puerto a la orquestación haciendo clic derecho sobre el area denominada Port Surface y seleccionemos la opción Configured Port. El nombre del puerto será Tienda_Recepcion:
En la siguiente ventana seleccionemos la opción de crear un nuevo tipo de puerto definiendo el nombre Tienda_Recepcion_Tipo y su tipo de comunicación como One-Way:
En la siguiente ventana seleccionemos la dirección de comunicación de tipo recepción y el port binding a Specify later. Una vez hecho esto hagamos clic en siguiente y luego finalizar.
El paso anterior creará el puerto de recepción en la orquestación. A la operación llamada Request del puerto debemos definir cuál será el tipo de mensaje que recibirá. Seleccionemos Tienda_Album en la propiedad Message Type usando la ventana de propiedades
Agreguemos una actividad de tipo Receive a la orquestación y asignemos su propiedad Activate igual a True. Su tipo de mensaje será Tienda_Input_Album (consultar la sección "Anexos" en este artículo para más información acerca de los mensajes y variables que deben ser creados) y su operación relacionada será Tienda_Recepcion.Operation_1.Request
Agreguemos una actividad de tipo Construct Message justo debajo de la actividad Receive recién incorporada. En su propiedad Messages Constructed seleccionemos Tienda_Input_Artista ya que es el tipo de mensaje que deseamos construir. Además le agregaremos una sub-actividad de tipo Message Assignment para poder construir el mensaje.
Usando la ventana de propiedades modifiquemos Expression para que tenga el siguiente código:
headerDocString = Tienda_Input_Album(XMLNORM.FlatFileHeaderDocument);
headerDocXml = new System.Xml.XmlDocument();
headerDocXml.LoadXml(headerDocString);
Tienda_Input_Artista = headerDocXml;
El anterior código obtiene el artista del archivo recibido (gracias a que ese esquema está definido como header en el pipeline de recepción) y lo guarda en una variable de tipo XmlDocument. Posteriomente, esta variable es usada para inicializar el mensaje de tipo Tienda_Input_Artista.
Bien, ahora necesitamos agregar un puerto de tipo Send usando la ventana de BizTalk Explorer con las siguientes consideraciones:
- El tipo de puerto será Static-One-Way
- Nombre: Tienda_Router_Sql
- El tipo de transporte será SQL
- La cadena de conexión deberá configurarse para conectarse a la base de datos Tienda usando el usuario biztalkuser definido en la parte 1 de este artículo.
- Document Target Namespace: http://tienda.router/sqloutput
- Response Document Root Element: alb
- Send Pipeline: PassThruTransmit
Una vez agregado el puerto de tipo Send, hagamos clic derecho sobre la carpeta SPSchema y seleccionemos Add-Add Generated Items... e indiquemos la plantilla Add Adapter Metadata en la caja de diálogo.
Seleccionemos el puerto Tienda_Router_Sql en la siguiente ventana y hagamos clic en el botón Next.
En el siguiente paso del asistente llamado Database Information hagamos clic en el botón Next. En el siguiente paso definamos los siguientes valores y despúes hagamos clic en el botón Next.
- Target namespace: http://tienda.router/sqloutput (el mismo que cuando creamos el puerto de tipo Send)
- Port type: Send port
- Request document root element name: alb_request
- Response document root element name: alb_response
En el siguiente paso seleccionemos la opción Stored Procedure y hagamos clic en el botón Next. En el siguiente paso seleccionemos InsertaArtista y en seguida hagamos clic en Finish. Repitamos estos mismos pasos para el procedimiento almacenado InsertaAlbum.
Creación de los mapas de transformación
Hagamos clic derecho en la carpeta Map y seleccionemos la opción Add->New Item... y seleccionemos la plantilla Map de la caja de diálogo. El nombre del mapa será Tienda_Artista.btm.
Seleccionemos el data source del esquema origen a Tienda_Artista:
Seleccionemos el data source del esquema destino a SqlService_sqloutput. A continuación, seleccionemos alb_request como root node. Realicemos el mapeo necesario tal y como lo muestra la siguiente figura:
Agreguemos una nueva actividad de tipo Construct Message a la orquestación y dentro de ella una actividad de tipo Transform. Hagamos doble clic sobre Transform_1 y configuremos de la siguiente manera la transformación:
- Existing Map
- Fully Qualified Map Name: Tienda.Map.Tienda_Artista
- Source: Tienda_Input_Artista
- Destination: Tienda_Output_Artista
Agreguemos una actividad de tipo Send a la orquestación y le asignamos su propiedad Message a Tienda_Output_Artista.
Agregar un nuevo puerto de envío a la orquestación haciendo clic derecho sobre el Port Surface del diseñador con los siguientes parámetros:
- Name: [Empresa]_Envio_Header
- Tipo: [Empresa]_Envio_Header_Tipo
- Comunicación: One-Way
- Dirección: Send
- Binding: Especificar después
Configurar su operación llamada Request con la propiedad Message Type como Tienda.SQLService_sqloutput.alb_request. Una vez hecho esto, conectamos el shape Send_1 al nuevo puerto tal y como lo muestra la siguiente figura:
Repitamos los pasos anteriores para el mensaje Tienda_Output_Album.
Podemos usar una actividad de tipo Parallel para que el envío del artista junto con sus albumes relacionados sea al mismo tiempo en vez de secuencial.
Deployment
Como último paso debemos hacer Deploy de nuestro proyecto haciendo clic en la opción Deploy del menú Build de Visual Studio .NET.
Una vez hecho el deployment debemos configurar los puertos de recepción y envío usando la herramienta BizTalk Server 2006 Administration Console haciendo clic derecho sobre la orquestación en la lista de aplicaciones.
- El pipeline del puerto de recepción debe ser de tipo Tienda_ReceivePipeline
- El puerto de recepción debe tener relacionado un folder que tenga el suficiente nivel de permisos de acceso para poder leer los archivos (en este demo se agregó Everyone Full Control a un folder llamado C:\Archivos)
- El filtro para el puerto de recepción debe ser *.txt
- Configurar adecuadamente el polling interval. En esta demo se configuró a 15 segundos (15000 ms)
- El puerto de envío debe ser de tipo SQL y su pipeline de tipo PassThruTransmit
- El puerto de envío debe tener configurada la cadena de conexión correcta para poder ejecutar los stored procedures relacionados
Lo último que resta es iniciar la orquestación haciendo clic sobre ella y seleccionar la opción Start del menú contextual. Para probar, copiemos un archivo de texto a la carpeta en donde se configuró el puerto de recepción y listo! Nuestras tablas son actualizadas correctamente en SQL Server.
Anexos
Mensajes
| Nombre del mensaje |
Tipo |
Observaciones |
| Tienda_Input_Artista |
Tienda.FFSchema.Tienda_Artista |
Creado por medio del Flat File Schema Wizard |
| Tienda_Input_Album |
Tienda.FFSchema.Tienda_Album |
Creado por medio del Flat File Schema Wizard |
| Tienda_Output_Artista |
Tienda.SQLService_sqloutput.alb_request |
Creado por medio de la opción Add Adapter Metadata (cambiar el nombre apropiadamente por medio de la ventana de propiedades si es que ya existe un archivo con el mismo nombre) |
| Tienda_Output_Album |
Tienda.SQLService_sqloutput_1.alb_request |
Creado por medio de la opción Add Adapter Metadata (cambiar el nombre apropiadamente por medio de la ventana de propiedades si es que ya existe un archivo con el mismo nombre) |
Variables
| Nombre de la variable |
Tipo |
| headerDocString |
String |
| headerDocXml |
System.Xml.XmlDocument |
Conclusión
BizTalk Server 2006 es una poderosa herramienta para la integración entre aplicaciones incluso de diferentes plataformas. En este artículo dividido en dos partes vimos cómo enviar los datos de archivos de texto planos a tablas de SQL Server por medio de una orquestación de BizTalk Server 2006.
Ya está disponible la primer emisión de PodWorx, el podcast de DevWorx conducido por Mike, Misa y su servidor y en el cual platicamos de diferentes noticias y temas con perfil técnico, condimentado con un poco de humor y una pizca de sarcasmo.
En esta edición platicamos principalmente acerca de la Clínica gratuita para el examen 70-536 y claro está, de otros temas también. El resumen de esta emisión y otras emisiones lo podrán leer directamente del blog de PodWorx.
Lo pueden descargar de esta dirección.
Salu2!
Y efectivamente!!!, acabo de bajar mis correos y me encuentro que el número de personas que amablemente han solicitado su inscripción a la clínica en línea asciende a ya casi 200!!!. Muchas gracias por su interés; en pocos días recibirán un correo confirmando su registro para que puedan entrar a la información privada de la clínica y sus materiales. Les agradecemos a todos(as) la gran respuesta que han mostrado. Por favor lean el post de Misael para más información acerca del proceso de registro.
Salu2!
Se invita a todas las personas interesadas a participar en la clínica para presentar el examen de certificación 70-536, la cual comenzará el próximo día 03 de marzo del 2008 y será llevada a cabo de manera online; siendo su duración aproximada de 2 meses. Se extiende esta invitación también a todas aquellas personas ya certificadas que deseen reforzar sus conocimientos acerca de los temas que toca el temario para este examen. La clínica es totalmente gratuita y será impartida por:
- Rodrigo Díaz (Ineta Speaker)
- Miguel Ángel Morán (MVP C#)
- Misael Monterroca (Ineta Speaker)
El temario lo pueden consultar aquí.
Nos vemos en línea!
Como parte de la misión de esta empresa, hemos creado DevWorx Learning Center: una iniciativa para la creación de material de aprendizaje y entrenamiento audiovisual para difundir la plataforma tecnológica .NET de Microsoft a todas aquellas personas de habla hispana que deseen conocer o aprender más acerca de estas maravillosas herramientas. Esperando que les sea de gran utilidad, sean ustedes bienvenidos.
http://learning.devworx.com.mx/default.aspx
Saludos!
No es raro hoy en día encontrarnos con aplicaciones que integran datos de diferentes plataformas para obtener la información necesaria y poder explotarla adecuadamente. Son bastantes los escenarios que nos podemos encontrar como consultores en los que determinada empresa cuenta ya con un sistema de tipo legacy y que debido a su gran importancia histórica es imposible tirarlo a la basura incluso resultaría bastante caro y arriesgado adentrarse en el largo y sinuoso camino de la migración total -incluso parcial- de su código a una plataforma moderna y escalable como es .NET. Por lo anterior es muy común que las empresas requieran de alguna forma u otra seguir obteniendo o procesando los datos que sus sistemas legacy arrojan y a la vez renovar su plataforma y arquitectura tecnológica a nuevos horizontes.
Así que, en este artículo aprenderemos a procesar archivos de texto planos para leer su contenido y posteriormente escribirlo a tablas de SQL Server 2005 por medio de una orquestación de BizTalk Server 2006. Una vez terminado de leer este artículo podrán apreciar lo sencillo que puede ser esta tarea al ser coordinada y procesada con esta magnífica pieza de software.
El escenario
Nuestro sistema legacy es un sistema de compras e inventarios de una cadena de gran importancia a nivel nacional de venta de discos compactos musicales. No obstante, la empresa requiere que el catálogo de discos sea replicado a una base de datos de SQL Server 2005 por medio de una orquestación de BizTalk Server 2006 una vez que un nuevo título llegue a su inventario.
El sistema legacy escribirá un archivo de texto plano con extensión .txt por artista una vez que nuevos álbumes lleguen al inventario. El archivo de texto plano tendrá el siguiente esquema:
ARTISTAID | NOMBRE | GENERO
ARTISTAID | ALBUMID | TITULO_DEL_ALBUM | ANIO | CANTIDAD
ARTISTAID | ALBUMID | TITULO_DEL_ALBUM | ANIO | CANTIDAD
ARTISTAID | ALBUMID | TITULO_DEL_ALBUM | ANIO | CANTIDAD
...
Con lo anterior podemos deducir que en un solo archivo podrán incluirse diferentes albumes del mismo artista. Además, podemos observar que los archivos incluyen el pipe (|) como separador de cada atributo.
Por otro lado, tenemos una base de datos de SQL Server 2005 llamada Tienda la cual cuenta con las tablas Artista y Album que son donde se depositarán los datos de los archivos de texto plano y su esquema es el siguiente:
La solución
La solución está basada en una orquestación implementada con BizTalk Server 2006 la cual será capaz de detectar la existencia de un nuevo archivo y procesará su contenido apropiadamente para escribir los datos en las tablas del servidor de SQL Server 2005.
Para iniciar, implementemos los procedimientos almacenados encargados de escribir los datos en las tablas de la base de datos. Los procedimientos almacenados serán llamados spInsertaArtista y spInsertaAlbum para las tablas Artista y Album respectivamente y su código es el siguiente:
create procedure dbo.InsertaArtista
@ArtistaID int,
@Nombre varchar(50),
@Genero varchar(50)
as
Set nocount on
Insert into Artista (ArtistaID, Nombre, Genero)
Values (@ArtistaID, @Nombre, @Genero)
go
create procedure dbo.InsertaAlbum
@ArtistaID int,
@AlbumID int,
@Titulo varchar(50),
@Anio smallint,
@Cantidad int
as
Set nocount on
Insert into Album
(ArtistaID, AlbumID, Titulo, Anio, Cantidad)
Values
(@ArtistaID, @AlbumID, @Titulo, @Anio, @Cantidad)
También necesitamos un login de SQL para poder conectarnos a SQL Server 2005 desde BizTalk y poder ejecutar los procedimientos almacenados. Claro está que será más recomendable usar autenticación de tipo Windows en vez de usar usuarios de tipo SQL pero para este artículo lo dejaremos así. La cuenta que crearemos será biztalkuser con el password Pa$$W0rd y le asignaremos el rol de dbo_owner sobre la base de datos Tienda:
Muy bien, tenemos los elementos básicos para comenzar. Lo primero que vamos a hacer es abrir Visual Studio .NET y crearemos un nuevo proyecto de tipo Empty BizTalk Server Project y le pondremos el nombre Tienda, tal y como lo muestra la siguiente figura:
Una vez creado nuestro proyecto es buena idea cambiarle las propiedades Application Name y Restart Host Instances para poder identificar nuestra aplicación en la consola de administración de BizTalk y para reiniciar todas las instancias cuando despleguemos el proyecto respectivamente. La siguiente figura muestra las propiedades de nuestro proyecto:
Por efectos de orden y limpieza en nuestro proyecto crearemos los siguientes fólders:
| Nombre |
Descripción |
| FFSchema |
Aquí guardaremos los esquemas para el pipeline que lee los archivos de texto planos |
| Map |
Aquí guardaremos los mapas de transformación |
| Pipeline |
Aquí guardaremos los pipelines de recepción para los archivos de texto planos |
| SPSchema |
Aquí guardaremos los esquemas necesarios para ejecutar los procedimientos almacenados en SQL Server 2005 |
Creación de los esquemas
El siguiente paso será la creación de los esquemas apropiados para interpretar el esquema de los archivos de texto plano. Para el tipo de archivo que procesaremos en este ejemplo crearemos dos esquemas: uno para el header que contiene información básica del artista y otro para el detalle el cual como mencionamos anteriormente puede contener uno o varios albumes del mismo artista. Los siguientes pasos muestran la creación del esquema para los álbumes, sin embargo serán los mismos pasos para la creación del esquema para el artista. Para hacer esto agreguemos al fólder FFSchema un nuevo elemento de tipo Flat File Schema Wizard y asignemos el nombre Tienda_Album.xsd tal como lo muestra la siguiente figura
Al hacer anterior Visual Studio nos muestra el asistente de creación de esquemas para archivos de texto planos. En la primer ventana asignaremos un archivo muestra de los cuales necesitamos procesar y asignaremos algunos parámetros como Record name y Target namespace. La siguiente figura da ejemplo de esto:
La siguiente tarea será seleccionar las líneas en el archivo de texto que representan el detalle tal y como lo muestra la siguiente figura:
Hagamos clic en siguiente para aceptar la opción "By delimiter symbol". La siguiente ventana nos solicita indicar el delimitador para cada registro, en nuestro caso será el default {CR}{LF} ya que cada registro está indicado en una línea por separado. La siguiente figura muestra esta ventana:
Al hacer clic en el botón Siguiente en la ventana anterior se nos muestra la opción de indicar cuáles son los elementos hijos. En el caso específico de este ejemplo seleccionaremos el primer registro como Repeating record y le asignaremos el nombre Album mientras que al resto de registros les asignaremos el tipo Ignore ya que son exactamente iguales que el primero en estructura. La siguiente figura muestra los elementos configurados:
La siguiente ventana nos muestra un resumen del esquema, sin embargo aun falta terminar de configurar los registros así que haremos clic en siguiente. La siguiente ventana llamada "Select Document Data" nos solicita seleccionar los datos que definen un registro dentro del archivo de texto plano. De manera predeterminada el asistente es lo suficientemente inteligente para seleccionar el registro tal como lo muestra la siguiente figura, posteriormente haremos clic en Siguiente.
Tal y como hicimos anteriormente, en la ventana "Select Record Format" aceptaremos la opción "By delimiter symbol" y haremos clic en el botón Next.
Ahora se nos presenta de nueva cuenta la ventana "Delimited Record", en ella especificaremos en la lista desplegable llamada "Child delimiter" el caracter que delimita cada columna dentro de nuestro archivo en este caso se trata del pipe (|). Al hacer clic en el botón Next se nos muestra la siguiente ventana en donde podemos definir el nombre de cada elemento (columna) que representa un registro de cada álbum:
Al hacer clic en siguiente se nos presenta el resumen del esquema y para terminar haremos clic en el botón Finish.
Una vez terminada la creación del esquema modificaremos la propiedad Element FormDefault del nodo <Schema> para tener el valor "Qualified":
No olvidemos el esquema para el Artista! Sigamos todos los pasos anteriores que usamos para crear el esquema de los álbumes con la única diferencia que a la propiedad Max Occurs en Artistas/Artista le asignaremos un valor de 1.
Creación del Pipeline de recepción
Nuestra siguiente tarea será la creación del pipeline de recepción para nuestro proyecto. Para hacer esto agreguemos un nuevo elemento de tipo Receive Pipeline dentro de nuestro fólder Pipeline y asignemos el nombre Tienda_ReceivePipeline.btp tal como lo muestra la siguiente figura:
Para diseñar nuestro pipeline usaremos el componente Flat file disassembler y lo colocaremos en la sección "Disassemble" del diseñador la cual permite indicar la funcionalidad a ejecutar cuando queremos desensamblar nuestro archivo. Además le asignaremos las propiedades Document schema y Header schema a Tienda_Album y Tienda_Artista respectivamente, además de poner en True la propiedad Preserve header. La siguiente figura muestra el componente Flat file dissasembler configurado:
Wuf! Vamos muy bien pero aún falta camino por recorrer. La segunda parte de este articulo explicará la orquestación de BizTalk y demostrará cómo todas las piezas de este rompecabezas se unen.
Para realizar la tarea que indica el título de este post podríamos hacerlo de diferentes maneras, una de ellas abriendo el sitio usando SharePoint Designer 2007 y simplemente borrando el control. No obstante esta opción es demasiado radical ya que ni siquiera los usuarios administradores podrían ver ese control una vez borrado. Por lo tanto el escenario más común buscado sería: Ocultar la opción "View All Site Content" pero solo para los usuarios X o los usuarios Y. Bien pues una manera de solucionar esta duda sería editar el master page de nuestro sitio y encapsular el mencionado control View All Site Content (que técnicamente es un SPLinkButton) con un control SPSecurityTrimmedControl especificando su propiedad PermissionsString a un permiso que sepamos que solamente tienen los usuarios a los que queremos que se les despliegue el control.
Veamos lo anterior ahora en código: A continuación se muestra un fragmento de código que pertenece al master page de mi sitio al que le quiero ocultar el control View All Site Content. El fragmento muestra la barra de navegación izquierda que es donde comunmente se encuentra ese control: (los números son de referencia únicamente)
1: <asp:ContentPlaceHolder ID="PlaceHolderLeftNavBar" runat="server">
2: <div class="ms-quicklaunchouter">
3: <div class="ms-quickLaunch" style="width: 100%">
4: <h3 class="ms-standardheader">
5: <label class="ms-hidden">
6: <SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,quiklnch_pagetitle%>"
7: EncodeMethod="HtmlEncode" /></label>
8: <div class="ms-quicklaunchheader">
9: <SharePoint:SPLinkButton id="idNavLinkViewAll" runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx"
10: Text="<%$Resources:wss,quiklnch_allcontent%>" AccessKey="<%$Resources:wss,quiklnch_allcontent_AK%>" /></div>
11: </h3>
En la línea número 9 está nuestro objetivo. Pongamos el control SPLinkButton dentro de un SPSecurityTrimmedControl tal como lo muestra el siguiente código ya modificado:
1: <asp:ContentPlaceHolder ID="PlaceHolderLeftNavBar" runat="server">
2: <div class="ms-quicklaunchouter">
3: <div class="ms-quickLaunch" style="width: 100%">
4: <h3 class="ms-standardheader">
5: <label class="ms-hidden">
6: <SharePoint:EncodedLiteral runat="server" text="<%$Resources:wss,quiklnch_pagetitle%>"
7: EncodeMethod="HtmlEncode" /></label>
8: <SharePoint:SPSecurityTrimmedControl runat="server" PermissionsString="ManageWeb">
9: <div class="ms-quicklaunchheader">
10: <SharePoint:SPLinkButton id="idNavLinkViewAll" runat="server" NavigateUrl="~site/_layouts/viewlsts.aspx"
11: Text="<%$Resources:wss,quiklnch_allcontent%>" AccessKey="<%$Resources:wss,quiklnch_allcontent_AK%>" /></div>
12: </SharePoint:SPSecurityTrimmedControl>
13: </h3>
Debemos hacer notar que estamos usando el permiso ManageWeb. Esto qué significa? Que unicamente aquellos usuarios que tengan ese permiso podrán ver el control View All Site Content. Y ya que se trata de un permiso -comunmente- asignado a administradores, un usuario normal no debería tenerlo (en mi caso, por ejemplo). Claro está, esto dependerá de la implementación de cada quién; por lo tanto aquí está la lista de permisos que podemos usar.
Asimismo, esto también aplica para la barra de navegación o "Top link bar" de los sitios de SharePoint, solo busquen en el master page el control TopNavigationMenu de tipo <SharePoint:AspMenu> y repitan la receta.
Espero que esto les sea de ayuda.
Salu2!
- Toyo (Restaurante). Si te gusta la comida japonesa no dudes en pisar este lugar ya que la comida está deliciosa, además de que podrás encontrar una gran variedad de cervezas nacionales e internacionales. Si llegas y estás en un modo muy "inter" pide una Duvel. Está en la "Glorieta de los Caballitos", justo al lado de la Honda.
- Chai (Restaurante). Lugarcito bastante plascentero para ir a comer un sandwich o una baguette, o de plano tomar el café mientras lees tu blog favorito o el tu diario. Ofrecen servicio de Internet inalámbrico y si el clima te favorece, por qué no... pide terraza. Está sobre Av. Vallarta casi esquina Chapultepec.
- Pipiolo (Restaurante). Típico restaurante mexicano en donde preparan alambres, brochetas, quesadillas y carnes. El Filete tipo Pipiolo es su especialidad y por cierto: está buenísimo. Hay diversas sucursales, pide a tu taxista de confianza que te lleve al más cercano.
- La Terraza de la Abuela (Restaurante). Restaurante de cocina mexicana con muy buen sabor. Pide el caldo tlalpeño y alguna especialidad de la casa. Hay varias sucursales, pero la sucursal que está por el Centro Magno brinda un servicio de primerísimo nivel y sabe mejor.
- Carnes en su Jugo De La Torre (Restaurante). La especialidad de la casa "Carne en su Jugo" (obvio verdad?) no dudes en pedirla. Está super bueníiiiiiiiiiiisima. Tu platillo vendrá en compañía de algunas tostadas, huacamole, frijoles refritos y cebollitas asadas. Está sobre la Av. López Mateos entre la Glorieta de La Minerva y la Glorieta de los Caballitos. (Muchas gracias Blu, por la recomendación).
- El Santo Coyote (Restaurante). Cocina Mexicana de primer nivel en donde puedes probar suculentos platillos típicos y cortes de carne. Las instalaciones son de primer nivel y los platillos son exquisitos como para comer hasta reventar. No me acuerdo exactamente como llegar pero como es bastante famoso tu taxista favorito te llevará sin contratiempos.
- El Scratch (Bar). Si gustas del Blues este es el lugar para ti. Localizado en el centro histórico de la ciudad de Guadalajara, en este bar podrás disfrutar de un excelente grupo que toca como los grandes, también podrás ver videos rarísimos de este género musical. El ambiente es propicio para disfrutar tu cerveza favorita, y es bastante buena opción si andas cerca y ya es tarde.
- La Bodeguita del Medio (Restaurante-Bar). Uno de los restaurante-bares cubanos más famoso (sino el más famoso) el cuál no necesita descripción. Ningún Mojito sabe como en La Bodeguita del Medio. También llevate tu plumón para plasmar ese momento en la pared más cercana a tu mesa, en la del baño o de plano en tu ropa si ya andas de mala-copa.
- Red Pub (Bar). El concepto de este bar es de mis favoritos: Pequeño, barra con grifos de cerveza, cerveza artesanal riquísima y sobre todo... excelente música. Si te late el Grunge, Alternativo, Brit, Indie, Trip-hop, Industrialelectrónico ... este lugar sin duda es para ti. Localizado por Av. México... no me acuerdo muy bien dónde :D (mencioné que la cerveza está RIQUÍSIMA?)
- La Cantina de Los Remedios (Restaurante-Bar). Cantina a su máxima expresión (con estilo y calidad por supuesto), aquí puedes comer unos deliciosos tacos de arrachera, un corte de carne o una ollita de queso fundido con chorizo, acompañado de tu(s) cerveza(s) favorita(s). Es el típico lugar que regularmente visitaría por ejemplo Andrés de 2 a 2 (2pm a 2pm del siguiente día). Localizada cerca de Av. de las Rosas casi esquina con Av. López Mateos en la Colonia Chapalita aunque hay varias.
- Lonches Gemma (Restaurante). Si de tortas ahogadas o más bien de lonches se trata, en Lonches Gemma comerás delicioso. Si bien la original torta ahogada es de carnitas de cerdo ahogada -literalmente- en salsa roja, aquí podrás encontrar opciones menos agresivas para esa gastritis tan dulce que traes. Puedes encontrar de pierna, pollo, etc. con salsas menos picantes. Excelente opción cuando tienes poco tiempo para comer o cuando de plano andas muy bruja. Si no mal recuerdo hay varias sucursales, pero en La Gran Plaza (Av. Vallarta cerca del Men's Club (quéeeeeeeeee???)) hay un local en la planta alta.
- El Sax (Bar). Barcito pequeño, muy casero pero de buen ambiente en donde puedes escuchar a un vato (Gus) que toca bastante bien la lira y sobre todo que sabe de buena música. Está en la Colonia Minerva cerca de la Glorieta de los Naranjitos.
- La Matera (Restaurante). La Matera es un restaurante de cocina argentina en donde puedes disfrutar unas fabulosas empanadas de queso roquefort, de carne o de queso con cebolla, acompañadas del tradicional chimichurri, -el cuál preparan riquísimo en este restaurante-. Como plato fuerte puedes elegir un corte argentino (te recomiendo el Bife). Eso sí, si tu hotel está lejos es necesario que te regreses caminando ya que con 500grs. de carne sales con la pupila dilatada. Si tu destino no está muy lejos pues entonces date corriendo unas cuatro vueltas a la manzana. Se encuentra en Av. México como a una cuadra de la Av. López Mateos.
- La Moresca (Restaurante-Bar). La Moresca es un bar-restaurante fresoide en donde puedes disfrutar una gran variedad de platillos en los que se destacan las deliciosas pizzas (como la de cuatro quesos) y las ensaladas. Altamente recomendable para cenar y tomarte una chela, como la Minerva obscura (cerveza local artesanal... bastante buena). Ojo: si llegas a cenar espera hacer una fila de unos 20 a 30 minutos ya que este lugar es bastante concurrido. Se encuentra cerca del Centro Magno, por la Av. López Cotilla. Otra vez, agradezco a Blu su buena recomendación.
Si alguna vez se encuentran en WSS 3.0 con el siguiente error al guardar una lista como plantilla:
The list is too large to save as a template. The size of a template cannot exceed 10485760 bytes.
Esto se debe nada menos y nada más a que SharePoint soporta como máximo 10MB por plantilla. Para resolver lo anterior debemos usar STSADM.EXE de la siguiente manera:
stsadm -o setproperty -propertyname max-template-document-size -propertyvalue 52428800
... donde 52428800 es el número máximo expresado en bytes para el tamaño de las plantillas.
Una vez que ejecutemos lo anterior nos saldrá el siguiente mensaje:
Operation completed successfully
y listo.
Salu2!
This is the english version of my "Cómo ser un mejor desarrollador?" article
Maybe we have asked this question to ourselves a bunch of times. With so many technologies, acronyms and learning options available today it seems that the answer to this question is not as easy as it seems.
Maybe so many of you will respond right now: "Studying" or "Taking a Training Course", but: Is that enough?
Here's the list of things that -in my personal life- I try to do in order to be a better developer. The main idea behind the following list is to enrich it with your ideas and collaboration.
I don't know anything
Why? This is the most important start point and the most critic because the fundamental idea -like in any other learning process- is to recognize and accept our ignorance in so many and so huge topics and technologies. Take off our egocentrism allows us to open our mind to other kind of knowledge and other kind of questions. After all, we learn something from everyone each day. Remember that monotony is the mother of mediocrity.
Listen to PodCasts
Why? You can listen to the podcast at any time you want using your iPod, Zen, Zune, etc. in your car, at the office, at the gym, before sleep (please... BEFORE sleeping not WHILE YOU ARE sleeping ;)), etc. I mean: you can stay in contact with the specific topic whenever you want and you can combine it with another kind of activity (please be careful when driving because you couldn't say to the officer "I'm so sorry, I've crashed the car because I was listening how to create a workflow in WF..."). But which ones? Alright take these as a recommendation: Scott Hanselman's Hanselminutes and Ron Jacobs' ArCast. In these podcasts you can listen to so many topics about recent and upcoming technologies and in the other hand they are fun! Those guys really know what they're talking about...seriously.
Watch WebCasts
Why? I like Webcasts because they show and explain visually a specific topic; meanwhile the podcasts are audio-only. But which ones? I recommend: http://www.microsoft.com/events/default.mspx
Watch ScreenCasts
Why? A ScreenCast is a small video file that shows an specific technology topic in a "how-to" way. They just are awesome knowledge sources because they teach us how to perform the required tasks for the problem we're trying to resolve. But which ones? Obviously, it depends on the technology we're using. What about the ASP.NET, AJAX, Silverlight and Workflow Foundation as a startup?
Forum Participation
Why? The forums are a basic resource when we have a specific doubt related to technology. With the word Forum I refer to those Web-based and Newsgroups as well. Also we have the opportunity to answer the questions of any other people in the world that has a problem and maybe you know how to fix it. But which ones? Each technology has its own forum. Personally, I often visit the Workflow Foundation and Silverlight ones.
User groups meetings / Community meetings
Why? There's no better way of learning from others but in person, front to front about an specific topic. That's what .NET User Groups are for, to schedule meetings between different people geographically related in order to talk and show the technology. But which ones? There's always a .NET User Group near you. Visit MSN Groups to find more information about it.
Read Books
Why? The answer is obvious. Books are an ancient source of any kind of knowledge (hundreds and hundreds of years of manual and automatic printing can't be wrong). But which ones? Personally, I like Programmer-To-Programmer books from Wrox (yeah, the red ones). Another great development books are Microsoft .NET Development Series books because they are written by truly experts.
Read Blogs
Why? A web log is a personal log from other's ideas, thoughts and technical articles from its author and it's accessible via Web. A good example is this blog where I'm writing my own opinions in how to be a better developer. Is this The Ultimate Special Platinum Double-Pack Director's Cut Extended Anniversary Edition Article about it? Of course not! And it's not meant to be like that tho. It's just a way to synthesize what I do in order to be a better developer and it's a mechanism to share it and to obtain feedback about it. But which ones? I could write down here all my feeds but I'll just write the ones that I read day by day:
ScottGu
Soma
Silverlight
Eric Sink
Joel on Software
Erika Ehrli
Learn to use other technologies
Why? Yes. We are geeks. And we love Microsoft development technologies, but we would be blind or crazy if we wouldn't recognize that there's a bunch of other excellent technologies and that not everyone in this world use the same tools as we do. In the other hand, they're not absolutely necessary to be non-Microsoft technologies. For example, IronRuby is a technology that I don't know how to use it but it seems to me very powerful and interesting enough to try to learn from it. But which ones? There's a lot right in front of our eyes. For example I'm currently using and learning ActiveRecord. Other technologies in my "To-Learn" list are: IronRuby, IronPython, F#, Microsoft Sync Framework and ASP.NET MVC Framework.
Adopt a Development Methodology
(Very special thanks to Misael for this one)
Why? A methodic person has more control over the things he performs, and he can identify where he is and what step follows in his development path: Identify, Measure, Document, Secure and Control are steps that can be reached using the correct methodology. But which ones? There are so many methodologies but the must important could be the following:
Do not procrastinate
Why? Up to this point, we have mentioned a list of learning resources that we can use in order to be better developers. But we need the tactics and strategy, and these are of course: Discipline. We need a great effort and discipline in order to accomplish our goal and to stop using and doing the things that waste our time. YouTube, FaceBook, MSN Messenger are just a few of those things that come to my mind right now. No excuses (like Alice in Chains once said) please. Remember how we worked 10 years ago. Let's measure our procrastination level: If you think this is a very drastic solution then you have a very serious procrastination problem. But, if you are willing to stop wasting your time (you know you do!) then: Congratulations, your procrastination problem can be cured.
Try to hang up with people that love software development
At last but not least, it's very important to look for people that are just as restless as you are and have the same learning goals (please refer to point number one). Once you find them then it will be very helpful to talk and chat with them, and get support from them in your process of personal improvement. That process would be less painful and more fun!
This article was not meant to be a meme but I would like for this topic that the following people could share their own thoughts and ideas: