Trinidad

RECU-0135 (Recurso Referencia)

Descripción

Apache Trinidad es una librería de componentes JavaServer Faces. Esta librería es un subproyecto de Apache MyFaces. Oracle donó los componentes ADF Faces a Apache, el cual los introdujo al proyecto Apache MyFaces.

El proyecto Apache MyFaces contiene varios subproyectos relacionados con la tecnología JavaServer. Apache MyFaces provee de los siguientes elementos:

  • Una implementación JavaServer Faces (MyFaces API, MyFaces implement modules).
  • Contiene varias librerías de componentes “widgets UI” para construir aplicaciones web con JSF (ej. MyFaces Tomahawk, MyFaces Trinidad, MyFaces Tobago).
  • Paquetes de extensiones para JavaServer Faces (ej. MyFaces Orchestra).
  • Módulos de integración para otras tecnologías y estándares (ej. MyFaces Portlet Bridge para la integración con portlet-estándar).

Renderización parcial de la página (PPR)

AJAX es la técnica mas usada en aplicaciones web a día de hoy. Trinidad permite una construcción sencilla basada en componentes AJAX y ofrece muchos caminos para atender peticiones tanto de AJAX como de componentes no AJAX.

PartialSubmit - PartialTriggers

Vamos a realizar un ejemplo sencillo con partialSubmit y los componentes de Trinidad "commandbutton" y "command link", el evento lanzado por estos componentes será interpretado como un evento AJAX.

Primero se envía una notificación al servidor que no modifica nada de la página. Para hacer esto necesitamos comunicar que parte de la página debe de recargarse. La manera mas fácil de hacerlo es mediante partialTriggers que conecta componentes que deben de ser recargados con los componentes que son la razón para la recarga.

<tr:commandButton text="Do Something"
                       id="myButton"
                       partialSubmit="true"
                       actionListener="#{myBean.doSomething}"/>

  <-- repaint the outputText any time 'myButton' has an event -->
  <tr:outputText value="#{myBean.textValue}"
                    partialTriggers="myButton"/>


public void doSomething(ActionEvent event)
{
  // Change the text value
  this.textValue = "A new value";
}

  <tr:commandButton text="Do Something"
                       id="myButton"
                       partialSubmit="true"
                       partialTriggers="myButton"
                       actionListener="#{myBean.doSomething}"/>

  <-- repaint the outputText any time 'myButton' has an event -->
  <tr:outputText value="#{myBean.textValue}"
                    partialTriggers="myButton"/>


public void doSomething(ActionEvent event)
{
  ((CoreCommandButton) event.getSource()).setDisabled(true);
  // Change the text value
  this.textValue = "A new value";
}
Limitaciones de la Renderización parcial de la página

Una de las limitaciones más importantes en el uso de la PPR es que se puede usar para modificar cualquier propiedad de un componente. Sin embargo, no se puede usar PPR para modificar directamente la propiedad "rendered" de un componente.

AutoSubmit

Un uso común de PPR es el atributo autoSubmit. Este atributo es soportado en todos los componentes de entrada y devuelve el valor de los campos ante cualquier petición de tipo AJAX. Para minimizar las comunicaciones, en el caso de introducir texto, solo lanza el autoSubmit cuando se sale del componente

En el siguiente ejemplo, un botón se activa automáticamente cuando la cantidad es mayor que cero:

<tr:inputText value="#{myBean.quantity}" autoSubmit="true"
                   id="quantity"/>

  <tr:commandButton text="Put One Back"
                       disabled="#{myBean.quantity le 0}"
                       partialTriggers="quantity"
                       actionListener="#{myBean.putOneBack}"/>

Usando el ContextRequest

No siempre se quiere identificar un componente mediante el empleo de partialTriggers:

  • No se conoce que componente necesita recargarse hasta que se procese en el servidor.
  • Solo se actualiza un componente en determinados casos, no siempre se actualiza el componente.

Para estos casos, se puede programar la recarga de un componente a través de RequestContext.addPartialTarget():

if (_needToRepaint())
  {
    // Repaint another component programatically
    RequestContext rc = RequestContext.getCurrentInstance();
    rc.addPartialTarget(anotherComponent);
  }
  if (_needToRepaintAParticularRow())
  {
   
    RequestContext rc = RequestContext.getCurrentInstance();
    Object oldRowKey = table.getRowKey();
    table.setRowIndex(rowToRepaint);
    rc.addPartialTarget(componentWithinRow);
   
    table.setRowKey(oldRowKey);
  }

Comunicaciones entre páginas

Uno de los aspectos mas importantes es como comunicar valores entre páginas. Se puede pensar en guardar el valor en la petición o en la sesión , ambas posibilidades funcionan pero sin duda son mas limitadas. Apache Trinidad introduce un nuevo ámbito denominado pageFlowScope que busca la mejor oferta de ambos

pageFlowScope

Ademas de los ámbitos proporcionados por JSF (applicationScope, sessionScope, y requestScope), Trinidad añade un ámbito (pageFlowScope). Los valores son añadidos a este ambito para estar disponibles mientras se continua la navegación entre páginas

<h:outputText value="#{pageFlowScope.someKey}"/>

Limitaciones de pageFlowScope

Antes de continuar, hay una serie de limitaciones de pageFlowScope. En primer lugar, desde que pageFlowScope no es parte de la especificación JSF estándar, hay un par de las sutilezas de los ámbitos estándar no se puede soportar:

  • EL expresiones no busca automáticamente en pageFlowScope, si desea localizar una página en el ámbito del flujo (flow-scoped), debe incluir "pageFlowScope".
  • pageFlowScope no puede ser utilizado como un <managed-bean-scope>. (Pero el <valor> de un <managed-property> puede hacer referencia a los valores de page Flow-Scoped.)

En segundo lugar, porque las páginas original y de detalle tienen que ponerse de acuerdo sobre el nombre de la página de flujo variable de ámbito, que se acopla más.

Por último, nunca pageFlowScope se vacía a sí mismo, la única manera de limpiar pageFlowScope es forzarlo manualmente.

Uso de tr:setActionListener

Este código es fácil, pero para hacer aún más simple de codificación, le ofrecemos una etiqueta ActionListener nueva que le permite el código de este estilo sin tener que escribir ningún código Java. La etiqueta <tr:setActionListener> tiene dos propiedades, "from" y "to", y simplemente toma un valor de la "from" atributo y lo pone en "to".

Modelo de tabla

El componente se utiliza para mostrar una lista de datos estructurados. Por ejemplo, si tenemos una estructura de datos llamada Persona que tiene dos propiedades - Nombre y Apellidos, podríamos utilizar una tabla con dos columnas - uno para el nombre, y otro para el apellido - para mostrar una lista de objetos Persona.

El componente de la tabla es similar al componente UIData estándar en JSF, pero incluye una serie de características adicionales, incluido el apoyo para la identificación de las filas por clave (en lugar de por el índice), soporte integrado para la paginación a través de modelos de gran tamaño, la clasificación del modelo, y la selección de elementos únicos o múltiples en el modelo

Componente Tabla

El componente Apache Trinidad utiliza un modelo para acceder a los datos en la lista subyacente. La clase de modelo específico es org.apache.myfaces.trinidad.model.CollectionModel. También puede utilizar otras instancias de modelo, por ejemplo, java.util.List, matriz, y javax.faces.model.DataModel. La tabla se convertirá automáticamente en la instancia en un CollectionModel.

Para acceder a una fila en particular en la lista, en primer lugar convertir la fila en la fila actual, y luego llamar a la getRowData () (método de la tabla). Para hacer una fila actual, llame al método setRowIndex() (en la tabla) con el índice adecuado en la lista. Alternativamente, llame al método setRowKey() con el rowKey apropiado.

Para obtener el número total de filas en la lista, llame al método de la tabla getRowCount () . En el caso de que el modelo todavía no sepa el número total de filas que están disponibles, getRowCount () devolverá -1.

La tabla tiene una isRowAvailable () que devuelve true si la fila actual está disponible. Este método es especialmente útil cuando el número total de filas es desconocido.

Columnas

Los hijos inmediatos de un componente de la tabla deben ser todos componentes <tr:column>. Cada componente visible ADF Columna crea una columna separada en la tabla.

Encabezados

Utilice el "encabezamiento",la etiqueta F:facet para crear el encabezado de la columna. También puede usar el atributo "headerText" para establecer el encabezado de la columna. El ejemplo siguiente crea una tabla de dos columnas con los encabezados de columna - "Nombre" y "Apellidos":

<tr:table> 
   <tr:column>
     <f:facet name="header">
       <tr:outputText value="Nombre"/>
     </ f: facet>
     ...
   </ tr: column>
   <tr:column headerText="Apellidos">
     ...
   </ tr: column>
</ tr: table>

Los componentes de los hijos muestran los datos de la columna para cada fila de la columna. La columna no crear componentes hijos por fila, sino que cada hijo es repetidamente prestado, una vez por fila. Debido a este comportamiento , algunos componentes no trabajan dentro de la tabla.

Todo lo que es sólo la producción pura, sin ningún problema, funciona sin problemas, al igual que los componentes que no "mutan",

Los componentes que mutan su estado, están afectados, pero los que implementan EditableValueHolder son compatibles (esto incluye todos los controles de formulario de entrada de la especificación JSF, así como controles de entrada de ADF Faces), componentes que están en UIXShowDetail.

Como cada fila se marcan con los datos de la fila actual En el siguiente ejemplo, los datos de cada fila se coloca debajo de la propiedad de EL "fila". Cada columna muestra los datos de cada fila por obtener otras propiedades de la fila de la "propierties":

<tr:table var="row" value="#{myBean.allEmployees}"> 
   <tr:column>
     <tr:outputText value="#{row.firstname}"/>
   </ tr: column>
   <tr:column>
     TR: valor outputText = "# () row.lastname" />
   </ tr: column>
</ tr: table>
Grupos de Columnas

<tr:column> son etiquetas que se pueden anidar para producir grupos de columnas. El encabezado de una columna del grupo se extiende en todas las columnas que contiene. El ejemplo siguiente crea un grupo de columnas que tiene el encabezado "Nombre" y contiene dos columnas con encabezados "first" y "last":

<tr:table var="row" value="#{myBean.employees}"> 
     <tr:column headerText="Name">
       <tr:column headerText="First">
         <tr:outputText value="#{row.firstname}"/>
       </ tr: column>
       <tr:column headerText="Last">
         TR: valor outputText = "# () row.lastname" />
       </ tr: column>
     </ tr: column>
   </ tr: table>

Rango de navegación

Cuando la lista que se muestra en una tabla es enorme, la tabla puede romper la lista en rangos y mostrar un solo rango a la vez. Los rangos de los controles se proporcionan en la tabla para dejar que el desplazamiento del scroll del usuario al siguiente rango, o para volver al anterior. Si se conoce el tamaño total de la lista,se habilita un control para que el usuario salte directamente a una parte concreta de la lista . Utilice los atributos de la tabla "rows" y "first" para controlar la función de navegación rango.

El número máximo de filas a mostrar en un solo rango está controlada por el atributo "rows" , que por defecto a un tamaño razonable (por ejemplo, 25). Para deshabilitar la navegación rango (y mostrar todas las filas en una sola página) establece este atributo en 0. En el siguiente ejemplo, el número máximo de filas que se muestran por alcance se establece en 10:

<tr:table rows="10" ...>

El rango actual de pantalla es controlado por el atributo "first". Este atributo es un índice (basado en cero) de una fila en la lista. Cada rango se inicia cuando se identifica fila como "first", y sólo contiene tantas filas como lo indica el atributo "rows". Inicialmente, el atributo "first" esta por defecto a cero, lo que muestra el rango es la primera fila en la parte superior.

RangeChangeEvent

Cuando el usuario cambia el rango (que se muestra en la tabla), la tabla genera un RangeChangeEvent. Este evento incluye el índice (basado en cero) de la fila que ahora debe estar en la parte superior del rango. La tabla responde a este evento por cambiar automáticamente el valor del atributo "first" a este índice.

En algunos casos es necesario saber cuando el usuario cambia el rango de la tabla (por ejemplo, cuando el usuario navega hacia adelante podría ser necesario que libere a todos los datos en caché creado para una serie anterior). Para recibir notificaciones de cuando el usuario cambia el rango, se debe registrar una instancia de RangeChangeListener .

Selección

La función de selección de una tabla permite al usuario seleccionar una o más filas en la lista. El usuario puede entonces realizar alguna operación en el registro seleccionado por la activación de un componente ActionSource adecuado (por ejemplo, haciendo clic en un control CommandButton ADF). Utilice el "rowSelection", atributo de la tabla, para habilitar la función de selección.

Hay dos tipos de selección: simples y múltiples. El tipo de selección está determinada por el valor del atributo "selection". Utilice el valor "single" para habilitar la selección única, y "multiple" para permitir la selección múltiple.

La selección actual de las filas de la tabla puede ser inspeccionada y modificada a través de la RowKeySet con objeto de obtener llamando getSelectedRowKeys () en la tabla. Para cambiar mediante programación la selección, añadir o eliminar rowKeys de este conjunto. Alternativamente, la fila correspondiente se puede hacer llamando al actual setRowIndex o setRowKey sobre la tabla, y luego la selección de la fila puede ser cambiada llamando a add() o remove() de la RowKeySet .

En el siguiente ejemplo, se llama al método performDelete cuando se hace clic sobre el botón "Eliminar" .

<tr:table binding="#{mybean.table}" rowSelection="multiple" ...> 
   <f:facet name="footer">
       <tr:commandButton text="Delete" actionListener="#{mybean.performDelete}"/>
   </ f: facet>
   ...
</ tr: table>

// El método performDelete recorre todas las filas seleccionadas y llama al método markForDeletion () en cada uno:

performDelete public void (acción ActionEvent)
(
   Mesa UIXTable getTable = ();
   Selección Iterator = table.getSelectedRowKeys (). Iterador ();
   Objeto oldKey = table.getRowKey ();
   while (selection.hasNext ())
   (
     RowKey Object = selection.next ();
     table.setRowKey (rowKey);
     Fila MyRowImpl = (MyRowImpl) table.getRowData ();
     row.markForDeletion ();
   )
   / / Restaurar la antigua clave:
   table.setRowKey (oldKey);
)

/ / Métodos de enlace para el acceso a la mesa.
public void ajustable (tabla UIXTable) (_table = tabla;)
público UIXTable getTable () (return _table;)
_table UIXTable privado

Componente Tree y TreeTable

EL componente Tree se utiliza para mostrar datos jerárquicos. Por ejemplo, si tenemos un gráfico que representa el personal de la organización de todos los informes directos en el marco de cada empleado, se podría utilizar un componente de árbol para mostrar este gráfico. Cada elemento (empleado) en la jerarquía puede tener cualquier número de elementos secundarios (directos). Además de varios elementos primarios pueden compartir los elementos de un mismo hijo.

Apache Trinidad en la actualidad dispone de dos componentes del árbol: Tree y TreeTable. El componente Tree es compatible con múltiples elementos de raíz, y tiene una sencilla interfaz de usuario (UI) (cada elemento en el tree es ofrece una sangría para indicar su nivel en la jerarquía, y se conecta a su padre). Las características del componente Tree incluyen mecanismos para la expansión y el colapso de partes de la jerarquía.

El componente TreeTable muestra una jerarquía en una interfaz de usuario similar a un tabla , y es más elaborada que el componente Tree. TreeTable permite mostrar las columnas de datos por elemento de la jerarquía. Las características del componente TreeTable incluiyen mecanismos para centrarse en las subestructuras (en el árbol principal), así como la expansión y el colapso de los elementos de la jerarquía.

Componente Chart

El componente de gráficos Trinidad proporciona una solución de gráficos en un entorno de JSF. Utiliza el estándar W3C Scalable Vector Graphics para mostrar gráficos en el navegador del cliente. El Gráfico de Trinidad, soporta los tipos de gráficos siguientes:

  • verticalBar - Una tabla verticalBar utiliza una serie de columnas para comparar los valores entre los grupos. Los grupos se organizan horizontalmente, mientras que los valores se muestran verticalmente a fin de poner más énfasis en la comparación de los valores y menos énfasis en el tiempo.
  • barra horizontal - Un gráfico de barra horizontal utiliza una serie de barras para comparar los valores entre los grupos. Los grupos están organizados verticalmente, mientras que los valores se muestran en horizontal, a fin de poner más énfasis en la comparación de los valores y menos énfasis en el tiempo.
  • stackedVerticalBar - Una tabla vertical apilado se utiliza para comparar la contribución de cada valor a un total a través de una serie.
  • stackedHorizontalBar - Similar a stackedVerticalBar excepto que la serie y los grupos se pasan
  • Pie - Uno de los tipos de gráficos más utilizados, los gráficos circulares muestran cómo la proporción de datos contribuyen a un todo.
  • Area - Zona de cartas hincapié en el grado de cambio en el tiempo, y también muestra la relación de las partes de un todo.
  • stackedArea - Un gráfico de área apilada es un gráfico de áreas que utiliza dos o más series de datos y puede ser utilizado para comparar el grado de cambio a un total a través de una serie
  • líne - Un gráfico de líneas muestra las tendencias en los datos con el paso del tiempo.
  • barline - Un gráfico barline muestra la combinación de la barra vertical y gráfico de líneas. Cada valor de una serie es alternada de un barline, con el valor de la primera serie aparece como una barra.
  • XYLine - Un gráfico XYLine ilustra las tendencias en los datos con el paso del tiempo. Es diffentiates de un gráfico de línea normal por tener los valores de x dictar la pantalla a lo largo del eje X.
  • Diagrama de dispersión - Un gráfico de dispersión utiliza puntos de valor para representar datos. Este gráfico necesidades tanto los valores a lo largo de los ejes X e Y.
  • radar - Un gráfico radial es un gráfico circular en la que los datos se muestran en términos de valores y angles.It es un gráfico circular, utilizados principalmente como una herramienta de comparación.
  • radarArea - Esto es similar a un gráfico de radar, excepto por el hecho de que la zona delimitada por una serie está llena.
  • funnel - Un grafico funnel muestra como la proporción de datos contribuyen a un todo. Es similar a un gráfico circular, pero muestra como un embudo.
  • circularGauge - A los datos circularGuage muestra en un indicador. Tiene un punto de giro, alrededor del cual gira un valor de modo que se puede mostrar en relación a un máximo y un mínimo.
  • semiCircularGauge - Similar a un circularGauge excepto por el hecho de que el indicador es de forma semicircular

Validadores y Conversores

Uno de los beneficios de Apache Trinidad es que soporta los convertidores y validadores en el lado del cliente. Esto significa que los errores pueden ser capturados en el cliente evitnado de esta manera una ida y vuelta del error.

La idea básica de la conversión y validación en el cliente es que funciona de una manera muy similar a como funciona en el servidor, excepto el idioma que en el cliente es javascript en vez de Java. Hay objetos convertidor de javascript que soportan los métodos getAsString () y getAsObject (). Un TrConverter puede lanzar una TrConverterException. Hay objetos validador de javascript que soportan el método validate (). Un TrValidator puede lanzar una TrValidatorException.

Conversores

Digamos que ha escrito una aplicación javax.faces.convert.Converter y ahora desea agregar el conversor en el lado del cliente. La primera cosa a hacer es escribir una versión del convertidor en javascript. La principal diferencia entre los convertidores en el cliente y el servidor es que en el cliente no se tiene acceso a un componente. La etiqueta del campo se se pasa al convertidor para su uso en el formato de la cadena de error. Aquí está el código javascript para el convertidor de "interfaz".

/**
 * Converter "interface" similar to javax.faces.convert.Converter,
 * except that all relevant information must be passed to the constructor
 * as the context and component are not passed to the getAsString or getAsObject method
 *
 */
function TrConverter()
{
}


/**
 * Convert the specified model object value, into a String for display
 *
 * @param value Model object value to be converted
 * @param label label to identify the editableValueHolder to the user
 *
 * @return the value as a string or undefined in case of no converter mechanism is
 * available (see TrNumberConverter).
 */
TrConverter.prototype.getAsString = function(value, label){}

/**
 * Convert the specified string value into a model data object
 * which can be passed to validators
 *
 * @param value String value to be converted
 * @param label label to identify the editableValueHolder to the user
 *
 * @return the converted value or undefined in case of no converter mechanism is
 * available (see TrNumberConverter).
 */
TrConverter.prototype.getAsObject = function(value, label){}

Validadores

La idea general de escribir los validadores es casi exactamente lo mismo que escribir convertidores de cliente. Digamos que ha escrito una aplicación javax.faces.validator.Validator y ahora desea agregar la validación del cliente. La primera cosa a hacer es escribir una versión del validador en javascript. Aquí está el código javascript para la interfaz de la "TrValidator".

/ ** 
  * Validador de "interfaz", similar a javax.faces.validator.Validator,
  * Excepto que toda la información pertinente debe ser pasado al constructor
  * as the context and component are not passed to the validate method
  *
  * /
función TrValidator ()

/ **
  * Realizar la corrección de los controles aplicados por este validador.
  * Si se encuentra algún violaciónes, un TrValidatorException serán lanzados
  * TrFacesMessage que contienen la descripción de la falla.
  * @ Param valor valor que deberá ser validada
  * @ Param etiqueta etiqueta para identificar el editableValueHolder para el usuario
  * @ Param Convertidor de formato de cadena de error correctamente
  * /
TrValidator.prototype.validate = function (valor, etiqueta, conversor) ()

  // El validador puede arrojar objetos TrValidatorException javascript:
      
/ **
  * A TrValidatorException es una excepción lanzada por el método validate () de
  * El validador para indicar que la validación no.
  *
  * @ Param FacesMessage FacesMessage asociado a esta excepción
  * @ Param resumen localizado el texto del mensaje resumen, utilizarse sólo si es nulo FacesMessage
  * @ Param localizado detalle el texto del mensaje detalle, utilizarse sólo si es nulo FacesMessage
  * /
TrValidatorException función (
   FacesMessage,
   resumen,
   detalle
   )

Navegación

Las páginas no están escritas en forma aislada, una solicitud consta de muchas páginas. A menudo, estas páginas se organizan en un árbol, y los ejercicios de usuario abajo en el árbol para acceder a información más específica. Un ejemplo de navegación

<navigation-rule>
    <navigation-case>
      <from-outcome>guide.navigationModel_root</from-outcome>
      <to-view-id>/components/navmodel/page.jspx</to-view-id>
      <redirect/>
    </navigation-case>
    <navigation-case>
      <from-outcome>guide.navigationModel_a1</from-outcome>
      <to-view-id>/components/navmodel/page_a1.jspx</to-view-id>
      <redirect/>
    </navigation-case>
    <navigation-case>
      <from-outcome>guide.navigationModel_a2</from-outcome>
      <to-view-id>/components/navmodel/page_a2.jspx</to-view-id>
      <redirect/>
    </navigation-case>
    <navigation-case>
      <from-outcome>guide.navigationModel_a3</from-outcome>
      <to-view-id>/components/navmodel/page_a3.jspx</to-view-id>
      <redirect/>
    </navigation-case>
    <navigation-case>
      <from-outcome>guide.navigationModel_a4</from-outcome>
      <to-view-id>/components/navmodel/page_a4.jspx</to-view-id>
      <redirect/>
    </navigation-case>
     <navigation-case>
      <from-outcome>guide.navigationModel_a1b1</from-outcome>
      <to-view-id>/components/navmodel/page_a1b1.jspx</to-view-id>
      <redirect/>
    </navigation-case>
  </navigation-rule>

Ejemplos

Aplicación de Ejemplo En este apartado haremos una aplicación que mostrará una de las características de la librería Apache Trinidad. La idea es mostrar las capacidades AJAX de esta librería por lo que el ejemplo hará uso de la "Renderización Parcial de Página".

El ejemplo será muy sencillo, compuesto por dos campos de formulario (uno de entrada y otro de salida), de forma que el usuario introduce un valor en el primer campo y cuando éste pierde el foco (por ejemplo cuando el usuario pulsa el tabulador) el contenido es enviado al servidor, procesado (en concreto pasado a mayúsculas) y devuelto al cliente para que se rellene el segundo campo.

Diseño de las Páginas JSP

Puesto que Apache Trinidad es una librería de etiquetas AJAX, para aplicaciones complejas es necesario trabajar con documentos JSP. Los documentos JSP son una variante de las páginas JSP en la que los documentos se forman como archivos XML que deben estar bien formados. Si nuestras páginas JSP son documentos XML bien formados, el renderizador podrá construir un árbol DOM correcto y podrá aplicar AJAX con facilidad.

Un documento JSP se caracteriza por tener extensión .jspx e incluir código XML en su interior. Puesto que no podemos incluir directivas jsp la forma de incluir una librería de etiquetas es la siguiente:

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:trh="http://myfaces.apache.org/trinidad/html"
                xmlns:tr="http://myfaces.apache.org/trinidad">
          <!-- Contenido -->
     </jsp:root>

Nuestro ejemplo estará formado por un único documento JSP, llamado ejemplo.jspx, que tendrá el siguiente código fuente:

<?xml version="1.0" encoding="UTF-8"?>
     <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:trh="http://myfaces.apache.org/trinidad/html"
                xmlns:tr="http://myfaces.apache.org/trinidad">
          <jsp:directive.page contentType="text/html;charset=utf-8"/>
          <link rel="stylesheet" type="text/css" href="/servicios/madeja/css/estilos.css" />
          <f:loadBundle basename="org.javacenter.jsf.Mensajes" var="msg"/>
          <f:view>
              <h1> <h:outputText value="#{msg.tituloPrueba}"/> </h1>
           <p> Fecha de Carga: <h:outputText value="#{bean.fecha}"/> </p>
           <tr:document title="Ejemplo de Renderización Parcial de Página">
                  <tr:form>
                      <tr:panelPage>
                          <tr:panelHeader text="Bienvenido a la Página de
     Ejemplos de Apache Trinidad">
                              <tr:panelGroupLayout layout="horizontal">
        <tr:panelHeader text="Escribe algo en el campo de texto y pulsa el
     tabulador.">
            <tr:inputText value="#{bean.nombre}" autoSubmit="true"
                          id="campoTexto1"/>
        </tr:panelHeader>
                              </tr:panelGroupLayout>
                              <tr:panelGroupLayout layout="horizontal">
        <tr:panelHeader text="Aquí aparecerá la cadena insertada pasada a
     mayúsculas.">
            <tr:inputText id="campoTexto2" disabled="true"
                    value="#{bean.nombre}" partialTriggers="campoTexto1"/>
        </tr:panelHeader>
                              </tr:panelGroupLayout>
                          </tr:panelHeader>
                      </tr:panelPage>
                  </tr:form>
              </tr:document>
          </f:view>
     </jsp:root>

Lo más destacable son los dos campos inputText, ambos asociados al campo "nombre" del bean. El primero de ellos tiene el atributo autoSubmit="true" lo que indica que cuando cambie y pierda el foco, el formulario será enviado mediante AJAX al servidor. El segundo campo tiene el atributo partialTriggers="campoTexto1" que indica que cuando se envíe el formulario con id igual a "campoTexto1" se actualice también este campo.

También hemos incluido un fichero de mensajes, cuyo contenido es el siguiente: titulo=Ejemplo de Renderización Parcial con Apache Trinidad tituloPrueba=Ejemplo de Renderización Parcial de Página

Implementación del Bean

El código del bean es muy simple. Su código es el siguiente:

package org.javacenter.jsf;
   import java.util.Date;
   public class Bean {
        private String nombre = "";
        public String getNombre() {
            return nombre.toUpperCase();
        }
        public void setNombre(String nombre) {
            this.nombre = nombre;
        }
        public String getFecha() {
            return new Date().toString();
        }
   }

Como podemos observar, el bean no tiene nada en especial. Simplemente tiene un atributo nombre con su correspondiente método setter y getter y un método getFecha() que permitirá al documento JSP acceder a un atributo no existente llamado fecha.

Configuración

La configuración del fichero web.xml debe hacerse tal y como se muestra. Podemos ver un ejemplo a continuación:

<?xml version="1.0" encoding="UTF-8"?>
   <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                            http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <context-param>
            <param-name>com.sun.faces.verifyObjects</param-name>
            <param-value>false</param-value>
        </context-param>
        <context-param>
            <param-name>com.sun.faces.validateXml</param-name>
            <param-value>true</param-value>
        </context-param>
        <context-param>
            <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
            <param-value>client</param-value>
        </context-param>
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>/faces/*</url-pattern>
        </servlet-mapping>
        <session-config>
            <session-timeout>30</session-timeout>
        </session-config>
        <filter>
            <filter-name>trinidad</filter-name>
            <filter-class>
                org.apache.myfaces.trinidad.webapp.TrinidadFilter
            </filter-class>
        </filter>
        <filter-mapping>
            <filter-name>trinidad</filter-name>
            <servlet-name>Faces Servlet</servlet-name>
        </filter-mapping>
        <servlet>
            <servlet-name>resources</servlet-name>
            <servlet-class>
                org.apache.myfaces.trinidad.webapp.ResourceServlet
            </servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>resources</servlet-name>
            <url-pattern>/adf/*</url-pattern>
        </servlet-mapping>
   </web-app>

Ahora debemos configurar JSF para añadir el render kit de Apache Trinidad y poner el bean dentro del alcance de los documentos JSP. Para ello escribiremos lo siguiente:

<?xml version='1.0' encoding='UTF-8'?>
   <!DOCTYPE faces-config PUBLIC
   "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
   "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
   <faces-config>
        <application>
            <default-render-kit-id>
                 org.apache.myfaces.trinidad.core
            </default-render-kit-id>
        </application>
        <managed-bean>
            <managed-bean-name>bean</managed-bean-name>
            <managed-bean-class> org.javacenter.jsf.Bean </managed-bean-class>
            <managed-bean-scope> request </managed-bean-scope>
        </managed-bean>
   </faces-config>

Enlaces externos