TOBAGO

RECU-0136 (Recurso Referencia)

Descripción

Tobago es mucho más que una librería de etiquetas. Las siguientes afirmaciones caracterizan a Tobago y lo hacen diferente de otros frameworks.

  • La finalidad de Tobago es crear aplicaciones de negocio sin la necesidad de un diseño HTML. El desarrollo de páginas con Tobago se parece más al diseño de interfaces de usuarios convencionales que al diseño de páginas webs.
  • Los componentes de la Interfaz de Usuario son abstracciones del HTML y cualquier diseño de información que haga, no pertenece a la estructura general de la página. El formato final de salida es determinado por el cliente.
  • Un mecanismo basado en temas, hace fácil cambiar la apariencia y permite proveer implementaciones especiales para ciertos navegadores. Una solución basada en la readaptación ante fallos nos asegura la reusabilidad de gran parte del código para nuevos temas.
  • Se usa un gestor de diseño para organizar los componentes de manera automática. Esto quiere decir, que no hace falta un diseño manual con HTML para tablas u otros componentes.

Modo de empleo

Una aplicación con Tobago, es una aplicación web estándar y necesita un descriptor (WEB-INF/web.xml). Como aplicación JSF, el archivo web.xml tiene que incluir una definición para el servlet FacesServlet y el correspondiente mapeo. Es conveniente que durante el desarrollo, los recursos que van a ser usados, como imágenes, scripts y hojas de estilos estén fuera del jar del tema. Para lograr esto, el archivo web.xml debe contener la definición de ResourceServlet y el correspondiente mapeo.

Una página con Tobago, tiene el siguiente aspecto:

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
<%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<f:view>
  <tc:page>
    <f:facet name="layout">
      <tc:gridLayout/>
    </f:facet>
    <tc:out value="Hola Mundo"/>
  </tc:page>
</f:view>

Características

A continuación se resumen las características principales de Tobago

Layout

Tobago organiza la colocación de los componentes con la ayuda de los administradores de Layout. El controlador de distribución principal se llama diseño de cuadrícula. Se divide el espacio rectangular disponible en las células de la red. La rejilla es generada por la columna y los valores de fila de la etiqueta <tc:gridLayout>. La sintaxis de estos valores se basa en la multilongitud de la notación que se hace en HTML.

Para añadir un controlador de distribución a un contenedor como la caja, el panel o la página que tiene que agregar una faceta de diseño (es decir, una faceta con el nombre de 'diseño') a la etiqueta de contenedores respectivos.

<tc:panel> 
   <f:facet name="layout">
     <tc:gridLayout columns="*" rows="fixed;fixed;*"/>
   </ f: facet>
   <tx:in Name"/> label="Nombre"
   <tx:in Name"/> label="Last
   <tc:cell />
</ tc: Panel>

En este ejemplo ponemos a dos controles de entrada con etiquetas en dos filas consecutivas. Por debajo de los dos campos de entrada se añade un elemento separador. El diseño token Layout 'fixed' asesora al administrador de layout para dar el control de entrada de la altura, que este tipo de control que normalmente posee en el tema seleccionado.

Los valores de la columna y fila de los atributos de la etiqueta <tc:gridLayout> puede contener una lista separada por punto y coma de las fichas de diseño. Un diseño puede ser una razón longitud exacta en píxeles como 200px, con una longitud como porcentaje del 25%, con una longitud relativa como 2 , o una longitud específica llamada fijos, que la duración exacta es determinada por el tema y asegurarse de que el control es útil. Un único control de entrada de línea, por ejemplo, tiene que ser tan alto que los caracteres de la fuente asignada se pueden leer dentro del control.

La longitud relativa se determina pasado por el controlador de distribución. El espacio que queda disponible se distribuye entre las longitudes existentes relativas. Cada longitud recibe espacio proporcional al número entero antes de que el ''. Un solo '' es una abreviatura de «1 * '. El gestor de diseño se encarga del atributo prestados de los controles, también. Si el atributo actúa dinámicamente definido por un valor vinculante, la página puede contener menos controles en algunos casos que en otros. El controlador de distribución se puede distribuir el espacio disponible entre la nueva relación y la duración restante porcentaje.

Marcado

Puesto que no tenemos control directo sobre el diseño sin tener que escribir su propio tema, Tobago apoya el concepto de marcado. Puede asignar determinados valores de marcado lógico a un control para ajustar la representación. Un tema que especifica el marcado de cada control. El tema norma ya establece algunos márgenes de utilidad.

...
<tc:label value="Normal"/>
<tc:out value="999.99"/>

<tc:label value="Number"/>
<tc:out markup="number" value="999.99"/>

<tc:label value="Emphasized"/>
<tc:out markup="strong" value="999.99"/>

<tc:label value="Emphasized Number"/>
<tc:out markup="number,strong" value="999.99"/>
...

Renderizado parcial

Para evitar la recarga de pantalla completa Tobago establece la representación parcial, que asesora al cliente para actualizar sólo partes de la pantalla para optimizar la cantidad de datos enviados al cliente y el tiempo para hacer las actualizaciones necesarias. Algunos controles como el control de ficha y la hoja de apoyo soportan la representación parcial. Considerando que los controles de contenedores, como el panel de genéricos permite al grupo de los controles arbitrarios para ser capaz de actualizar exclusivamente como un grupo.

Formularios Virtuales

La etiqueta de página establece una forma implícita en todos los controles en la pantalla. La etiqueta form permite dividir estos controles en pequeños grupos para ser capaces de gestionar la validación sólo para estos controles agrupados. Un fragmento de código del ejemplo de la libreta de direcciones:

<tc:form> 
   <TX: etiqueta selectOneChoice = "# () bundle.footerLanguage"
       value = "# () controller.language">
     <f:selectItems value="#{controller.languages}"/>
     <f:facet name="change">
       <tc:command action="#{controller.languageChangedList}"/>
     </ f: facet>
   </ tx: selectOneChoice>
</ tc: form>

Seguridad

La extensión módulo de seguridad de Tobago permite proteger los enlaces método con la ayuda de anotaciones. El módulo proporciona comandos alternativos a los componentes, con el manejo de la seguridad. Las anotaciones están disponibles @ RolesAllowed, DenyAll @ y @ PermitAll. Un fragmento de código del ejemplo de la libreta de direcciones:

public class AdminController ( 

   @ RolesAllowed ( "admin")
   admin public String () (
     OUTCOME_ADMIN retorno;
   )

   ...
)

Buenas prácticas y recomendaciones de uso

Manejo de Errores

Es una práctica extendida a la hora de manejar errores cuando se usa Tobago utilizar alguna de las tres formas siguientes:

  • Se lanza una excepción en la aplicación y el contendor de servlet se dirige a una página definida en el fichero web.xml.
  • El manejador del navegador no se refiere a ninguna página existente. El código de error 404 en la web.xml es afectado.
  • El manejador del navegador se dirige a una página con un error de sintaxis.

A continuación mostramos el código de un fichero jsp con las tres posibilidades:

<%@ taglib uri="http://myfaces.apache.org/tobago/component"
prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %>
<layout:overview>
  <jsp:body>
    <tc:box label="Sample Error Scenarios">
      <f:facet name="layout">
        <tc:gridLayout rows="35px;35px;35px;*" columns="*;100px" />
      </f:facet>
      <tc:out value="An exception is thrown in the application. The
servlet container forwards to a page defined in the web.xml." />
      <tc:button action="#{bestPracticeController.throwException}"
label="Application" />
      <tc:out value="The navigation handler refers to a non existing
page. The error code 404 in the web.xml is affected." />
      <tc:button action="404" label="Not Found" />
      <tc:out value="The navigation handler refers to a page with a
syntax error." />
      <tc:button action="syntax" label="Syntax Error" />
      <tc:cell />
      <tc:cell />
    </tc:box>
  </jsp:body>
</layout:overview>

Para ver funcionado de las tres opciones remitimos al lector a la siguiente dirección donde hay un ejmplo de este funcionamiento:

http://tobago.atanion.net/tobago-example-demo/faces/overview/intro.jsp;jsessionid=FB66FE1B8C082543A23DBD8612DFA5A5

Temas

En Tobago es fácil dar a una aplicación una buena apariencia de diseño. Podemos usar temas predefinidos como “speyside” o “scarborough”. La única cosa que tenemos que hacer es configurar los temas en el lugar correcto. Esto se debe hacer en el fichero tobago-config.xml para definir un tema por defecto. Por ejemplo:

<tobago-config>
  <theme-config>
    <default-theme>speyside</default-theme>
  </theme-config>
  <resource-dir>tobago</resource-dir>
</tobago-config>

Transiciones

Para hacer transiciones de una página a otra tenemos dos posibilidades. En la primera la transición se hace desvaneciendo la página actual y mostrando una barra de carga. En la segunda la transición es mas brusca, pasando de una página a la otra directamente después de haberse cargado la segunda en nuestra máquina. A continuación mostramos el código jsp de ambas opciones.

<%@ taglib uri="http://myfaces.apache.org/tobago/component"
      prefix="tc" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib tagdir="/WEB-INF/tags/layout" prefix="layout" %>
<layout:overview>
  <jsp:body>
    <tc:box label="Transitions between pages">
      <f:facet name="layout">
        <tc:gridLayout rows="fixed;fixed;fixed;*" />
      </f:facet>
      <tc:out value="Prevent double-clicks" />
      <tc:button label="Sleep 5 s (transition=true)"
      action="#{transitionController.sleep5s}"/>
      <tc:button label="Sleep 5 s (transition=false)"
      action="#{transitionController.sleep5s}" transition="false"/>
      <tc:cell />
    </tc:box>
  </jsp:body>
</layout:overview>

Ejemplos

A continuación pasamos a mostrar el código necesario para visualizar en nuestra aplicación algunos de los componentes que aporta Tobago:

Para que en nuestra página se nos renderice un botón, no tenemos más que definir el siguiente fuente:

<tc:button label="Borrar" action="#{controller.delete}" 
    image="imagenes/borrar.png" defaultCommand="false">
  <f:facet name="confirmation">
    <tc:out value="¿Realmente me quieres borrar?" />
  </f:facet>
</tc:button>

Al agregar al código del botón la etiqueta f:facet se obliga que al pulsar sobre el botón, el navegador pida confirmación de la acción que se va a ejecutar. Si se pulsa el botón Ok, se ejecutará la acción demandada.

Esta estructura es equivalente para los enlaces.

Se puede utilizar un control genérico tc:command para capturar eventes en los controles tc:selectBooleanCheckbox, tc:selectOneRadio, tc:selectManyCheckbox, y tc:selectOneChoice. A continuación se muestra un ejemplo para que vaya al servidor tras la pulsación de los temas disponibles:

<tx:selectOneChoice label="#{bundle.footerTheme}" value="#{controller.theme}">
  <f:selectItems value="#{controller.themeItems}" />
  <f:facet name="change">
    <tc:command action="#{controller.themeChanged}"/>
  </f:facet>
</tx:selectOneChoice>

Tablas

El componente tc:sheet permite mostrar datos de forma tabular. Podemos ver un ejemplo en el que se muestra como almacenar una agenda:

<tc:sheet columns="1*;1*;1*" value="#{controller.currentAddressList}"
    var="address" state="#{controller.selectedAddresses}"
    sortActionListener="#{controller.sheetSorter}" rows="25"
    showRowRange="left" showPageRange="right" showDirectLinks="center">
  <tc:column id="firstName" label="#{bundle.listFirstName}" sortable="true"
      rendered="#{controller.renderFirstName}">
    <tc:out value="#{address.firstName}" />
  </tc:column>
  <tc:column id="lastName" label="#{bundle.listLastName}" sortable="true"
      rendered="#{controller.renderLastName}">
    <tc:out value="#{address.lastName}" />
  </tc:column>
  <tc:column id="dayOfBirth" label="Birthday" sortable="true"
      rendered="#{controller.renderDayOfBirth}">
    <tc:out value="#{address.dayOfBirth}">
      <f:convertDateTime pattern="#{bundle.editorDatePattern}" />
    </tc:out>
  </tc:column>
</tc:sheet>

El atributo value nos devuelve una lista desde el controlador utilizado que contiene la lista con los datos. El tag usado tc:sheet es la raíz de un árbol con tres columnas identificadas por tc:column.

  • En el tag sheeet, se define una variable local address la cual identificará cada una de las filas que nos ha devuelto la lista con los resultados.
  • En cada columna se mostrará en la cabecera el valor de la etiqueta label de cada columna.

Pestañas

El control tc:tabGroup renderiza lo que conocemos como pestañas, es decir, vistas de distintos paneles en la misma página. Para la implementación de este control, el proyecto Tobago ha utilizado Ajax para cambiar el contenido interno de los paneles.

<tc:tabGroup switchType="reloadTab" immediate="true">
  <tc:tab label="#{bundle.editorTabPersonal}">
    <jsp:include page="tab/personal.jsp"/>
  </tc:tab>

  <tc:tab label="#{bundle.editorTabBusiness}" rendered="#{!controller.simple}">
    <jsp:include page="tab/business.jsp"/>
  </tc:tab>

  <tc:tab label="#{bundle.editorTabMisc}" rendered="#{!controller.simple}">
    <jsp:include page="tab/misc.jsp"/>
  </tc:tab>
</tc:tabGroup>

En este ejemplo se han introducido unas condiciones para la visualización de la segunda y tercera pestaña, utilizando para ello el atributo rendered.

Otros controles

  • Para que la aplicación desarrollada con Tobago tenga apariencia de una aplicación de escritorio se puede usar el control denominado tc:menu, con este control y otros que mostramos a continuación conseguimos la visualización de un menú.
<tc:menuBar id="menuBar">
  <tc:menu label="_File">
    <tc:menuItem label="_New" action="#{controller.createAddress}" image="image/org/tango-project/tango-icon-theme/16x16/actions/contact-new.png"/>
    <tc:menuItem label="_Add Dummy Addresses"
        action="#{controller.addDummyAddresses}"/>
    <tc:menuSeparator/>
    <tc:menuItem label="_Logout" image
        ="image/org/tango-project/tango-icon-theme/16x16/actions/system-log-out.png"/>
  </tc:menu>

  <tc:menu label="_Settings">
    ...
    <tc:menu label="_Theme">
      <tx:menuRadio action="#{controller.themeChanged}"
          value="#{controller.theme}">
        <f:selectItems value="#{controller.themeItems}"/>
      </tx:menuRadio>
    </tc:menu>
    <tc:menuCheckbox label="Simple _Mode" value="#{controller.simple}"/>
  </tc:menu>
  ...
</tc:menuBar>
  • Si queremos implementar en nuestra página una especie de grupo de botones a modo de barra de herramientas, lo conseguimos con el control tc:toolbar
<tc:toolBar iconSize="big">
  <tc:toolBarCommand label="#{bundle.toolbarAddressList}"
      action="#{controller.search}" immediate="true" image=
 "image/org/tango-project/tango-icon-theme/32x32/mimetypes/x-office-address-book.png"
      disabled="#{facesContext.viewRoot.viewId == '/application/list.jsp'}"/>
  ...
</tc:toolBar>
  • Si tenemos la necesidad de subir algún fichero, usaremos el control tc:file. El archivo que se va a subir será alojado dentro de un atributo de tipo FileItem dentro del paquete commons-fileupload
<tc:file value="#{controller.uploadedFile}" required="true">
  <tc:validateFileItem contentType="image/*"/>
</tc:file>

Con el controlador tc:validateFileItem filtras que el usuario no pueda subir un fichero que no sea imagen.