Mostrando entradas con la etiqueta tiles. Mostrar todas las entradas
Mostrando entradas con la etiqueta tiles. Mostrar todas las entradas

miércoles, 19 de enero de 2011

Propagar atributos en tiles

Una vez que estamos configurando nuestra plantilla de tiles mediante xml se nos puede presentar la necesidad de utilizar atributos dentro de una jsp que se está visualizando mediante un <tiles:insertAttribute />. Voy a poner un ejemplo para que se entienda mejor el caso:

En nuestro fichero tiles-def.xml tenemos el siguiente definition:












El main.jsp tiene el siguiente contenido:


<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
....





Hasta aqui nada raro. Pero, ¿Qué pasa si dentro del header queremos utilizar el atributo menu? header.jsp:


<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>

<img src="<%=request.getContextPath()%>/images/logo.png" />



Si ejecutamos esto nos dara una excepción NoSuchAttributeException, quejándose de que no existe el atributo 'menu'. ¿Qué soluciones tenemos?

La primera opción que se me ocurre y seguramente sea la más elegante es reordenar un poco la definición que tenemos dejándola de la siguiente manera:














Y el main.jsp quedaría:


<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
....





Si esta solución no os convence y no podeis separar la definición existente en dos (como me ha ocurrido recientemente) se puede hacer lo siguiente:

Primero, exponer todos los atributos de la definición como atributos de la request dentro del main.jsp:


<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
....








Después modificamos el header para que, en vez de utilizar el <tiles:insertAttribute/>, se use el <jsp:include/>:


<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>

<img src="<%=request.getContextPath()%>/images/logo.png" />



No me gusta nada esto de tener que utilizar el requestScope y jsp:includes directamente y en mi opinión tiene que haber otra forma de hacerlo más
elegante, pero estuve investigando un poco y no encontré nada. Como esto funciona no le dí muchas más vueltas jeje.

lunes, 18 de octubre de 2010

Integración Spring MVC con Tiles

En el siguiente post voy a explicar los pasos necesarios para realizar una integración sencilla de Spring MVC con Tiles.

El objetivo de esta integración es que automáticamente se aplique una plantilla a una vista sin necesidad de que se tenga que definir en el fichero tiles-def.xml cada vez. Dependiendo de la url con la que se invoque a la aplicación se ejecutará una u otra-

Por ejemplo:
- http://server/appname/player/home --> Cómo la url empieza por /player automáticamente cogerá la plantilla de tiles para los jugadores
- http://server/appname/crm/home --> Cómo la url empieza por /crm automáticamente cogerá la plantilla de tiles para los usuarios del CRM.

Para hacer esto me he basado en el siguiente tutorial: Spring by Example's Dynamic Tiles 2 Spring MVC Module. Recomiendo la lectura de este enlace, ya que voy a extender la funcionalidad que se explica ahí.

Lo primero que tenemos que hacer es importar las librerías necesarias mediante Maven:



springbyexample.org
Spring by Example
http://www.springbyexample.org/maven/repo


....


org.apache.tiles
tiles-core
2.2.1


org.apache.tiles
tiles-jsp
2.2.1


org.apache.tiles
tiles-servlet
2.2.1


org.apache.tiles
tiles-servlet-wildcard
2.2.1


org.apache.tiles
tiles-el
2.2.1


org.springbyexample
org.springbyexample.dynamic.tiles2
1.2


org.springframework
org.springframework.beans


org.springframework
org.springframework.web


org.springframework
org.springframework.context


org.springframework
org.springframework.context.support


org.springframework.webflow
org.springframework.webflow


org.apache.tiles
com.springsource.org.apache.tiles.core


org.apache.commons
com.springsource.org.apache.commons.digester


org.apache.commons
com.springsource.org.apache.commons.beanutils


org.apache.commons
com.springsource.org.apache.commons.logging


org.apache.tiles
com.springsource.org.apache.tiles


org.springframework
org.springframework.core


org.springframework
org.springframework.web.servlet


org.springframework.webflow
org.springframework.js





Después de esto hay que definir en los ficheros de configuración de Spring para que se cojan las definiciones de tiles de su fichero correspondiente:



class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">


/WEB-INF/tiles-def.xml





Dentro de este fichero 'tiles-def.xml' configuramos las dos plantillas que queremos utilizar:



"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">

























Vamos a crear una nueva clase en nuestro proyecto que extienda la funcionalidad que nos proporciona 'springbyexample'. En este caso vamos a prepararlo para que dependiendo de la ruta de la vista a la que vayamos a llamar se invoque a una plantilla o a la otra. La clase en cuestión es la siguiente:



public class ViewNameStartTilesUrlBasedViewResolver extends org.springbyexample.web.servlet.view.tiles2.TilesUrlBasedViewResolver{

private String viewNameStartsWith = "";

@Override
protected boolean canHandle(String viewName, Locale locale) {
if (viewName.startsWith(viewNameStartsWith)){
return super.canHandle(viewName, locale);
}
return false;
}

public void setViewNameStartsWith(String viewNameStartsWith) {
this.viewNameStartsWith = viewNameStartsWith;
}

}



Después definimos dos beans en Spring que se encarguen de evaluar si se tiene que ejecutar una plantilla o la otra.



class="com.example.ViewNameStartTilesUrlBasedViewResolver">
value="org.springbyexample.web.servlet.view.tiles2.DynamicTilesView">








class="com.example.ViewNameStartTilesUrlBasedViewResolver">
value="org.springbyexample.web.servlet.view.tiles2.DynamicTilesView">










Tal y como hemos configurado esto, cada vez que Spring devuelva una vista, se ejecutará primero la comprobación de si la vista empieza por "player/". En caso de que así sea se ejecutará la plantilla '.playerMainTemplate'. Si no es así se evaluará a ver si empieza por 'crm/' y se ejecutaría su plantilla correspondiente.

Otra cosa a tener en cuenta es donde se tiene que encontrar la jsp para que la vista se ejecute correctamente. Si Spring MVC devuelve una vista con valor 'player/account/home', se buscará una jsp en la ruta: 'WEB-INF/jsp/player/account/home.jsp' automáticamente, sin necesidad de que lo definamos nosotros en tiles-def.xml.