Mashups, más allá de la generación de informes

Creación de un widget de formulario para utilizar con feeds de actualización relacional de IBM Mashup Center

Los desarrolladores de todo tipo pueden ocasionalmente tener la necesidad de crear una aplicación que realice actualizaciones simples a la tabla de una base de datos. Este artículo describe cómo crear un widget del IBM® Mashup Center que pueda desplegar un formulario HTML que permite a los usuarios actualizar tablas de bases de datos relacionales. De manera opcional, usted puede crear rápidamente su propia página mashup utilizando simplemente el widget descargable de muestra tal cual es y suministrando su propio formulario HTML.

Louis Mau, Solutions Architect, IBM

Louis Mau forma parte del equipo de desarrollo de InfoSphere MashupHub. Actualmente se ocupa de ayudar a los clientes a construir aplicaciones situacionales con IBM Mashup Center. Antes de este rol, fue el Architect de DB2 Everyplace Sync Server.



Klaus Roder, Solutions Architect, IBM Mashup Center, IBM

Klaus Roder trabaja como arquitecto de soluciones para el IBM Mashup Center en el IBM Silicon Valley Lab. Actualmente se especializa en el desarrollo y el despliegue de mashups empresariales con clientes usando el IBM Mashup Center. Previamente a su posición actual, Klaus trabajó en el proyecto de IBM Web Interface for Content Management (WEBI) y en el equipo de desarrollo del WebSphere Information Integrator Content Edition (IICE). Klaus posee un título en ciencias informáticas de la Universidad de Ciencias Aplicadas de Würzburg y es miembro de San Francisco Bay Area ACM chapter.



18-02-2011

Visión general

La mayoría de los desarrolladores ocasionalmente deben crear una aplicación que realice actualizaciones simples a una tabla de base de datos. A partir de la Versión 2 del IBM Mashup Center, usted puede crear fácilmente un feed relacional (JDBC) que pueda ejecutar una única sentencia SQL INSERT, UPDATE, o DELETE. Este artículo describe cómo desarrollar un widget que lo ayude a utilizar dichos feeds en aplicaciones mashup.

Este artículo supone que usted está familiarizado con la creación de mashups y feeds además de las bases para la escritura de un widget. En particular, usted debería saber cómo programar en JavaScript y tener experiencia con el uso de IBM Mashup Center. La sección Resources contiene enlaces a los siguientes dos elementos que proporcionan buena información introductoria que puede ayudarlo a ponerse al día con algunas de las bases para la creación de mashups: "Creating a feed from an enterprise database (JDBC)" y "Developing widgets for IBM Mashup Center."

Soporte para la base de datos del IBM Mashup Center

El IBM Mashup Center incluye InfoSphere MashupHub y Lotus Mashups. Este proporciona una herramienta innovadora para la generación de feeds relacionales para crear feeds de consumo de la mayoría de los servidores comunes de bases de datos, incluyendo DB2®, Informix®, e IMS™.

Feeds de actualización relacional

Con el IBM Mashup Center, usted puede crear un feed de los datos obtenidos de una consulta relacional. El feed es creado mediante la selección de tablas y columnas en las que está interesado, o usando una sentencia SQL para consultar la base de datos. El feed se crea desde los datos obtenidos del conjunto de resultados de las consultas.

Comenzando con V2 del IBM Mashup Center, además del uso de sentencias SQLSELECT, usted puede además utilizar el generador de feeds relacionales para ejecutar una sentencia SQL INSERT, UPDATE, o DELETE. Usted sólo puede ejecutar una única sentencia SQL, de modo que este dispositivo no puede utilizarse para procesamiento transaccional complejo. Sin embargo, usted puede utilizar la capacidad de actualización para soportar muchos escenarios relativamente simples como los siguientes ejemplos:

  • Toma de una captura de pantalla para realizar análisis de tendencia. Por ejemplo, supongamos que usted tiene un feed del que se obtiene la cantidad total de órdenes nuevas para cada día. Ejecutando y guardando el contenido del feed en una tabla de base de datos, usted puede generar un feed para mostrar la tendencia de entrada de órdenes. Usando el editor de mashups de datos, usted puede crear un mashup de datos con un operador FOREACH para INSERTAR contenido de cada entrada repetida en su propia fila.)
  • Comentarios o notas persistentes. Por ejemplo, usted podría tener una aplicación electoral simple para reunir las preferencias y opiniones de los usuarios.
  • Desarrollo de un formulario para mantener las listas ToDo que son persistentes en una base de datos.
  • Desarrollo de un formulario para enviar solicitudes de servicio. Por ejemplo, podría tratarse de solicitudes de servicio para una creación, una impresora, o un sistema de IT.

A veces, la creación de una página mashup para el simple uso de un feed de actualización relacional no es sencilla. Por ejemplo, usted podría usar el widget de entradas de usuario que recibió junto con IBM Mashup Center para generar controles como cuadros de texto para reunir las entradas del usuario. Sin embargo, el widget de entradas de usuario no puede ejecutar directamente un feed de actualización relacional, y no existe un widget que pueda visualizar los resultados de la ejecución de buena manera.

Este artículo describe cómo crear un widget personalizado que facilite el uso de estos feeds de actualización relacional para el segundo tipo de escenario que aparece en la lista más arriba. El widget personalizado toma un formulario HTML como parámetro de configuración. Este presenta el formulario, envía los datos del formulario a un feed de actualización relacional, y visualiza el estado de la actualización. Dado que este widget personalizado acepta el fragmento de un formulario HTML personalizado, usted tiene más control sobre el diseño del formulario. El uso del fragmento de un formulario HTML facilita además la creación del mismo formulario en múltiples páginas. La siguiente sección lo ayuda a describir el escenario de muestra utilizado para ilustrar las características del widget de formularios HTML.


Escenario de muestra

Para reducir la instalación y facilitar el proceso, el escenario de muestra utiliza la tabla de pólizas que viene con la base de datos de muestra Apache Derby instalada con el IBM Mashup Center. La figura 1 muestra una captura de pantalla de la aplicación mashup de muestra que este artículo describe cómo crear. La aplicación es bastante simple y consiste de dos widgets.

Figura 1. Página Mashup de muestra
Se muestra tabla en la izquierda con id de póliza, nombre de cliente, y columnas de superficie; a la derecha, el formulario de actualización y el borrado del domicilio de la póliza

Como se observa en la Figura 1, el widget DataViewer ubicado a la izquierda se utiliza para visualizar una lista de pólizas con interés recuperada de la base de datos. Si una fila (póliza) es seleccionada, se visualiza información detallada sobre la póliza en el widget del formulario HTML ubicado a la derecha. Los usuarios pueden cambiar el domicilio y presionar el botón submit en el widget del formulario HTML. El botón es configurado para ejecutar un feed de actualización relacional. El resultado de la ejecución es un documento XML. El documento XML es analizado sintácticamente y se visualiza un formulario sencillo de éxito o de error. La Figura 2 muestra el mensaje de éxito.

Si usted desea acceder al widget de muestra inmediatamente y utilizarlo con su propio formulario, tome el widget de muestra de la sección Download y agréguelo a su IBM Mashup Center. Luego usted puede saltear la descripción sobre cómo crear el widget y pasar directamente a la sección Integrando todo.

Figura 2. Mensaje de ejecución exitosa
Mensaje de ejecución exitosa

Antes de crear el widget que soportaría la funcionalidad mencionada anteriormente, usted necesita ocuparse de una cosa más: la definición de los feeds relacionales. La siguiente sección describe cómo hacerlo.


Creación de los feeds JDBC

Como mencionamos anteriormente, para facilitar la comprensión, el escenario de muestra descripto en este artículo utiliza la tabla de la póliza que viene con la base de datos de muestra del IBM Mashup Center.

Siga estos pasos para crear feeds relacionales para la tabla de la póliza:

  1. Diríjase a la página principal del catálogo y haga clic en Create.
  2. Seleccione New Feed.
  3. Seleccione Enterprise Database (JDBC) como la fuente de datos del feed.
  4. Para llegar a la base de datos que contiene la tabla de la póliza, seleccione Mashup Hub Sample Database en el campo Connection Profile.

    Si el perfil no existe todavía, créelo suministrando la siguiente información:

    • Nombre del perfil de la conexión: MashupHub Sample Database
    • Tipo de base de datos: Derby Embedded
    • Tipo de conexión: Driver Manager (Non-managed Connection)
    • Nombre de la base de datos: <installDir>/Hub/installedApps/Mashup Hub.ear/mashuphub-enterprise.war/hubsample
  5. Utilice las siguientes sentencias SQL para crear dos feeds que correspondan a los dos widgets que se observan en la Figura 1:
    • El primer feed es para el widget DataViewer que muestra la lista de pólizas. Tenga en cuenta que la incorporación del parámetro state le permite filtrar las pólizas para un estado determinado.
      select * from samples.policyholders where state = ':state'
    • El segundo feed feed es para el feed de actualización relacional utilizado por el widget de formulario HTML.
      update samples.policyholders set address = ':address', city = ':city', 
      state = ':state' where policyid = ':policyid'

    El artículo supone que usted está ya familiarizado con el uso del IBM Mashup Center para la creación de feeds relacionales. Dado que estas dos consultas utilizan parámetros, usted debe crearlos pegando las sentencias SQL en la Advanced box del editor de feeds JDBC. La sección Resources contiene enlaces que proporcionan detalles sobre la creación de feeds relacionales.

Antes de proseguir, esta es una buena oportunidad para revisar algunas áreas que a veces requieren atención adicional al utilizar feeds de actualización relacional:

  • Uso de HTTP GET.

    Como se explicó en el artículo W3C que aparece en la sección Resources, usted debería usar HTTP POST cuando "la interacción cambia el estado del recurso de modo que el usuario perciba (por ejemplo, una suscripción a un servicio)." Una razón para esto es que las URLs HTTP GET pueden agregarse fácilmente a favoritos y almacenarse en la memoria caché, lo cual puede ocasionar una invocación accidental e indeseada. El widget del formulario HTML que usted desarrolla usando este artículo utiliza HTTP POST como método de acceso. Por omisión, el IBM Mashup Center permite el soporte de GET y POST. Usted puede desabilitar el acceso a HTTP GET expandiendo el botón Access Method en la página de detalles del feed y deseleccionando la casilla de verificación GET .

  • Evite duplicar filas.

    Los feeds de actualización relacional están compuestos de una única sentencia SQL. Dado que no existe un error de logica, usted debe depender de las restricciones de la base de datos para asegurar la integridad semántica de los datos. Por ejemplo, para asegurar que no haya filas duplicadas, una de las columnas debería declararse como columna KEY de modo que cualquier inserción de fila usando una key previamente insertada fallaría.

  • Almacenamiento en la memoria caché.

    En la mayoría de los casos, los feeds que realizan actualizaciones no deberían guardarse en la memoria caché. Una excepción a esto ocurre cuando el feed de actualización es utilizado en un mashup de datos. Durante la edición, sin almacenar en la memoria caché, el feed de la actualización es ejecutado cada vez que se previsualizan los resultados. Por omisión, el operador de origen almacena en la memoria caché el feed de entrada durante una hora. Esto es exactamente lo que se necesita durante la construcción del mashup. Justo antes de guardar el mashup completo, usted debería desactivar el almacenaje en la memoria caché en todos los operadores deorigen que utilizan feeds de actualización relacional.

Después de terminar con estas preparaciones, usted está listo para crear el widget de formulario HTML personalizado.


Desarrollo de widgets

Los widgets del Mashup Center siguen la especificación iWidget. Hay dos tipos de widgets. La diferencia principal entre ellos es el método de desarrollo.

  • Widgets basados en archivos WAR — estos widgets pueden contener componentes basados en servidores y deben desplegarse en un servidor de la aplicación.
  • Widgets livianos — estos widgets se ejecutan completamente en el lado del cliente y no necesitan ser desplegados en un servidor de la aplicación. El widget de formulario HTML de muestra descripto en este artículo es un widget liviano.

Siga estos pasos para comenzar a desarrollar el widget de formulario HTML de muestra usando IBM Mashup Center Version 2:

  1. Como se observa en la Figura 3, haga clic en Go to View en el borde superior derecho de la página de Mashup Builder y seleccione Create a New Widget....
    Figura 3. Creación del menú del widget
    Captura de pantalla de la página de Mashup Builder con la opción Create a New Widget resaltada
  2. Como se observa en la Figura 4, desde el cuadro de diálogo de Widget Builder, seleccione Work with the widget editor.
    Figura 4. Cuadro de diálogo de Widget Builder
    La captura de pantalla muestra las opciones para crear un widget desde un asistente, o trabajar con el editor del widget
  3. En el siguiente cuadro de diálogo seleccione Create a new project.
  4. En cuadro de diálogo New Widget Project, seleccione Create a project from starter files. Esto crea un nuevo proyecto con una definición y un archivo catálogo de widget estructurales. Todos los archivos son conservados por el servidor. Como se observa en la Figura 5, el cuadro de diálogo Customized Widget Project muestra los nombres de los archivos bajo el encabezado "Select a file". Usando los botones que se encuentran debajo de la lista, usted puede seleccionar cualquier archivo existente para editar o puede cargar archivos adicionales en su proyecto.
    Figura 5. Cuadro de diálogo Customized Widget Project
    Captura de pantalla que muestra la lista de archivos que se pueden seleccionar
  5. Cuando esté listo para realizar la prueba, haga clic en Export y seleccione Add to palette.

El proyecto de muestra para este artículo es bastante simple y contiene solamente dos archivos.


Archivo de definición del widget

No es necesario modificar el archivo catalog.xml generado. Este simplemente proporciona el nombre del widget como aparece en el menú de la caja de herramientas y la ubicación del archivo de definición del widget (iWidget.xml). El archivo iWidget.xml especifica el archivo JavaScript que implementa la lógica, los eventos estáticos enviados o recibidos por el widget, el esquema en vista modo, y el esquema en modo edición. Esta sección lo guía a través de las modificaciones que debe realizar a iWidget.xml para cubrir cada una de estas áreas.

En el Listado 1 se muestra el elemento raíz del archivo iWidget.xml. El atributo iScope en el elemento raíz iwidget es el más importante. Este especifica el objeto JavaScript que implementa las funciones de rellamada iWidget. El archivo que contiene el JavaScript se carga utilizando el elemento del recurso. Si desea ver los detalles sobre estos y otros atributos, consulte el enlace sobre la programación del widget y la documentación del API en la sección Resources .

Listado 1. Encabezado de iWidget.xml
<iw:iwidget name="htmlForm"
            xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
            iScope="sample.mashupcenter.htmlForm"
	    allowInstanceContent="true" supportedModes="view edit"
            mode="view" lang="en">

<iw:resource uri="htmlForm.js"/>

En el Listado 2 se muestran las definiciones para el evento de recepción y los dos eventos de envío predefinidos del widget. El evento de recepción es indicado por la presencia de atributos handled y onEvent . El valor del atributo onEvent es el nombre de la función para realizar la llamada cuando el evento es recibido. El valor del atributo published define el nombre del evento publicado. La sección Event handling and generation más adelante en este artículo describe se administran estos eventos.

Listado 2. Especificación del evento de iWidget.xml
<iw:event id="ResetForm" handled="true" onEvent="handleReset"
          eventDescName="desc_handleReset"/>
<iw:eventDescription id="desc_handleReset" payloadType="any" title="Clear all Fields"
                        description="Clear all the fields in the form" lang="en">
</iw:eventDescription>

<iw:event id="actionSuccessful" eventDescName="desc_actionSuccessful" published="true"/>
<iw:eventDescription id="desc_actionSuccessful" payloadType="text"
                        description="Number of records updated by WebService" lang="en">
</iw:eventDescription>

<iw:event id="actionFailed" eventDescName="desc_actionFailed" published="true" />
<iw:eventDescription id="desc_actionFailed" payloadType="text"
                        description="Failure to assign" lang="en">
</iw:eventDescription>

Finalmente, el archivo de definición del widget especifica además el esquema del widget para los modos vista y edición. El esquema es especificado por la marcación HTML incluida como CDATA en el elemento iw:content . El Listado 3 muestra la marcación HTML para el modo vista. Tenga en cuenta que todos los elementos div poseen una id de modo que usted puede administrarlos con JavaScript. Tenga en cuenta también que los valores de cada id usan _IWID_ como prefijo. Durante la ejecución, el IBM Mashup Center reemplaza todos los prefijos _IWID_ con la id única actual de la instancia del widget durante la creación del widget. Esto asegura que todas las ids sean únicas aunque haya múltiples instancias del widget en la misma página HTML. Hay dos elementos div en la definición del modo vista. La div con la id de _IWID_formdiv contendrá un fragmento de formulario HTML e inicialmente estará en blanco. La otra div contiene una especificación style de display:none, lo cual significa que no es se encuentra a la vista. Esta contiene una plantilla para desplegar el resultado del envío del formulario y puede visualizarse con JavaScript tras la ejecución de uno de los feeds de actualización.

Listado 3. Esquema del modo vista de iWidget.xml
<iw:content mode="view">
  <![CDATA[
  <div id='_IWID_formdiv'></div>

  <div id='_IWID_resultdiv' style='display:none; font-size:1.3em;'>
      <div id="_IWID_ResultXML" ></div>
      <br />
      <a href=""
         onclick="javascript:iContext.iScope().showFormAndHideResult();return false;">
         Back</a>
  </div>

  ]]>
</iw:content>

La sección modo edición contiene el código para un formulario con un área de texto y tres cuadros de texto. Esto se despliega cuando el usuario hace clic en Edit Settings. El área de texto es utilizada para ingresar el fragmento del formulario HTML. En los tres cuadros de texto se puede ingresar hasta tres URLs. Una sección posterior describe cómo asociar estas URLs con los botones del formulario. Los valores de la URL deberían ser los mismos que los que se ingresarían al atributo método del formulario. Osea, la URL sin los pares de valores de nombre que siguen el caracter ?.

El cuadro de diálogo de edición del formulario html muestra una captura de pantalla del formulario presentado. Para abreviar, este artículo no reproduce todo el esquema HTML del modo edición. Este puede obtenerse con el paquete completo del widget que usted puede descargar del enlace correspondiente en la sección Resources .


Implementación de JavaScript

El archivo de implementación de JavaScript se denomina htmlForm.js. Se trata de una clase de Dojo que administra eventos estándar como load, unload, view, edit, y cualquier otro evento personalizado y comunicación del servidor. A continuación hallará una rápida visión general de las funciones incluidas en el archivo:

  • onLoad— Esta es la función en la cual usted coloca el código de inicialización. Normalmente esta abarcaría la recuperación de la información de configuración guardada en la invocación anterior del cuadro de diálogo Edit Settings.

    Recuerde que todos los atributos de id en la marcación HTML para visualizar y editar modos contienen el prefijo _IWID_ que se reemplaza por la id de la instancia actual del widget cuando se crea el widget. Esto significa que antes el código JavaScript puede recuperar un elemento HTML identificado por su id, la id del widget de la instancia desde el objeto iContext debe ser utilizado para construir la id actual. Tenga en cuenta cómo en el Listado 4 los datos de configuración del widget son recuperados desde el objeto attributes del widget relacionado con iContext.

    Listado 4. Función onLoad
    onLoad: function() {
    
            this.uid = "_" + this.iContext.widgetId + "_";
    
            this.formDivNode   = dojo.byId(this.uid + 'formdiv');
            this.resultNode = dojo.byId(this.uid + 'resultdiv');
    
            // load attributes
            var attributes = this.iContext.getiWidgetAttributes();
            this.formHtml  = attributes.getItemValue( "formHtml" );
            ::::::::::::::::::::::::
    },
  • onUnload— Esta función se llama justo antes de que la página sea desconectada. Normalmente, no es necesario realizar una limpieza, lo cual significaría que usted no necesita implementar esta función. Sin embargo, dado que las id de Dojo V1.3 Dijit deben ser únicas y no son automáticamente borradas durante la limpieza al cambiar de página, usted debe borrarlas manualmente.
    Listado 5. FunciónonUnload
    onUnload: function()
    {
        // need to clear all existing dijits (to free up id's)
        if ( this.formDijit != null )
            this.formDijit.destroyRecursive( false );
    },
  • onview— Esta función es llamada cada vez que el widget se visualiza. El widget de muestra solamente presenta un mensaje por omisión si el widget no ha sido configurado (por ejemplo, cuando se lo arrastra por primera vez a la página). Las otras funciones son explicadas en detalle en las secciones siguientes.
    Listado 6. Función onview
    onview: function()
    {
        if ( this.formHtml == null  ||  this.formHtml.length <= 0 ) {
            this.formDivNode.innerHTML = "Switch To Edit to specify HTML form";
        } else if ( this.viewContent.length <= 0 ) {
            this.displayForm();
            this.reCreateEvents( );
        }  // else form already there, no need to do anything
    },
  • onedit— Esta función es llamada al hacer clic en Edit Settings . El código en el Listado 7 simplemente preintroduce en el cuadro de diálogo Edit Settings valores suministrados por el usuario desde cualquier invocación previa.
    Listado 7. Función onedit
    onedit: function()
    {
        dojo.byId( this.uid + "formHtml" ).value = this.formHtml;
        :::::::::::::::::::::::::::::::::::
    },
  • saveConfigData— Esta función no corresponde a ningún evento integrado. Se trata de una función de determinados widgets especificada en el método onclick del botón Save de la marcación HTML del modo edición. El código en el Listado 8 simplemente recupera y guarda los valores más recientes suministrados por el último usuario desde el cuadro de diálogo Edit Settings. El evento onModeChanged es utilizado para informar el tiempo de ejecución del widget para descartar el cuadro de diálogo Edit Settings.
    Listado 8. FunciónsaveConfigData
    saveConfigData: function()
    {
        this.formHtml = dojo.byId( this.uid + "formHtml" ).value;
        ::::::::::::::::::::::::::::::::::::::::::::::::::
    
        this.iContext.iEvents.fireEvent("onModeChanged", null, "{newMode:'view'}");
    
        var attributes = this.iContext.getiWidgetAttributes();
        attributes.setItemValue("formHtml"  ,  this.formHtml );
        ::::::::::::::::::::::::::::::::::::::::::::::::::
        attributes.save();
    },

La sección Resources contiene un enlace que usted puede utilizar para descargar el paquete completo del widget. Ahora que está familiarizado con las funciones comunes para todos los widgets, la próxima sección le presentará las funciones específicas del widget de muestra.


Visualización del formulario HTML

Para utilizar el widget, usted debe suministrar un formulario HTML. Usted puede crear el formulario usando cualquier editor o herramienta para generar los códigos que desee. Después de crear el formulario HTML, asegúrese de que contenga el atributo dojotype correspondiente para cada uno de los campos de entrada del formulario. (Si desea ver un ejemplo consulte el listado HTML de muestra en la sección Integrando todo .) Su formulario puede tener múltiples botones. Para que un botón esté activo, éste debe tener un atributo onclick con un valor similar al siguiente:

            onclick="_${widgetId}_iContext.iScope().submit('formUrl1');"

La siguiente es la sintaxis para llamar la función submit definida en el archivo JavaScript del widget. La sección Cómo enviar el formulario describe los detalles de cómo la función submit es administrada. Por ahora, sólo reemplace la subcadena ${widgetId} en el ejemplo que presentamos más arriba con la id actual para su widget de modo que el JavaScript sea válido. A continuación le explicaremos cómo realizar esto.

Para visualizar el fragmento del formulario HTML pegado en el cuadro de diálogo Edit Settings, simplemente asigne la cadena HTML al innerHTML del marcador de posición delesquema del modo vista de iWidget.xml div como se observa en el Listado 9. Pero antes de hacer esto, debe reemplazar la cadena ${widgetId} con la id actual del widget. Haga esto llamando a la función utilitaria de cadena Dojo substituir. Esto también puede observarse en el Listado 9. Lo último a tener en cuenta sobre el código en el Listado 9 es que dado que el formulario contiene Dojo Dijits, usted debe llamar al método analizar sintácticamente de Dojo para que el comportamiento en el Dojo surja efecto.

Listado 9. Función displayForm
displayForm: function()
{
    // fix up button onclick action to point to submit method of this widget.
    this.viewContent = dojo.string.substitute( this.formHtml
                                             , { widgetId: this.iContext.widgetId });
"
    // Add form content to the view content root node.
    if ( this.formDijit != null )  // need to clear all existing dijits (to free up id's)
        this.formDijit.destroyRecursive( false );
    this.formDivNode.innerHTML = this.viewContent;

    // Parse dojo components to display Dojo widgets
    dojo.parser.parse( this.formDivNode );
    this.formDijit = this.getFormDijit(  this.formDivNode );
},

Administración y generación de eventos

Una característica clave del widget de formulario HTML de muestra es que usted puede enviar datos al widget. Como se describe en la sección Escenario de muestra , al hacer clic en una fila del widget DataViewer se provoca que las columnas de la fila pasen a los campos de entrada del formulario del widget. Dado que los campos de entrada del formulario pueden variar de un formulario al otro, usted no puede definir los eventos de recepción para los campos del formulario de entrada estadísticamente en el archivo iWidget.xml como lo hizo con el evento de recepción y los dos eventos de envío predefinidos en la especificación del evento de iWidget.xml.

Para crear los eventos de manera dinámica para cada uno de los campos de entrada del formulario, usted primero debe analizar sintácticamente el HTML proporcionado para todos los campos de entrada del formulario, como se observa en el Listado 10.

Listado 10. FuncióncreateEventsForFields
createEventsForFields : function(  )
{   
    this.eventNames = [];
    this.dijitMap   = {};

    var children = this.formDijit.getChildren();
    for (var i = 0  ;  i < children.length  ;  i++ ) {
        var widget = children[i];
        var name  = widget.attr( 'name' );
        if ( name == null ||  name.length == 0 )
            continue;  // skip over unnamed form input fields
        if ( widget.type == 'radio'  &&  widget.checked == false )
            continue;   // for radio button, pick the one that is true

Después de identificar un campo de entrada del formulario, cree un evento para el mismo con el mismo nombre, como se observa en el Listado 11.

Listado 11. Creación dinámica de eventos
this.eventNames.push( name );
this._createEvent({
    name : name,
    type: "any",
    isHandled : true,
    handlingFn : dojo.hitch(this, this.handleEvent )
});

Al final del for loop, agregue cada evento a un dijitMap, como se observa en el Listado 12. Utilizará este mapa más tarde para disparar el evento correspondiente al llamar un evento.

Listado 12. dijitMap para almacenar nombres de eventos
// will also create dijit mapping to process event
this.dijitMap[ name ] = widget;

Luego, debe colocar en su lugar el código para administrar estos eventos cuando son disparados. Cuando uno de los eventos específicos presentados más arriba es enviado al widget, el nombre del evento es utilizado para encontrar (con la ayuda del código del dijitMap) el campo de entrada de formulario correspondiente. Si el campo de entrada de formulario no es nulo, establezca la carga útil que recibe como valor de widget, como se muestra en el Listado 14

Listado 14. FunciónhandleEvent
handleEvent: function(iEvent){
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    var  evtname    = iEvent.name;
    var  widget     = this.dijitMap[ evtname ];
    if ( widget != null )
        widget.setValue( iEvent.payload ); 
}

Cómo enviar el formulario

Como mencionamos en la sección Visualización del formulario HTML, los botones en el fragmento del formulario HTML deben incluir una llamada explícita a la función submit . El argumento a la función submit define qué feed URL definido en el cuadro de diálogo Edit del formulario html es ejecutado cuando se presiona el botón. Como se observa en el Listado 15, el argumento debe ser una de las siguientes cadenas:

  • formUrl1— Ejecute la URL del feed definida por el primer método del formulario.
  • formUrl2— Ejecute la URL del feed definida por el segundo método del formulario.
  • formUrl3— Ejecute la URL del feed definida por el tercer método del formulario.
Listado 15. Funciónsubmit
submit: function( action ) {
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    var actionURL = "";
    //Specify the root URL of the feed that you want to trigger:
    if ( action == 'formUrl1' ) {
        if (  this.formUrl1  &&  this.formUrl1.length > 0 )
            actionURL = this.formUrl1;
    } else if ( action == 'formUrl2' ) {
        if (  this.formUrl2  &&  this.formUrl2.length > 0 )
            actionURL = this.formUrl2;
    } else if ( action == 'formUrl3' ) {
        if (  this.formUrl3  &&  this.formUrl3.length > 0 )
            actionURL = this.formUrl3; 
    ::::::::::::::::::::::::::::::::::::::::::::::::::

Ahora que tiene la URL de base correcta para la acción seleccionada, debe reunir los valores de formulario ingresados por los usuarios. Esto se realiza con la función collectNVP . Como se observa en el Listado 16, todo el trabajo tedioso para recuperar valores desde los diferentes tipos de campo de formulario de entrada es administrado por la función getValues del formulario de biblioteca Dijit de Dojo. Su código sólo debe enlazar los campos y codificar los valores para asegurarse de que no haya caracteres inválidos.

Listado 16. FuncióncollectNVP
collectNVP: function(  ) {
    this.debugTrace( "collectNVP entered" );

    var formData = "";
    var temp = this.formDijit.getValues();
    for ( var  name in temp ) {
        if ( formData.length > 1 )  formData += '&';
        //Encode the key and value, to make sure there are no invalid characters.
        formData +=  encodeURI( name );
        formData +=  "=";
        // encodeURI( value );   doesn't escape &, ...
        var value =  temp[ name ];
        formData +=  escape( value );
    }
    return formData;
}

Después de haber reunido los datos del formulario y la URL de base, usted envía la llamada AJAX usando el método xhrPost de la biblioteca de Dojo. En cuanto al consejo en la sección Creación de feeds JDBC use HTTP Post como el método de acceso en lugar de HTTP GET para ejecutar el feed de actualización relacional.

Como se muestra en el Listado 17, los argumentos para el método xhrPost incluyen funciones de rellamada para los casos de carga (éxito) y error. En las siguientes dos secciones se describen los detalles de estas funciones de rellamada. El argumento urlToLoad, el cual contiene la URL de base o el método de formulario, no se utiliza directamente. Esto es así porque la regla de sandbox del navegador requiere que la URL de base suministrada por el usuario sea redirigida a través del proxy AJAX del Mashup Server. Esto se logra llamando a la función reWriteURI a la que se puede acceder desde iContext.

Listado 17. Envío del formulario
// Using POST for update type URL
submitUrl: function(urlToLoad, formdata )
    var location = this.iContext.io.rewriteURI( urlToLoad );
    dojo.xhrPost({
        url     : location,
        postData: formdata,
        load    :  dojo.hitch( this, this.handleFeedContent ),
        error   :  dojo.hitch( this, this.handleErrorResponse ),
        handleAs: "xml",
        sync    : true
    });
}

Como enviar exitosamente los datos del formulario

Como se especificó en la llamada AJAX xhrPost, la función handleFeedConent es llamada cuando el formulario es enviado con éxito. A este widget se le indica trabajar sólo con el feed de actualización relacional (JDBC) del MashupCenter. El feed devuelve la respuesta XML que se observa en la Figura 6. Si se obtiene una respuesta diferente, el programa muestra un mensaje indicando que se ha obtenido un "formato de resultado no soportado".

Figura 6. Respuesta de feed de actualización exitosa
segmento xml con elemento xecutionreslut top con elemento rowcount y value of 1 y elemento empty systemmsg

Como se observa en el Listado 18, si se obtiene el formato correcto, la función handleFeedConent muestra el mensaje "Operation successful" y la cantidad de filas que fueron insertadas con éxito. La función también dispara el evento actionSuccessful,el cual es definido estadísticamente en el archivo iWidget.xml descripto anteriormente en la sección Archivo de definición de widget .

Listado 18. Envío exitoso de formulario
handleFeedContent: function(data){
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    resultHTML += "Operation successful.";
    resultHTML += rowCount;
    resultHTML += " record(s) changed.";

    this.iContext.iEvents.fireEvent("actionSuccessful", null, "" );
    ::::::::::::::::::::::::::::::::::::::::::::::::::

Como se observa en el Lsitado 19, si la llamada del plug in (JDBC) relacional del MashupCenter devuelve un error (-1), la función handleFeedConent genera una cadena de resultado con el mensaje devuelto en el elemento systemmsg . Esta también dispara el evento actionFailed que es definido en la especificación de evento iWidget.xml .

Listado 19. Mensaje de error obtenido tras el envío exitoso del formulario
handleFeedContent: function(data){
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    if (  rowCount ==  "-1" ) {

       var  msg     = "Unknown error. <br><br>";
       var  msgList = dojo.query( "systemmsg" , data );
       if ( msgList  &&  msgList[0] )
            msg = dojox.xml.parser.textContent( msgList[0] );
       resultHTML += msg;

       this.iContext.iEvents.fireEvent("actionFailed", null, rowCount );

Administración de errones durante el envío de los datos del formulario

Como se observa en el Listado 20, si el envío de los datos del formulario falla, la función handleErrorResponse muestra los resultados obtenidos del error de comunicación llamando displayResult.

Listado 20. FunciónhandleErrorResponse
handleErrorResponse: function(data)
{
    this.debugTrace( "handleErrorResponse entered data="  + data );
    this.displayResult( data );
}

Visualización de los resultados del envío del formulario

En ambos casos, ya sea que el envío del formulario fue exitoso o tuvo errores, la función displayResult es utilizada para recordar el tamaño del formulario, ocultar el formulario de entrada actual, y mostrar los resultados del evío del formulario.

La definición deestilo para el nodo resultante es inicialmente definida en el diseño de modo vista de iWidget.xml como display:none, el cual provoca que se oculte. Como se observa en el Listado 21, la función displayResult hace que el nodo resultante sea visible cambiando su definición style.display por block.

Listado 21. FuncióndisplayResult
displayResult: function(data)
{
    // save the current size
    var  formSize = dojo.contentBox( this.formDivNode );
    // hide the form
    this.formDivNode.style.display = "none";

    // show the result
    this.resultNode.style.display = "block";
    dojo.contentBox( this.resultNode, formSize );
    var resultXmlNode = dojo.byId(this.uid + 'ResultXML');
    resultXmlNode.innerHTML = data;
},

El resultdiv incluye un enlace recibido que llama a la funciónshowFromAndHideResult . Como se observa en el Listado 22, esta función oculta el resultdiv y vuelve a mostrar el formulario.

Listado 22. FunciónshowFormAndHideResult
//Clear data, oculta el nodo resultante y muestra el formulario de nuevo.
showFormAndHideResult: function()
{
    this.debugTrace( "handleFeedContent entered" );

    this.formDivNode.style.display = "block";

    // clear any message text
    var resultXmlNode = dojo.byId(this.uid + 'ResultXML');
    resultXmlNode.innerHTML = "";
    this.resultNode.style.display = "none";
},

Integrando todo

Usted ya está preparado para incorporar su widget de formulario HTML en la aplicación mashup de muestra descripta en la sección Escenario de muestra . Comience con el fragmento de formulario HTML para el registro de la póliza. Como se observa en el Listado 23, use una tabla HTML para organizar los cuadros de texto. Como se describió anteriormente, el formulario debe usar Dojo Dijits. Al igual que en una página HTML común, los campos de entrada del formulario deben contener nombres que coincidan con el nombre de los parámetros utilizados en el feed de actualización relacional. Usted creó el feed anteriormente en la sección Creación de feeds JDBC . El formulario puede tener múltiples botones correspondientes a cualquier combinación de acciones INSERT, UPDATE, o DELETE . Para ilustrar la posibilidad de una mayor extensión, el formulario contiene un botón adicional no funcional etiquetado como Delete Policy que no tiene un feed correspondiente.

Listado 23. Formulario de póliza HTML
<form dojotype="dijit.form.Form" style="font-size:1.3em;">

  <div style='background-color:#D1EACC; height:4em; padding-top:5px; padding-bottom:5px'>
      <center><h3>Policy Address Update and Delete Form</h3></center>
  </div>

  <br>
  <table>

  <tr><td>Policy Id:</td>
      <td><input type="text"  name="policyid"  dojotype="dijit.form.TextBox"
                 style="width: 6em;" readonly /></td>
      <td></td>
      <td></td>
  </tr>

           :::::::::::::::::::::::::::::::::::::::::

  <tr>
  <td></td>
  <td colspan='4' align='right'>
      <button dojotype="dijit.form.Button" value="formUrl1">Update Address
              onclick="_${widgetId}_iContext.iScope().submit('formUrl1');"
      </button>
      <button dojotype="dijit.form.Button" value="formUrl2">Delete policy</button>
  </td>
  </tr>
  </table>
</form>

Ahora, como se puede observar en la Figura 7, diríjase al cuadro de diálogo de edición del formulario html y pegue el fragmento de formulario HTML en el campo del formulario Html, y pegue los feeds relacionales que ha creado en la secciónCreación de feeds JDBC en los campos de método del formulario correspondientes. Haga clic en Save para completar la configuración del widget.

Figura 7. Cuadro de diálogo de edición del formulario html
Captura de pantalla del cuadro de diálogo edición del formulario html con área de texto y cuadros de texto de fragmentos HTML para feeds relacionales

Todos los campos de entrada son completados cuando una fila del widget DataViewer es seleccionada. Como hemos explicado en la sección Administración y generación de eventos, el widget de formulario HTML dinámicamente crea eventos de recepción para cada uno de los campos de entrada del formulario. Lo único que usted debe hacer es conectarlos a los eventos de envío de DataViewer. La Figura 8 muestra la conexión de uno de los eventos de recepción generados al evento correspondiente del widget DataViewer.

Figura 8. Conexión de eventos de recepción
Captura de pantalla de cuadro de diálogo de conexión que enlaza el formulario html a resetear formulario

Finalmente, usted debe conectar el evento actionSuccessful desde el widget de formulario HTML a un widget personalizador de URL. Este último es conectado al widget DataViewer y configurado para usar la misma URL que la utilizada para DataViewer. La Figura 9 muestra el personalizador de URL y el gráfico de conexión.

Figura 9. Personalizador de URL y gráfico de conexión
Captura de pantalla de la interfaz del gráfico de conexión con el formulario html conectado al personalizador de URL conectado a Data Viewer

Después de una operación de actualización exitosa, el evento es disparado y DataViewer es actualizado automáticamente. Esto sirve sólo a modo de ilustración del caso de muestra, porque la operación de actualización de muestra no modifica lo que se visualiza en DataViewer.

Figura 10. Conexión de eventos de envío
Captura de pantalla del cuadro de diálogo de la conexión que muestra el evento de envío conectado al widget para recibir contenido

Conclusión

Este artículo le ha presentado los pasos básicos para la creación de un widget, incluyendo el registro de eventos dinámicos y la comunicación con el servidor. Para probar y ampliar lo aprendido en este artículo usted puede mejorar el widget administrando los errores de forma más elaborada para los feeds de actualización relacional.

Las aplicaciones Mashup son a menudo dashboards que muestran información desde fuentes dispares. Al usar feeds de actualización relacionales junto con este widget, usted puede crear rápidamente aplicaciones mashup que no sólo proporcionen informes sino también un medio para realizar acciones de actualización simples.


Descargar

DescripciónNombretamaño
Sample code for this articleHTMLformWidget.zip8KB

Recursos

Aprender

Obtener los productos y tecnologías

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Information mgmt, Lotus
ArticleID=627794
ArticleTitle=Mashups, más allá de la generación de informes
publish-date=02182011