Tiles en Struts
domingo, septiembre 1, 2002 at 2:00AM Tiles en Struts
Este articulo es una traducción del original de Prakash Malani publicado
en javaworld.com.
La traducción esta realizada por Pedro del Gallego Vida.
Introducción
Normalmente el desarrollo de una aplicación Web, el grupo responsable de
la interfaz de usuario (UI) crea el Look and Feel (L&F) del sitio. Basandose
en el Look and Feel, este grupo crea paginas HTML que representan la
funcionalidad de la aplicación y la forma de navegar. Con una implementacion
basada en Servlet y JavaServer Pages(JSP), donde las paginas HTML son
convertidas en servlet y JSP, los diseñadores de UI, indentificaron
componentes HTML y JSP comunes, como la cabecera (Header),el cuerpo (Body),
el pie de pagina (Footer), el menu, y la busqueda(Search).Este articulo
presenta varias soluciones para una efectiva y eficiente organización de los
componentes de vista (component view). Se evaluara cada solución siguiendo
una serie de criterios especificos detallados mas adelante.
Para explorar las soluciones de plantillas (templates) y de
Layout(esquemas), usaremos el framework Tiles. El "framework Tiles component
view" es conodido como tiles. Este framework usa un archivo de configuración
para estos tiles. Este framework no solo te permite reusar tiles, sino que
tambien que permite organizar layouts
Para explorar las soluciones mas poderosas y flexibles, investigaremos la
integracion entre Tiles y Struts.Struts es un framework open source para
desarrolar aplicaciones web usando el famoso modelo MVC
(modelo-vista-controlador), el modelo 2 de los patrones de arquitectura.
Struts viene con un conjunto amplio de etiquetas reutilizables, el cual es
perfeccionado por la libreria de etiquetas de Tiles.
Criterio de evaluación.
Evaluaremos cada una de las soluciones basándonos en los siguientes
criterios, los criterios no son mutuamnete excluyentes.Para una situación
específica y una aplicación en particula deberemos elegier enter los pros y
los contras de cada soución con respecto a estos factores.
Número de páginas.
La solución debe esforzarse por reducir el numero de páginas the HTML y
JSP.El numero de páginas incrementa la complejidad de desarrollo, de
administración y mantenimiento de la aplicación de una manera drástica.
Repetición de código.
Casi siempre repetir es malo. Cuanto mas código repetido mas díficil es la
tarea de desarrollar y mantener la aplicación.Un siple cambio puede
desencadenar una serie de cambios en cascada en muchas páginas diferentes
con consecuencias imprevisibles.Una manera prática de lograr reusabilidad es
eliminando código repetido.
Control del Layout.
Si repetir código es malo, repetir la logica de layout y código es
peor.Esparcir la logica y el comportamineto de los componentes de la vista
ataves de muchas JSP puede ser la receta para un desastre.Lograr reusar la
la plantilla y la logica de de los layout es una forma de reusar, mejor que
solo reusar componentes de vista.
Acoplamiento
El acoplamiento es el grado de interacción entre entidades.Los ingenieros
de software han pensado una y otra vez sobre como minimizar el acoplamiento
entre clases no relacionadas, paquetes y demas. Nosotros podemos aplicar los
mismos principios a los componentes de vista.
Complejidad
La complejidad aumenta la díficultad de desarrollo y mantenimiento,
haciendo la solución mas compleja menos satisfactoriaLa complejidad crece
rapido y lo que parecia una solución sencilla se torna rapidamente en un
gran enredo teniendo que añadir mas piezas.
Soluciones
Evaluaremos varias soluciones usando ejemplos basicos de JSP con
componentes de vista comunes, como cabecera y piede pagina.Presentaremos
estas soluciones segun el orden de complejidad, y despues las analizaremos
segun cada uno de las criterios de de evaluación
Solución 1
Considere el siguiente JSP : a.jsp
<html>
<body>
Header
<p>
a's body...
<p>
Footer
<p>
</body>
</html>
y el siguiente b.jsp
<html>
<body>
Header
<p>
b's body...
<p>
Footer
<p>
</body>
</html>
En muchos casos los desarrolladores obtienen el codigo de de los diseñadores
de UI y lo convierten literalmente en JSP, Como podemos ver arriba tenemos
las cabecera y los pie de pagina repetidos.La solución 1 no es deseable por
que cambios en un copmonente de vista requiere cambios de en cada una de
las paginas. cada una de las paginas es responsable de colocar (laying out)
sus componentes de vista.Esta solución simple carece de previsión.Con mucho
HTML y JSP repetido, reducimos el el numero de páginas pero a costa de un
pesado coste de mantenimeinto.
Solución 2
considere el JSP a.jsp
<html>
<body>
<%-- include header --%>
<jsp:include page="/header.jsp" />
a's body...
<p>
<%-- include footer --%>
<jsp:include page="/footer.jsp" />
</body>
</html>
considere el JSP b.jsp
<html>
<body>
<%-- include header --%>
<jsp:include page="/header.jsp" />
b's body...
<p>
<%-- include footer --%>
<jsp:include page="/footer.jsp" />
</body>
</html>
Note como componentes comunes, como la cabecera y el pie de página, son
divididos usando el mecanismo JSP include
Considere este header.jsp:
Header
<p>
Considere este footer.jsp:
Header
<p>
La solución 2 soluciona algunas de las limitaciones mayores de la
solución 1.Solo se necesita cambiar los componentes de vista comunes una
vez, por tanto, esta solución elimina la duplicidad de código y simplifica
el mantenimiento.Esta solución incrementa un poco el numero de páginas, pero
reduce drásticamentte el numero el firme acoplamiento entre componentes de
vistas y otras páginas.Esta solución es simple y es usaa en muchos
aplicaciones reales, sin embargo tiene un inconveniente, si cambiamos el
layout de la aplicación, tendremos que hacerlo en cada página.lo que se
supone un caro y prohibitivo cambio.Esta solución alcanza la reutilización
de componentesŽ, pero no de las plantillas y dela logica de layout.
Solución 3.
considere a.jsp:
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
a's body...
<p>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
y b.jsp:
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
b's body...
<p>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
La solución 3 usa el mecanismo insert de Tiles, usando esto incluinos el
componente de vista en el sitio correspondiente.En todo los aspectos esta
solución es identica a la solución 2, con sus ventajas y sus desventajas.
Solución 4 Separando el cuerpo
considere el JSP a.jsp
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
<%-- include body --%>
<tiles:insert page="
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
y este otro b.jsp:
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
<%-- include body --%>
<tiles:insert page="bBody.jsp" flush="true"/>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
Esta solución separa el nucleo del cuerpo en su página individual
aBody.jsp y bBody.jsp
vea el JSP aBody.jsp:
a's body...
<p>
vea el JSP bBody.jsp:
b's body...
<p>
Esto limita el cambio del cuerpo a su página y ademas permite reutilizarlo
en otras partes.Eliminando la repetición y la duplicidad.Como las otras
soluciones, cada pagina crea todavía su propio layout. Por tanto aqui tampco
tiene una política sobre los layout o esquemas.
Solución 5 Plantillas
Usando la característica de crear plantillas podemos definir los Layouts
como plantillas.Dede estos layouts, podemos insertar marcadores de lugar en
vez del actual componente de vista usando la etiqueta de Tiles insert.Así
para todos los componentes esta página define un layout reutilizable.
vea este jsp layout.jsp
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert attribute="header"/>
<%-- include body --%>
<tiles:insert attribute="body"/>
<%-- include footer --%>
<tiles:insert attribute="footer"/>
</body>
</html>
Otras paginas de contenido, como a.jsp y b.jsp ussaran el layout anterior
para situar los componentes de vistas.En las paginas actuales insertamos los
componentes usando la etiqueta Tiles insert, Usuando la etiquea Tiles put,
podemos especificarel componente de vista actual para todos los marcadores
de lugar.
Considere a.jsp:
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<tiles:insert page="/layout.jsp" flush="true">
<tiles:put name="header" value="/header.jsp"/>
<tiles:put name="body" value="/aBody.jsp"/>
<tiles:put name="footer" value="/footer.jsp"/>
</tiles:insert>
Considere b.jsp:
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<tiles:insert page="/layout.jsp" flush="true">
<tiles:put name="header" value="/header.jsp"/>
<tiles:put name="body" value="/bBody.jsp"/>
<tiles:put name="footer" value="/footer.jsp"/>
</tiles:insert>
La mayor ventaja de esta solución es que encapsula el comportamiento del
layout, reduce drasticamente el acoplamiento del entre los componentes. Sin
embarfo incrementa la complejidad introduciendo otra página para el
layout.Entender y implementar el mecanismo de de las plantillas tambíen
puede ser díficil al principio.
Solución 6 Struts y Tiles
La página de layout anterior layout.jsp contiene código HTML y JSP para
organizar los componentes.La páginas a.jsp y b.jsp no contiene código HTML
ninguno; estas solo contienen etiquetas Tiles para insertar los componentes
necesarios.No seria agradable especificar todos las páginas de contenido en
un solo archivo XML de configuración?
LLamaremos a este archivo tileDefinitions.xml y especificara las páginas
como:
<?xml version="1.0" encoding="ISO-8859-1"?>
<component-definitions>
<definition name="aDef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value="/aBody.jsp"/>
</definition>
<definition name="bDef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value="/bBody.jsp"/>
</definition>
<definition name="cDef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value="/cBody.jsp"/>
</definition>
</component-definitions>
La solución 6 elimina todas las páginas de contenido a.jsp, b.jasp...
poniendo sus definiciones en un archivo XML. Pero si no existe un recurso
llamado a.jsp, como podemos solicitarlo? Y mas importante como podemos
acceder al archivo XML tileDefinitions.xml.La integracion entre Strust y
Tiles lo permite. Ademas la configuración uniforme de parametros de Struts,
nos permitira especificar el archivo de configuración como otro parametro en
el web.XML, como mostramos abajo. Especificando el parametro
definition-config posibilita a Struts encontrar y conocer acerca de la
definición Tiles.
<!-- Standard Action Servlet Configuration (with debugging) -->
<servlet>
<servlet-name>action</servlet-name>
<!--
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
-->
<servlet-class>
org.apache.struts.tiles.ActionComponentServlet
</servlet-class>
<init-param>
<param-name>definitions-config</param-name>
<param-value>
/WEB-INF/tileDefinitions.xml
</param-value>
</init-param>
...
<!-- Mapeado Estandard del Action Servlet -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
...
</servlet>
ahora definimos una acción Struts, la cual devuelve una definición
especifica del archivo de configuración con el valor éxito
package com.malani.struts.action;
import org.apache.struts.action.*;
import javax.servlet.http.*;
public class DoFirst extends Action {
public ActionForward perform(
ActionMapping aMapping,
ActionForm aForm,
HttpServletRequest aRequest,
HttpServletResponse aResponse
) {
return aMapping.findForward("success");
}
}
No podemos invocar un definición directamente desde el navegador, pero
puedes invocar una desde Struts, como si esta fuese un recurso
actual.Definimos las acciones struts en el archivo struts-config.xmlcomo
vemos abajo.
<action path="/a" type="com.malani.struts.action.DoFirst">
<forward name="success" path="aDef"/>
</action>
<action path="/b" type="com.malani.struts.action.DoFirst">
<forward name="success" path="bDef"/>
</action>
<action path="/c" type="com.malani.struts.action.DoFirst">
<forward name="success" path="cDef"/>
</action>
Ahora invocamos la acción Struts solicitando a.do y b.do respectivamente
para devolvernos el recurso deseado.
La solución 6 tiene la ventaja de establecer todas las definiciones en un
archivo de configuración XML, reduce el numero de páginas. Pero al
introducir Struts aumenta notablemente el grado de complejidad.
Solución 7 Herencia en Tiles.
En el aarchivo de configuración que todas las definiciones de las páginas
son parecidas. Estas definen tres componentes , cabecera cueropo y pie de
página, de las cuales dos de ellas (la cabecera y el pie de página) son
siempre iguales. Una poderosa caracteristica de Tiles es la herencia entre
definiciones. Por tantopodemos crear una definición base y dejoar que las
demas hereden de esta.La definición base solo debe suministrar la
características. La definición hija solo debe definir sus componentes
unicos.Enseñaremos el siguiente codigo para observar como se usa la herencia
en el archivo de configuración XML.
<?xml version="1.0" encoding="ISO-8859-1"?>
<component-definitions>
<definition name="baseDef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value=""/>
</definition>
<definition name="aDef" extends="baseDef">
<put name="body" value="/aBody.jsp"/>
</definition>
<definition name="bDef" extends="baseDef">
<put name="body" value="/bBody.jsp"/>
</definition>
<definition name="cDef" extends="baseDef">
<put name="body" value="/cBody.jsp"/>
</definition>
</component-definitions>
Esto elimina parte del codigo repetido.
Resumen de soluciones
La siguiente tabla resume las distintas soluciones y sus caracteristicas
respecto a cada uno de los criterios de evaluación, existen mas criterios
como la extensibilidad, la mantenibilidad o el rendimiento.
Solution Paginas Repeticion LayoutControl Acoplamiento Complejidad
1: Basic * *** * *** *
2: include ** ** * ** *
3: insert ** ** * ** *
4: separar *** ** ** ** **
5: Plantillas *** * *** * **
6: S. & Tiles ** * *** * ***
7: T Herencia ** * *** * ***
Escala: Alto: *** Medio: ** Bajo: *
Observamos que el grado de complejidad va creciendo segun avanzamos en
las soluciones, al igual que el control del layout, sin embargo tanto la
repeticioón de código como el acoplamiento desciende.
Que solución es la mejor?
La mejor solución depende de las necesidades del proyecto y sus
reqerimientos y de tus habilidades y conocimientos en el desarrollo y
mantenimiento de aplicaciones web. La solución basica es demasiado simple.No
es recomendable porque va en contra de los principios de las buenas
practicas de la ingeniería del software, Si ya estamos usando Struts
entonces podremos aprvecharnos de la infuencia del la integración de Tiles y
Struts, para crear una poderosa solución.
Resumen
En este articulo, hemos examinado varias soluciones para organizar
componentes de vista en HTML y JSP. Hemos explorado la unión entre Tiles y
Struts. Estas estrategias y soluciones pueden ayudarnos a hacer un tomar
decisiones arquitectonicas con respecto a nuestras aplicaciones Web.
|
j2ee 
Reader Comments