Componentes personalizados en Echo2 – Parte I

16/11/2006

Desarrollo con Echo2
Este es el primero de una serie de artículos acerca de la creación de componentes para Echo2:

El framework Echo2 viene con una serie de componentes predefinidos que te permiten construir una aplicación Web. Sin embargo quizás quieras construir los tuyos propios que vayan mas allá de los básicos que trae el framework.

Una forma de crearte tus propios componentes consistiría en la composición de varios de los ya existentes. Por ejemplo podríamos crearnos nuestro propio componente LoginPanel como una simple composición de un Grid, un TextField y un Button. Y podríamos añadirles document listeners y action listeners para que actuen como un único componente.

Pero ¿qué ocurre si queremos crear un componente que simplemente no existe o si lo que queremos es modificar significativamente el modo en que trabaja un componente? Para conseguir esto tenemos que escribir nuestro propio componente con su correspondiente elemento de representación (rendering peer).

Un ejemplo sencillo

Comencemos creando un sencillo componente llamado RulerLine. Este componente nos pemitirá dibujar una línea horizontal en la parte cliente. Aunque es un componente tremendamente sencillo ya que no tiene entrada por parte del usuario y no necesita un control de estado especial nos servirá como comienzo.

/**
* <code>RulerLine</code> es un componente muy sencillo
*/
public class RulerLine extends Component {
}

Aunque podría parecer que aún no tenemos nada, lo cierto es que con esto ya tenemos un componente que soporta colores de fondo y de primer plano, sus propias fuentes y que además puede formar parte de la gerarquía de componententes de Echo2.

Mapeo de componente con su par de representación

Echo2 utiliza un truco de recursos Java para mapear un componente a su representación. Cuando tienen un componente que representar, busca todas las instacias de un archivo de propiedades especial y busca en estas instancias el mapeo entre la clase del componente y su clase correspondiente de representación.

El nombre del archivo de propiedades es:

/META-INF/nextapp/echo2/SynchronizePeerBindings.properties

Solamente necesitas situar este archivo en el raiz de tu archivo JAR y Echo2 lo encontrará haciendo uso de su nombre y lo revisará para encontrar el mapeo necesario.

Siguiendo con nuestro ejemplo, crearemos el archivo /META-INF/nextapp/echo2/SynchronizePeerBingins.properties en nuestro archvio JAR y escribiremos lo siguiente:

example.RulerLine example.ui.RulerLinePeer

Lo que indicará al framework Echo2 que el componente RulerLine es representado por su par de representación RulerLinePeer.

Elementos de representación

Los elementos de representación en Echo2 no tienen estado. Se utiliza una misma instancia de un elemento de representación para TODOS los componentes que están mapeados con ella. Esto ayuda a reducir la cantidad de memoria de una aplicación web Echo2. Esto también quiere decir que debemos ser cuidadosos al escribir el código de los elementos de representación y asegurarnos de no fijar variables de instancia, etc…

El elemento de representación se encarga de “representar” XML y normalmente contenido XHTML en unos mensajes XML especiales que se envían al motor AJAX de Echo2 que se encuentra en el navegador cliente.

El motor AJAX cliente sabe como interpertar muchos de estos mensajes y realiza acciones como la adición/eliminación DOM y cosas por el estilo.

No explicaremos la estructura de los mensajes XML ya que raramente es necesario conocerla. Echo2 realiza un buen trabajo en cuanto a la “encapsulación” de los mismos en llamadas a un API Java de tal modo que nunca veas el XML que viaja. En su lugar, todo se transforma de y en objetos Java.

Puedes ver los mensajes XML enviados y devueltos añadiendo el parámetro “debug” a la URL de tu aplicación Echo2. Esto abre un panel de depuración que muestra todas las comunicaciones con el servidor en tiempo real.

Por ejemplo http://demo.nextapp.com/Email/app?debug mostrará la aplicación de ejemplo Email de Echo2 con el panel de depuración en acción.

Añadiendo XHTML al DOM del cliente

Un elemento de representación debe implementar una interfaz especial llamada

nextapp.echo2.webcontainer.ComponentSynchronizePeer

Durante el ciclo de vida del proceso de representación se llamará a los métodos de esta interfaz.

Se llama a ComponentSynchronizePeer.renderAdd para añadir la representación XHTML del componente en el navegador cliente. Hay dos modos de realizar esto, pero nos centraremos en el más habitual que consiste en la adición DOM.

Existe un concepto de componente de representación puro de cliente. Sin embargo se trata de un concepto avanzado que no contemplaremos en esta parte del tutorial.

Echo2 tiene una serie de características que permite añadir contenido XHTML al Document Object Model (DOM – Modelo de objetos de documento) en el navegador cliente.

Si tu elemento de representación utiliza este mecanismo para añadir XHTML al servidor (y la mayoría lo hacen) también debes soportar otro interfaz especial llamado

nextapp.echo2.webcontainer.DomUpdateSupport

Tiene un único método llamado renderHtml que puede llamarse para representar el XHTML que se enviará al navegador cliente y que será insertado en el DOM.

Aquí tenemos el código

public void renderHtml(RenderContext rc, ServerComponentUpdate update, Node parentNode, Component component) {
Document doc = rc.getServerMessage().getDocument();
Element hrE = doc.createElement(“hr”);
hrE.setAttribute(“id”, ContainerInstance.getElementId(component));
parentNode.appendChild(hrE);
}

Este sencillo elemento de representación simplemente crea una instancia de org.w3c.dom.Element con la etiqueta de nombre hr. Luego fija el id de la etiqueta XHTML con un valor único que identifica al componente. El resultado en la red de todo esto es que se genera el siguiente XHTML

<hr id=”c_1234″ />

Sin embargo realmente ocurren muchas cosas por detrás. Los objetos RenderContext y ServerComponentUpdate mantienen una gran cantidad de información que puede ser importante para tu elemento de representación. Estos permiten realizar “trucos” como la actualización parcial y cosas por el estilo. Para dejar las cosas sencillas de momento no los usaremos.

Ahora veamos el método renderAdd. Aquí es donde ocurre la “magia” realmente

public void renderAdd(RenderContext rc, ServerComponentUpdate update, String targetId, Component component) {
Elemnt domAddElement = DomUpdate.renderElementAdd(rc.getServerMessage());
DocumentFragment htmlFragment = rc.getServerMessage().getDocument().createDocumentFragment();
renderHtml(rc, update, htmlFragment, component);
DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, targetId, htmlFragment);
}

Lo que hace esto es crear una directiva de mensaje XML especial que informa al motor del lado cliente de Echo2 que queremos añadir XHTML al DOM.

Esto se realiza mediante el siguiente código Java

Element domAddElement = DomUpdate.renderElementAdd(rc.getServerMessage());

Si miramos más a fondo en la clase DomUpdate veremos cómo crear una sección especial en el documento XML que será interpretada en el navegador cliente por el motor AJAX de Echo2.

Luego se llama a este código

DocumentFragment htmlFragment = rc.getServerMessage().getDocument().createDocumentFragment();
renderHtml(rc, update, htmlFragment, component);

La primera línea crear un objeto contenedor especial llamado DocumentFragment en el DOM w3c. Se trata de un objeto marcador especial que no genera XML pero que permite las relaciones de padre/hijo en una estrucutra DOM.

La segunda línea llama a nuestro método renderHtml utilizando el fragmento de documento como nodo padre. Se generará el XHTML <hr id="c_1234" />.

DomUpdate.renderElementAddContent(rc.getServerMessage(), domAddElement, targetId, htmlFragment);

La última línea añade el XHTML generado al mensaje XML que se enviará al motor AJAX de Echo2 del navegador cliente.

Echo2 “agrupará” varias actualizaciónes de componententes y los pondrá en un mensaje XML para enviarlos al navegador cliente. Esto es así por motivos de rendimiento. Por ejemplo, la pulsación de un botón podría resultar en la modificación de 10 componentes. Las 10 actualizaciones se enviarán de vuelta en una unica interacción XML servidor/cliente.

Cuando el motor AJAX de Echo2 del cliente recibe este mensaje XML añadirá nuestro XHTML en el lugar correcto del DOM cliente.

Actualizando XHTML en el DOM cliente

Imaginemos que cambia una propiedad en nuestro componente RulerLine. Echo2 sabe que el componente ya está representado en el navegador cliente así que no lo volverá a añadir. En su lugar, detectará este cambio de propiedad y llamará al método renderUpdate.

Así, tenemos la oportunidad de actualizar la representación del componente en el cliente. Sin embargo como es un componente sencillo no aprovecharemos las maravillas de la “actualización parcial” sino que lo que haremos será eliminar el componente y volverlo a añadir. Este es nuestro sencillo mecanismo de “actualización”. Posteriormente añadiremos soporte para actualizaciones parciales.

Veamos el método

public boolean renderUpdate(RenderContext rc, ServerComponentUpdate update, String targetId) {
DomUpdate.renderElementRemove(rc.getServerMessage(), ContainerInstance.getElementId(update.getParent()));
renderAdd(rc, update, targetId, update.getParent());
return false;
}

La primera línea crear un mesaje de directiva XML que se utilizará para indicar al motor AJAX del cliente que elimine un cierto elemento DOM por id.

Ahora, si te fijas, verá que el id que aparece aquí no es el id de nuestro componente RulerLine sino un componente devuelto usando update.getParent().

Bien, realmente eso no está bien. El método getParent() no tiene demasiado sentido. El padre en este caso es el componente en cuestion (RulerLine) y se llama padre (parent) porque puede haber tenido componentes hijos modificados. Seguramente hubiese sido mejor llamar a este método algo así como getTargetComponent() para evitar confusiones.

Así que al final, lo que vemos es que el elemento con nuestra id será eliminado del DOM.

La segunda línea llama al método renderAdd() de nuevo para añadir el nuevo XHTML para el RulerLine ya que ya habrá sido eliminado. Este es el modo más sencillo de actualizar la represencitación de un componente en el lado cliente, la llamada estrategia de eliminar/re-añadir.

El framework Echo2 es muy cuidadoso en cuanto al orden en el que procesa estos mensajes de directiva XML. Las eliminaciones simpre se realizan antes que la adiciones.

Eliminando XHTML del DOM cliente

Para nuestro sencillo component no tenemos que hacer nada. Echo2 conoce el id del componente en el DOM y por tanto puede “eliminarlo” enviando un mensaje de directiva XML por nosotros.

Sin embargo, si necesitamos limpiar alguna cosa se invoca al método renderDispose(). En nuestro caso nosotros no hacemos nada sin embargo lo podríamos utilizar para enviar directivas XML especiales para limpiar los recursos del lado del cliente tales como manejadores de eventos y demás.

public void renderDispose(RenderContext rc, ServerComponentUpdate update, Component component) {
// no tenemos que hacer nada
}

Vía

2 Responses to “Componentes personalizados en Echo2 – Parte I”


  1. […] Componentes personalizados en Echo2 – Parte I […]


  2. […] Componentes personalizados en Echo2 – Parte I […]


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: