Microsoft SQL Server Management Studio 2008: Error 916

MSSQL, Microsoft SQL Server No Comments »

Encontré un problema al tratar de conectarme con Microsoft SQL Server Management Studio 2008 (SSM) a una instancia de SQL Server 2008. La base de datos se encuentra en un servidor de desarrollo que tenemos en la oficina. Después de conectarme a la base con credenciales de Windows, por alguna razón no lograba acceder a las bases de datos. Al dar click sobre el nodo “Database”, dentro del Explorar del “Object Explorer”, me arroja el siguiente mensaje:

Microsoft SQL Server Management Studio 2008 - error

Microsoft SQL Server Management Studio 2008 - Error 916

Cuando se expande el nodo de bases de datos, SSM recolecta información sobre cada base de datos del servidor. Esa información es la misma que aparece en el “Object Explorer Details View” (pueden desplegar esa vista tecleando F7 una vez conectado a la instancia en SSM). El problema es que la información a recolectar no está disponible para las bases de datos apagadas o con la propiedad “AutoClose” prendida.  Si SSM no logra recibir toda la información que requiere, ejecuta un query hacia las bases de datos para tratar de completar su recolección de datos. Dos problemas pueden suceder:

  • Si muchas bases de datos tienen la propiedad “AutoClose” prendida, la lista puede tardar mucho tiempo en desplegarse ya que SSM tiene que abrir una conexión y consultar todas las bases
  • Si el usuario no tiene derechos para consultar una base de datos, se arroja un error en SSM
  • En mi caso, es obviamente la segundo opción que aplica. Lo único que se puede realizar es apagar la propiedad “AutoClose” de todas las bases de datos y asegurar que el siguiente query nunca contenga ningún registro:

    SELECT * FROM sys.databases WHERE is_auto_close_on = 1

    El bug ya ha sido reportado en Microsoft. Si también te encontraste con ese problema, regístrate y agrega un upvote.

    La tarea no se ejecutó porque no se encontó AL.exe

    Visual Studio 2008 No Comments »

    Recientemente, estuve trabajando en Visual Studio 2008 con varias soluciones hechas con la versión 2005 del IDE. Pude importar y convertirlas sin mayor problema pero a la hora de compilar, varios proyectos empezaron a quejarse y se me presentó el siguiente error:

    Error 42
    La tarea no se ejecutó porque no se encontró "AL.exe" o porque no está instalado el SDK correcto de Microsoft Windows.
    La tarea busca "AL.exe" en el subdirectorio "bin", bajo la ubicación especificada en el valor InstallationFolder de la clave del Registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A.
    Para resolver el problema, realice una de las siguientes acciones:
    1) Instale Microsoft Windows SDK para Windows Server 2008 y .NET Framework 3.5.
    2) Instale Visual Studio 2008.
    3) Establezca manualmente la clave del Registro especificada anteriormente en la ubicación correcta.
    3.) Pase esta ubicación al parámetro "ToolPath" de la tarea.
    

    El mensaje indica que el proceso de compilación no encuentra el ejecutable “AL.exe”. El Assembly linker es una herramienta que ocupa Visual Studio para generar un assembly a partir de módulos escritos en MSIL (lenguaje intermedio de Microsoft) y archivos de recursos. El Assembly Linker viene incluido con el IDE, si no lo tienen instalado, deben descargar el Microsoft SDK e instalarlo. Si igual que yo, ya lo tienen instalado deben abrir el registro mencionado y verificar que el valor de la clave “InstallationFolder” apunte hacia la ubicación del Assembly Linker en su máquina. En caso que se requiera, deberán actualizar el valor de este registro. Después, también será necesario agregar una nueva variable de entorno  como lo pueden ver en la siguiente imagen:

    ALTOOLPATH

    ALTOOLPATH

    El nombre de la variable de entorno es “ALTOOLPATH” y su valor en mi máquina es “C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\al.exe”. Ahora, abran Visual Studio y compilen la solución. Todo debería funcionar correctamente y si no, espero sus comentarios.

    ¿Cómo habilitar el servicio Full-text Indexing en MSSQL 2008?

    MSSQL No Comments »

    La búsqueda de texto completo (full text search) es una técnica para buscar texto en un documento o en una base de datos. El motor de la búsqueda se encarga de examinar todas las palabras de un documento y las compara con las palabras proporcionadas por un usuario. La búsqueda es completa porque todas las palabras de los documentos o de la base de datos se ocupan. No todas las búsquedas son completas. En el caso de los sitios web, existe por ejemplo la búsqueda por tags que examina solamente el catálogo de tags y no el contenido tageado. Es una táctica menos costosa y que puede ser bastante potente si el contenido está correctamente tageado. Tambien vale la pena mencionar que el mismo sistema gestor de base de datos dispone de varios técnicas para consultar una tabla: Table Scan, Index Seek, etc.

    ¿Cuando se requiere ocupar la búsqueda de texto completo? Como todos lo saben, en SQL Server igual que en cualquier otro sistema gestor de base de datos ya existen comandos que permiten realizar búsquedas en tablas. Por ejemplo, si queremos buscar el país ‘México’ en un catálogo de paises, basta con ejecutar el siguiente comando SQL:

    SELECT * FROM Pais WHERE nombre = 'México'
    

    Esto es más que suficiente para ese tipo de búsquedas. Sin embargo, existen casos dónde se requiere recurrir a consultas más complejas donde por ejemplo:

    - se ocupan documentos o tablas con un volumen importante.
    - se realiza una búsqueda con más de una palabra o una frase.
    - la cercanía de las palabras es relevante: se busca la palabra ‘México’ y ‘playa’ con 5 palabras o menos entre cada uno.
    - se asignan pesos/importancias diferentes en cada palabra de una frase.
    - se necesita considerar las derivaciones de una palabra o de un verbo (ejemplo: correr, corrimos, corre).
    - se necesita realizar un búsqueda en campo binario (varbinary o image).
    - se toman en cuenta sinonimos (tesaurus)

    El Full-Text Engine que dispone SQL Server 2008 permite contestar de forma eficaz a estas consultas, sus táreas más importantes son la indexación y la consulta. La indexación consiste en la creación de una tabla donde se almacenan todas las palabras encontradas en los textos analizados. Por cada palabra se conservan datos como su posición en los documentos, su frecuencia,… No todas las palabras se indexan. El motor de indexación utiliza stoplists (compuestas de stop words) para ignorar palabras como “de”, “la” o “en” con poca relevancia.

    Antes, con SQL Server 2000, la indexación se realizaba mediante el servicio MSSEARCH Service (Microsoft Search). Este servicio presente en cada sistema operativo tenía la desventaja de ser compartido con otros procesos como SharePoint o Exchange. Se mejoró esa situación con SQL Server 2005 ya que se agregó funcionalidad para poder crear instancias exclusivas del servicio de búsqueda (Microsoft Full-Text Engine for SQL Server). Sin embargo, una de las consecuencias negativas de esta arquitectura divida entre varios procesos es que los datos indexados no se están respaldando en la base de datos si no en el servicio de búsqueda (externo a la base de datos), lo cual podía complicar la tarea del DBA a la hora de realizar réplicas de una máquina a otra. Al contrario de la versión 2000 & 2005, el Full-Text Engine de SQL Server 2008 está ahora totalmente integrado al mismo proceso de SQL Server como cualquier otro tipo de servicio de la base de datos. Este cambio estructural es muy importante y trae consigo beneficios tanto de rendimiento como de seguridad (leer más en MSDN).

    En el siguiente ejemplo, vamos a crear un catálogo de indexación para una tabla de comentarios de un blog ficticio. El Full-Text Engine no está incluido en todas las versiones de SQL Server 2008. Si igual que yo trabajan con la versión Express, deben descargar la versión Express with Advanced Services. Pueden verificar que tengan el servicio instalado mediante la siguiente instrucción:

    SELECT fulltextserviceproperty('isfulltextinstalled')

    Luego, vamos a crear una base de datos para hacer nuestras pruebas:

    USE master
    IF DB_ID('full_text_db') IS NOT NULL
    DROP DATABASE full_text_db
    CREATE DATABASE full_text_db
    GO
    

    Se tiene que verificar que nuestra base de datos tenga la búsqueda de texto completo activado:

    SELECT DATABASEPROPERTY('full_text_db', 'IsFullTextEnabled');

    Si el servicio no está habilitado sobre la base de datos que creamos, lo pueden activar de la siguiente manera:

    USE full_text_db
    GO
    EXEC sp_fulltext_database 'enable'
    

    Ya con nuestra base de datos lista, podemos crear nuestro catálogo de indexación:

    CREATE FULLTEXT CATALOG comentariosFullTextSearch

    Creamos la tabla de comentarios cuyo contenido vamos a indexar. Es obligatorio crear un índice sobre esa tabla ya que el servicio de indexación lo requiere:

    CREATE TABLE Comentarios (
    ID [int] IDENTITY(1,1) NOT NULL,
    contenido VARCHAR(8000) NOT NULL,
    CONSTRAINT [PK_Comentarios] PRIMARY KEY CLUSTERED
    (
    ID ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    

    Nada más se tienen que indexar la columnas que se requieren. En nuestro caso vamos a avisar al Full-Text Engine que queremos indexar a la columna ‘contenido’. Mediante la instrucción ‘Language’ indicamos en que idioma está el texto que contiene la tabla:

    CREATE FULLTEXT INDEX ON Articulo
    (
    contenido
    Language 0XC0A -- Local ID para español - 3082/0XC0A
    )
    KEY INDEX PK_Articulo ON articulosFullTextSearch
    WITH CHANGE_TRACKING AUTO
    

    Nada más nos queda llenar nuestra tabla con datos de prueba y lanzar la indexación. Por lo general, la indexación se dispara de forma automática y se actualiza regularmente cada vez que se cambian datos en una columna indexada por ejemplo:

    INSERT INTO Comentarios VALUES ('México es muy lindo.')
    INSERT INTO Comentarios VALUES ('Me gusta Méchico.')
    INSERT INTO Comentarios VALUES ('¡Viva Méjico!')
    GO
    ALTER FULLTEXT INDEX ON Comentarios
    START FULL POPULATION
    

    Si todo salió correctamente, ya deben de poder ejecutar la siguientes consultas y empezar a hacer uso del catálogo de indexación que creó el Full-Text Engine para nosotros:

    SELECT * FROM Comentarios WHERE CONTAINS(contenido, '"*México*"')
    SELECT * FROM Comentarios WHERE CONTAINS(contenido, '"México*" OR "Méjico"')
    

    En mi siguiente post, les daré más explicación sobre los predicados CONTAINS y FREETEXT y sobre cómo armar consultas con sinónimos usando un archivo XML (tesaurus).

    FUENTES:
    http://en.wikipedia.org/wiki/Full_text_search
    http://msdn.microsoft.com/es-es/library/ms142571.aspx

    ¿Por qué desparece la opción de proyectos en visual Studio Express 2008?

    Visual Studio 2008 No Comments »

    Ya van varias veces que por alguna misteriosa razón desaparece la opción de abrir/cerrar proyectos en mi versión Express de Visual Studio 2008. Hace poco desintalé SQL Server Express 2008 para luego instalar la versión avanzada (with Advanced Services) con el fin de aprovechar el motor de búsqueda Full-Text Search. Después de la instalación, había desaparecido la opción de proyecto en el menú:

    VSExpress 2008 (sin opción de proyectos)

    Para regresar esa opción:
    1. Abre tu IDE
    2. Herramientas -> Importar y exportar configuraciones
    3. Seleciona “Restablecer todas las configuraciones”
    4. Puedes conservar tu configuración pero no es obligatorio
    5. Selecciona ‘Finalizar’ y listo!

    Para regresar esa opción:

    1. Abre tu IDE.

    2. Herramientas -> Importar y exportar configuraciones.

    3. Seleciona “Restablecer todas las configuraciones”.

    4. Puedes conservar tu configuración pero no es obligatorio.

    5. Selecciona ‘Finalizar’ y listo!

    VSExpress 2008 (con opción de proyectos)

    ¿Cómo utilizar ssbdiagnose para depurar un Service Broker?

    MSSQL, Service Broker No Comments »

    En un artículo anterior, expliqué los pasos básicos para instalar un Service Broker. Por su naturaleza asíncrona, no siempre es fácil depurar errores de dicho Servicio. Además, varios componentes están involucrados en el buen funcionamiento del proceso: cola de mensajes, mensajes, contratos, servicios de emisión y de recepción, stored procedure de activación, etc. Para poder depurar el Service Broker, existe la herramienta “ssbdiagnose”. Esta utilidad sirve parta detectar problemas que ocurren en conversaciones o en la configuración del Service Broker. Es bastante sencillo usarla, funciona para servidor locales como remotos. Si tienes Sql Server 2005 o 2008 instalado, ssbdiagnose se encuentra en:

    C:\Program Files\Microsoft SQL Server\100\Tools\Binn

    Se dispara una diagnostico con el siguiente comando:

    ssbdiagnose -XML -E -S ".\SQLEXPRESS" -d service_broker_db CONFIGURATION FROM SERVICE ServicioEmisor TO SERVICE ServicioRecepcion ON CONTRACT ContratoCalculoPosiciones > C:\sbOutputXML.xml

    El parámetro -XML indica que la salida será en el formato XML y se podrá consultar en el archivo C:\sbOutputXML.xml. El parámetro -E avisa que se usarán las credenciales windows del usuario actualmente logeado para conectarse a la instancia de la base de datos service_broker_db. Las demás instrucciones sirven para mandar un mensaje del servicio de emisión hacia el servicio de recepción usando el contrato ‘ContratoCalculoPosiciones’.

    Cuando levanté por primera vez una instancia del Service Broker, por alguna razón los mensajes de la cola nunca se procesaban. Usando ’ssbdiagnose’ descubrí dos problemas bastante graves. Resolviéndolos pude hacer funcionar mi instancia. El primer error que me arrojó fue:

    <Issue code="29997" level="Error" type="Diagnosis" server=".\SQLEXPRESS" database="service_broker_db ">Service Broker GUID is identical to that of database service_broker_db on server .\SQLEXPRESS</Issue>

    El error indica que el Globally Unique Identifier del Service Broker está duplicado en la base de datos. Para visualizar los GUID de todos los Service Broker, ejecuta el siguiente query:

    SELECT
    name
    ,is_broker_enabled
    ,is_honor_broker_priority_on
    ,is_trustworthy_on
    ,service_broker_guid
    FROM sys.databases
    ORDER BY service_broker_guid
    

    Este error sucede cuando un base de datos se importa desde otro servidor. La solución consiste en regenerar el GUID del Service Broker:

    ALTER DATABASE [service_broker_db] SET NEW_BROKER;
    

    Después de generar el GUID, me encontré el siguiente error (blilingüe!):

    The EXECUTE AS for the user dbo specified for activation on queue dbo.MiStoredProcedure cannot be impersonated due to an exception No se puede ejecutar como la entidad de seguridad de base de datos porque la entidad de seguridad "dbo" no existe, este tipo de entidad de seguridad no se puede suplantar o el usuario no tiene permiso.

    El problema descrito aquí tiene mucho que ver con el anterior. La base de datos que usé era una copia de una base creada en otra máquina. El comando ‘EXECUTE AS’ necesita permisos para ejecutarse y no están disponibles dado que el ‘owner’ de la base no está definido correctamente. Se puede arreglar este problema de permisos con el siguiente comando:

    ALTER AUTHORIZATION ON DATABASE::[service_broker_db] TO [SA];

    Ya con estos dos errores arregledos, los mensajes de la cola empezaron a ser procesados por el servicio de recepción.

    Se puede depurar un Service Broker “a mano” pero es mucho más complejo y largo que utilizar la herramienta “ssbdiagnose”. Espero que también les ayude en algo!

    Información de MSDN sobre “ssbdiagnose”.

    Configurar Service Broker con SQL Server 2008

    MSSQL, Service Broker 3 Comments »

    Recientemente, estuve involucrado en el desarrollo de una trivia online para niños. Durante 3 meses, 12 retos se publicaron y unos 20k jugadores se registraron. Conforme avanzaban las semanas, los niños iban ganando puntos. Desde el primer día de la trivia, estaba disponible una página con la lista de jugadores ordenados por puntos y fecha de participación. Para generar ese listado, se tenía que realizar una suma de todos los puntos de cada jugador y luego ordenarlos por puntos obtenidos. Durante las primeras semanas, el listado se cargaba sin problema. Pero como lo podrán imaginar, el query se hizo poco a poco más y más lento. El cálculo ya involucraba muchos datos y aunque logramos mejorar un poco el query, no dejaba de alentarse con los días.

    Obviamente, fue necesario encontrar una solución. Como el query estaba alentando mucho la generación de la lista de ganadores, se me ocurrió que era necesario mandar su ejecución en un proceso asíncrono al thread principal. Cada vez que un jugador grabe algún punto, se tendrá que calcular nuevamente los resultados pero sin afectar a la consulta de la tabla de ganadores.

    Existen varias maneras de crear un proceso asíncrono con SQL Server 2008 pero una de éstas consiste en utilizar el no muy famoso Service Broker:

    service_broker_mssql2008

    El Service Broker permite implementar un servicio de mensajería bastante robusto sin salirse de la base de datos. En computación, una mensajería (o cola de mensajes) es un componente lógico que se ocupa para permitir la comunicación entre procesos. Además provee un protocolo de comunicación asíncrona en el cuál el emisor y el receptor no deben interactuar con el mensaje al mismo tiempo. El emisor agrega un mensaje a la cola y el receptor lo consulta en otro momento.  En mi caso, la ejecución del query es mi “mensaje”. El emisor es la trivia y el receptor es el Service Broker. Cada vez que un niño marca puntos, la aplicación mete en la cola un mensaje para ejecutar el cálculo de posiciones. Luego, el Service Broker se encarga de ejecutar el cálculo sin interumpir al thread principal. Y no importa si varios jugadores están grabando puntos al mismo tiempo, porque por cada nuevo punto, el Service Broker se encargará de recalcular la tabla de posiciones.

    Originalmente, el Service Broker ha sido diseñado para permitir intercambiar datos entre bases de datos distribuidas y así repartir la carga de ejecución entre varias máquinas. Sin embargo, también se puede utilizar, como en mi caso, adentro de la misma base de datos y en el mismo servidor. Ahora, ¿cómo implementar este servicio? Desafortunadamente, no existen tantos artículos sobre este componente como me lo esperaba. Tuve que buscar y debugear un buen antes de poder levantar mi propio servicio. La buena noticia es que valió la pena el esfuerzo. Aquí les explico cómo armar un servicio de mensajería sencillo.

    Antes que todo, se tiene que confirmar que la base de datos tiene el Service Broker habilitado. Esto se puede visualizar en las propiedades de la base de datos:

    service_broker_habilitado

    Se puede habilitar mediante la siguiente instrucción SQL:

    ALTER DATABASE miBD SET ENABLE_BROKER
    

    En los dos casos, la instrucción puede tardar un poco en ejecutarse. Cuando ya está lista nuestra base de datos, podemos empezar a configurar los componentes del servicio. Para proteger los accesos y las lecturas de los mensajes, se tiene que definir tanto el tipo de mensaje que se va a manejar, así como el contrato que va a existir entre el emisor y el receptor. Se puede requerir, por ejemplo, que los mensajes sean en formato XML y obligar el servicio a validar ese formato durante la transmisión de los mensajes. En nuestro caso, vamos a ocupar el formato más sencillo y sin requerir validación ninguna:

    CREATE MESSAGE TYPE CalcularPosiciones VALIDATION = NONE;
    

    Los intercambios de mensajes entre emisor y receptor se llaman conversaciones. Cada conversación está asociada con un contrato.  El anterior define el sentido de la conversación (de emisor a receptor o vice-versa) así como el tipo de mensaje que se puede intercambiar. Nuestro contrato define que solamente se pueden intercambiar mensajes de tipo ‘CalcularPosiciones’ y que sólo el iniciador de la conversación puede mandar mensajes de este tipo :

    CREATE CONTRACT ContratoCalculoPosiciones
    (
    CalcularPosiciones SENT BY INITIATOR
    )
    

    Luego, se crea una cola que se va a encargar de procesar cada nuevo mensaje. La configuramos con un estatus activo. La propiedad MAX_QUEUE_READERS indica si se pueden o no procesar varios mensajes a la vez. Para evitar colisiones, dejamos esta propiedad en un 1. El stored procedure ’spCalcularPosiciones’ será disparado por cada activación de la cola de recepción. Como lo veremos más adelante, este stored procedure se encargará del cálculo de la tabla de posiciones.

    CREATE QUEUE [ColaRecepcion];
    ALTER QUEUE [ColaRecepcion] WITH ACTIVATION
    (
    STATUS = ON,
    MAX_QUEUE_READERS = 1,
    PROCEDURE_NAME = spCalcularPosiciones,
    EXECUTE AS SELF
    );
    

    Para que la cola de recepción funcione, se le tiene que asociar a un servicio de recepción. El servicio tiene como tarea entregar los mensajes a la cola. Se asocian de la siguiente forma:

    CREATE SERVICE [ServicioRecepcion] ON QUEUE [ColaRecepcion]([ContratoCalculoPosiciones]);
    

    Para poder mandar los mensajes, se necesita crear una cola de envío y asociarla con un servicio emisor:

    CREATE QUEUE [ColaEmisor];
    CREATE SERVICE [ServicioEmisor] ON QUEUE [ColaEmisor];
    

    Ya tenemos listas nuestras dos colas de mensajes así como nuestros servicios. Ahora nos falta crear el stored procedure que se va a disparar por cada mensaje recibido:

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE PROCEDURE [dbo].[spCalcularPosiciones]
    AS
    BEGIN
    SET NOCOUNT ON;
    DECLARE @Handle UNIQUEIDENTIFIER;
    DECLARE @MessageType SYSNAME;
    DECLARE @fecha DATETIME;
    
    RECEIVE TOP (1)
    @Handle = conversation_handle,
    @MessageType = message_type_name
    FROM [ColaRecepcion];
    
    SELECT @Handle
    IF(@Handle IS NOT NULL)
    BEGIN
    -- Calcular puntos de todos los jugadores e insertarlos en la tabla de resultados
    -- Para efectos de prueba, también se puede inserta un registro en alguna tabla con efecto de crear un log de los movimientos de cada mensaje
    END
    END
    

    El stored procedure se encarga de buscar, con la instrucción RECEIVE, el último mensaje disponible en la cola. Se recupera el ‘handle’ de la conversación. Cada intercambio
    de mensaje se asocia con un handle, un identificador único. Después de recuperar el último mensaje, se realiza el cálculo de las posiciones de cada jugador o cualquier otro tipo de cálculo que necesiten.

    Ya están listos todos los componentes. Ahora, nada más nos falta probar que todo esté funcionando correctamente. Para mandar un mensaje a la cola, se ocupan las siguientes instrucciones:

    DECLARE @MessageBody XML
    SET @MessageBody = '';
    
    DECLARE @Handle UNIQUEIDENTIFIER;
    
    BEGIN DIALOG CONVERSATION @Handle
    FROM SERVICE [ServicioEmisor]
    TO SERVICE 'ServicioRecepcion'
    ON CONTRACT [ContratoCalculoPosiciones]
    WITH ENCRYPTION = OFF;
    
    SEND ON CONVERSATION @Handle
    MESSAGE TYPE [CalcularPosiciones](@MessageBody);
    

    Una vez que se manda el mensaje, el servicio de recepción se activa y agrega el mensaje a la cola de recepción que a su vez dispara nuestro stored procedure. Si todo sale bien, se debe ejecutar correctamente nuestro cálculo de posiciones. El envío del mensaje se puede incluir, por ejemplo, en un trigger asociado con la inserción de registros en una tabla. En mi caso, agregue un trigger a la tabla de puntos. Cada vez que un jugador inserta puntos en esa tabla, se dispara un mensaje nuevo hacia nuestro Service Broker. La gran ventaja de este servicio de mensajería es que la inserción de los puntos ya no está afectada por el cálculo de posiciones. Mientras se insertan nuevos puntos, el cálculo se ejecuta pero de forma asíncrona sin alentar el thread principal. Gracias a este servicio, la consulta de la tabla de posiciones ya no está alentada por ningún cálculo y tiene un tiempo de respuesta inmediata.

    Esta implementación del Service Broker es bastante sencilla. Si requieren configurarla para un desarrollo más complejo, les aconsejo consultar el blog de Remus Rusanu. Este blog contiene los artículos más completos que he visto sobre el Service Broker. También, pueden consultar una pregunta que dejé en el sitio de Stackoverflow.

    FUENTES:
    Crear Base de Datos (.sql)
    Crear Service Broker (.sql)
    Activar Service Broker (.sql)
    Borrar Service Broker (.sql)

    Spring & ActionScript 3.0 (en 3 pasos)

    ActionScript, Spring Framework No Comments »

    El ya famoso Spring Framework ahora también llega al mundo de ActionScript 3.0. La principal ventaja del contenedor Spring es que permite plasmar la creación de los objetos y sobre todo las relaciones entre los objetos desde un archivo de configuración XML (o varios). Se utiliza la palabra contenedor ya que Spring funciona como un escenario donde actúan todos los objetos de una aplicación. Tradicionalmente, la instanciación de objetos se ha realizado directamente desde el código. Con Spring ocurre lo que se llama una inversión de control ya que es el mismo contenedor el que se encarga de crear los objetos así como sus respectivas dependencias (herencia, interfaz, asociación, etc.). Uno se desconcierta un poco cuando empieza a trabajar con este tipo de contenedores. Esto sucede porque el control de la ejecución de la aplicación ya no es completo. Aparece un nuevo actor durante la ejecución cuyo trabajo es manejar el ciclo de vida de cada objeto. Esta inversión de control permite al desarrollador crear aplicaciones más flexibles (porque son más configurables) además de externalizar las dependencias entre componentes, y por lo tanto crear clases más fáciles de reutilizar.

    Spring ActionScript está escrito en ActionScript 3.0, su migración ha sido realizada principalmente por Christophe Herreman, inicialmente bajo el nombre de Prana Framework. Actualmente, el proyecto ha sido aceptado como una extensión oficial del Spring Framework.

    El propósito de este post es enseñarles cómo preparar su entorno de trabajo para poder disfrutar de Spring ActionScript desde Flash CS3. Primero, necesitamos descargar el contenedor. Lo pueden conseguir aquí. Coloquen los archivos fuentes (’org\springextensions\actionscript\*’) en la raíz del directorio donde van a trabajar. También se necesita bajar las fuentes de la biblioteca as3reflects desde as3commons. Asimismo, las fuentes se deben colocar en la raíz (’as3reflect\*’).

    Con el Framework instalado, ya podemos empezar a crear nuestro objeto de prueba. El primer paso consiste en crear una clase sencilla que tendrá como única propiedad su nombre además de su respectivo setter & getter: 

    package com.springframework
    {
       public class MiBean
       {   
           // ------- Constructor -------
           public function MiBean() { }
    
           // ------- Propiedades -------
           protected var _nombre:String;
           public function set nombre(value:String):void { _nombre = value; }
           public function get nombre():String { return _nombre; }
       }
    }
    

    El archivo debe llamarse ‘MiBean.as’ y ubicarse en el directorio ‘com\springframework’.

    En el segundo paso, vamos a crear nuestro archivo de configuración XML. Este archivo va a indicar al contenedor qué objeto se necesita instanciar y qué valor se asignará a la propiedad ‘nombre’:

    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.pranaframework.org/objects"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.pranaframework.org/objects http://www.pranaframework.org/schema/objects/prana-objects-0.6.xsd">
    <object id="miBean" class="com.springframework.MiBean">
    <property name="nombre" value="jdecuyper" />
    </object>
    </objects>
    

    En nuestro tercer y último paso, vamos a crear un archivo .fla en el cual se va a crear el contenedor Spring. Usando nuestro archivo de configuración, el contenedor va a instanciar la clase MiBean y pasarle el valor ‘jdecuyper’ a su propiedad ‘nombre’. En el primer frame de nuestro archivo, se coloca el siguiente código:

    import com.springframework.MiBean;
    import org.springextensions.actionscript.context.support.XMLApplicationContext;
    registerClassAlias("com.springframework.MiBean", MiBean);
    
    var xmlApplicationContext:XMLApplicationContext;
    xmlApplicationContext = new XMLApplicationContext("http://localhost/springactionscript/applicationContext.xml");
    xmlApplicationContext.addEventListener(Event.COMPLETE, applicationContextCompleteHandler);
    xmlApplicationContext.load();
    
    function applicationContextCompleteHandler(e:Event):void {
    var miBean:MiBean;
    miBean = xmlApplicationContext.getObject("miBean");
    trace(miBean.nombre);
    }
    

    La clase XMLApplicationContext sirve para crear el contenedor, también se conoce como la ‘bean factory’. El método ‘getObject’ se encarga de regresarnos una referencia a nuestro objeto. Una vez que MiBean está instanciado, se manda a llamar su propiedad ‘nombre’, y si todo sale bien, se pintará ‘jdecuyper’ en su ventana de debug.

    Les dejo con este ejemplo bastante sencillo pero que espero les pueda servir de inicio para desarrollos más complejos.

     

    ¿Cómo crear un branch desde algún repositorio?

    SVN 5 Comments »

     

    1. Click derecho en el directorio dónde se va a trabajar. 

    2. Selecionar Tortoise SVN -> Checkout (selecionar HEAD revision o alguna anterior).

    3. Selecionar Tortoise SVN -> Branch/Tag. Ingresar la URL dónde se tendrá que almacenar el nuevo “branch” .

    Tortoise - Crear Branch

     

    Tortoise nos avisa que nuestro working copy todavía pertenece al trunk y no al branch creado. 

     

    Tortoise - Switch

     

    Para cambiarse al branch, seleciona Tortoise SVN -> Switch, luego indica la URL del branch que requieres.
    A partir de ahora, los cambios que se harán al proyecto ya no afectarán el trunk. Si en algún momento, se decide intregar los cambios del branch al trunk, se utilizará el comando merge.

     

    ¿Cómo correr programas en segundo plano como servicios de windows?

    Windows Service 7 Comments »

    Recientemente me encargaron una aplicación que leyera varios feeds y los almacenara en una base de datos sin que tuviera que intervenir un usuario. Y se me ocurrió que crear un servicio de windows sería la mejor forma de hacerlo.

    Para ponerlo en palabras sencillas, un servicio windows es un ejecutable que -en segundo plano- realiza tareas especificas como monitorear cambios en archivos del sistema o en perifericos (USB, disco duro externo,…), o cualquier cosa que necesitemos hacer automáticamente, por ejemplo recordatorios o enviar correos. Su característica más interesante es que un servicio no requiere intervención de un usuario, funcionan al fondo. Por lo mismo, en la mayoría de los casos no son visibles en el entorno UI del usuario (aunque no es el caso, por ejemplo, de la consola SQL server Service Manager de MS SQL Server). La no-visibilidad y la autonomía de esos procesos, ocasionó, en el mundo UNIX®, su asosiación con la palabra “daemon”. Aunque se parecen, las palabras “daemon” y “demonio” no significan lo mismo. Evi Nemeth, co-autora del libro “UNIX System Administration HandBook“, indica lo siguiente:

    Many people equate the word “daemon”‘ with the word “demon”, implying some kind of Satanic connection between UNIX and the underworld. This is an egregious misunderstanding. “Daemon” is actually a much older form of  “demon”; daemons have no particular bias towards good or evil, but rather serve to help define a person’s character or personality. The ancient Greeks’ concept of a “personal daemon” was similar to the modern concept of a “guardian angel” — “eudaemonia” is the state of being helped or protected by a kindly spirit. As a rule, UNIX systems seem to be infested with both daemons and demons.

    El servicio que desarrolle se encarga, mediante un uso básico de threads, de hacer peticiones HTTP a una serie de ligas RSS. El resultado de las peticiones se procesan y almacenan en una base de datos. Visual Studio 2005 y 2008 ofrecen todo lo necesario para desarrollar un servicio de tipo “Hello world” en unos instantes. Les aconsejo desarrollar primero una aplicación de consola y luego pasar su código en un servicio para evitar perder tiempo en instalar y desinstalar el servicio durante la fase de debugeo. Cuando tiene listo su ejecutable, nada más le falta instalarlo mediante la herramienta installutil.exe que se encuentra en:

    %SystemRoot%\Microsoft.NET\Framework\v2.0.50727

    Para installar el servicio:

    installutil "C:\serviciosWindows\miAssembly.exe"

    Para installar el servicio y cambiar la ruta del log de instalación:

    installutil
    /LogFile="C:\serviciosWindows\log\instalUtil.installLog"
    "C:\serviciosWindows\miAssembly.exe"

    Para desinstallar el servicio:

    installutil /u "C:\serviciosWindows\miAssembly.exe"

    No tuve ningún problema para instalar mi servicio en XP Pro. Sin embargo, cuando lo intente hacer en una máquina Vista me encontre con unos problemas de seguridad. A la hora de arrancar, el servicio lanzaba un error en el CLR Debugger:

    No se controló System.Security.SecurityException
    Message="No se encontró el origen, pero no se pudo buscar en algunos o
    todos los registros de eventos. Registros inaccesibles: Security."
    Source="System" StackTrace: en System.Diagnostics.EventLog.FindSourceRegistration(String source,
    String machineName, Boolean readOnly) en System.Diagnostics.EventLog.SourceExists(String source, String machineName) en System.Diagnostics.EventLog.SourceExists(String source) en Lab.MiServicio..ctor() en Lab.Program.Main()

    Y del lado de la consola de los servicios (services.msc):

    Windows no pudo inicar el servicio "" en Equipo local. Error 1053: El servicio no respondió a tiempo a la solicitud de inicio o de control.

    Cuando un servicio arranca, intenta registrarse en el visor de eventos. Si no tiene los permisos necesarios, se termina inmediatamente. Para evitar esta restricción, se tiene que abrir el cmd con los derechos de administrador y luego ejecutar el commando de instalación. Además de ser una herramienta muy poderesa, los servicios generalmente obligan el programador a trabajar con threads. Lo cual implica unos dolores de cabeza pero nuevas ideas para solucionar problemas de computación.

    Ligas de interés:

    http://www.freebsd.org/copyright/daemon.html
    http://es.wikipedia.org/wiki/Daemon

    WP Theme & Icons by N.Design Studio
    Entries RSS Comments RSS Log in