UrlBasedViewResolver and Apache Tiles2 in Spring 3 - spring

I've got the following exception while trying to open the URL http://localhost:8080/app/clientes/agregar:
javax.servlet.ServletException: Could not resolve view with name 'clientes/agregar' in servlet with name 'Spring MVC Dispatcher Servlet'
My mvc-config.xml is the following:
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions" value="/WEB-INF/tiles/tiles.xml" />
</bean>
My simple tiles.xml:
<definition name="mainTemplate" template="/WEB-INF/template/template.jsp">
<put-attribute name="titulo" value="Simple Tiles 2 Example" type="string" />
<put-attribute name="header" value="/WEB-INF/template/header.jsp" />
<put-attribute name="footer" value="/WEB-INF/template/footer.jsp" />
</definition>
<definition name="*" extends="mainTemplate">
<put-attribute name="content" value="/WEB-INF/views/{1}.jsp" />
</definition>
When I try to open locations under /app it works fine, like /app/welcome or /app/clientes, but this error appears when trying to open /app/clientes/something. I guess it has something to do with the URL Resolver, but I can't find what...
My ClientesController class, annotated with #Controller has a method like the following:
#RequestMapping(method = RequestMethod.GET, value = "agregar")
public void agregar() { ... }
My JSP view files are located under /WEB-INF/views like:
/WEB-INF/views
-- /clientes
---- agregar.jsp
-- welcome.jsp
-- clientes.jsp
Thanks!

Added the following in my tiles.xml and works fine:
<definition name="*/*" extends="mainTemplate">
<put-attribute name="content" value="/WEB-INF/views/{1}/{2}.jsp" />
</definition>
Any better (more flexible) solution?

<definition name="/**" extends="page">
<put-attribute name="content" value="/WEB-INF/jsp/{1}.jsp"/>
</definition>
If you'll get StackOverFlow you should do like this (type="template"):
<put-attribute name="some_name" value="some_page.jsp" type="template"/>

I haven't tested it, but as the documentation says here: tiles wildcards
one asterisk (*) for a single placeholder;
two asterisks (**) to say "in every directory under the specified one";
So try with two asterisks
<definition name="**" extends="mainTemplate">
<put-attribute name="content" value="/WEB-INF/views/{1}.jsp" />
</definition>

Related

Attribute not found on Apache Tiles

I'm using Apache Tiles on a Sprint MVC app and I have this tiles.xml:
<tiles-definitions>
<definition name="defaultLayout" template="/WEB-INF/tiles/template/defaultLayout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/tiles/template/header.jsp" />
<put-attribute name="content" value=""/>
<put-attribute name="footer" value="/WEB-INF/tiles/template/footer.jsp" />
</definition>
<definition name="home" extends="defaultLayout">
<put-attribute name="title" value="Alsa" />
<put-attribute name="content" value="/WEB-INF/pages/home.jsp" />
<put-attribute name="active" value="index" />
</definition>
</tiles-definitions>
What I'm trying to do is use the attribute active to add a class to active menu item. For that I have this in header.jsp:
<%# taglib uri="http://tiles.apache.org/tags-tiles-extras" prefix="tilesx" %>
<tilesx:useAttribute name="active" />
The problem is that everytime I try to render the page I get this error:
org.apache.tiles.template.NoSuchAttributeException: Error importing
attributes. Attribute 'active' is null
What am I doing wrong?
The trick here is to add cascade=true to your attribute so that it will be available to nested definitions and templates.
<definition name="home" extends="defaultLayout">
<put-attribute name="title" value="Alsa" />
<put-attribute name="content" value="/WEB-INF/pages/home.jsp" />
<put-attribute name="active" value="index" cascade="true"/>
</definition>
See:
https://tiles.apache.org/framework/tutorial/advanced/nesting-extending.html
You may need to declare the class. You'll also need id.
<tilesx:useAttribute name="active" id="active" class="java.lang.String"/>
Also if there are other tiles definitions in your app other than "home" and if any of them do not define an "active" attribute, you may want to set "ignore" to true as part of your definition to avoid runtime errors. More here:https://tiles.apache.org/framework/tiles-jsp/tlddoc/index.html

Spring Tiles: Add context information (menu, title)

I am wondering what is the best way to add context information (like the current menu or the title of the page) to spring 3 + tiles 2 app.
I want the system to be as easily extenable as possible, so for example my tiles config uses a wildcards, because I do not want to write a new entry for every new request handler:
<tiles-definitions>
<definition name="baseLayout" template="/WEB-INF/jsp/layout.jsp">
<put-attribute name="title" value="Template" />
<put-attribute name="header" value="/WEB-INF/jsp/header.jsp" />
<put-attribute name="menu" value="/WEB-INF/jsp/menu.jsp" />
<put-attribute name="body" value="/WEB-INF/jsp/content.jsp" />
<put-attribute name="footer" value="/WEB-INF/jsp/footer.jsp" />
</definition>
<definition name="**-tile" extends="baseLayout">
<put-attribute name="title" value="{1}" />
<put-attribute name="body" value="/WEB-INF/jsp/{1}.jsp" />
</definition>
</tiles-definitions>
So I guess the only choice left is to add stuff to the model. I could of course add a new model entry (e.g. MODEL_ID) for every requesthandler, like this:
#RequestMapping(value="/order/{orderId}.x")
public String showOrder(ModelMap model, #PathVariable long orderId) {
// do stuff
model.addAttribute(Context.MODEL_ID, Context.getOrderContext());
}
and then this particular MODEL_ID is interpreted in title.jsp to show a title and in menu.jsp to highlight the current menu item.
However, I do not like the idea of adding those lines to all request methods of all my controllers.
I was thinking about writing an Interceptor which tries to determine the "context" based on the name of the view or requestpath, but then I have to rewrite all URLs in the interceptor and also keep them in sync with the Controllers.
What is the correct or simpliest way to add context info to every controller to use in common tiles?

Tiles 2 Access Variable in Template

I am using the Spring MVC framework with Apache Tiles 2. I want to be able to have multiple controllers all use the same view (different logic, some basic presentation). I can do that easily. What I want now is to have different Tiles definitions for each controller, all using the same JSP file, but each passing different template variables (page header, short description, etc). This is my Tiles template definition file:
<tiles-definitions>
<!-- Default Main Template -->
<definition name=".mainTemplate" template="/WEB-INF/templates/main.jsp">
<put-attribute name="shortTitle" value="Company ABC" type="string" />
<put-attribute name="body" value="/WEB-INF/templates/blank.jsp" />
</definition>
<!-- Overriding Templates -->
<definition name="index" extends=".mainTemplate">
<put-attribute name="title" value="Company Alpha Bravo Charlie" type="string" />
<put-attribute name="body" value="/WEB-INF/views/index.jsp" />
</definition>
<definition name="index2" extends=".mainTemplate">
<put-attribute name="title" value="Company Other Page" type="string" />
<put-attribute name="body" value="/WEB-INF/views/index.jsp" />
</definition>
</tiles-definitions>
I then try to have this /WEB-INF/views/index.jsp:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<h1>
Hello world, it's <tiles:getAsString name="title" />!
</h1>
When I load this into Tomcat and bring up the page, I get a long stack trace of exceptions. The top of the pile says org.apache.tiles.impl.CannotRenderException: ServletException including path '/WEB-INF/templates/main.jsp'.} with root cause org.apache.tiles.template.NoSuchAttributeException: Attribute 'title' not found. Anybody know what's going on?
I then try to have this /WEB-INF/views/index.jsp:
How do you try this? In your controller you would specify the name of the Tiles view, not one of the multiple JSP Tiles will use in order to render the page:
#RequestMapping("index2")
public String index2() {
// ...
return "index2";
}

Spring & Tiles - Get rid of tiles.xml

I have a Tiles template where each page provides a title, some stuff to add in the <head>, stuff to put in some concrete <div>, and stuff to append to <body> after everything else.
Most of those things are very small since the page is rendered with JS.
How can I get rid of tiles.xml or make it more manageable?
I don't want each of the pages to require 3 files:
<definition name="my_page" template="/template.jsp">
<put-attribute name="title" value="My Title" />
<put-attribute name="head" value="/tiles/my-head.jsp" />
<put-attribute name="body" value="/tiles/my-page.jsp" />
<put-attribute name="body-append" value="/tiles/my-append.jsp" />
</definition>
And I don't want to put content of all pages in tiles.xml.
Ideally, it would simply redirect my_page to /my_page.jsp which would import and fill the template by itself.
I'm talking about a Spring app with TilesView.
You can use the tiles JSP tags directly in your JSP. You don't have to use definitions if you don't want to.
In your my_page.jsp:
<tiles:insertTemplate template="/template.jsp" flush="true">
<tiles:putAttribute name="title" value="My Title" />
<tiles:putAttribute name="head" value="/tiles/my-head.jsp" />
... etc
</tiles:insertTemplate>
See http://tiles.apache.org/framework/tiles-jsp/tlddoc/index.html

How to localize page title with Spring and Tiles2?

I have a Spring application which uses Tiles for the view tier. So all my pages definitions look like this:
<definition name="main.page" template="/tiles/layout.jsp">
<put-attribute name="title" value="Page Title"/>
<put-attribute name="header" value="/tiles/header.jsp"/>
<put-attribute name="body" value=""/>
<put-attribute name="footer" value="/tiles/footer.jsp"/>
</definition>
<definition name="welcome.page" extends="main.page">
<put-attribute name="title" value="Main Page"/>
<put-attribute name="body" value="/pages/welcome.jsp"/>
</definition>
The code which sets page title is:
<title><tiles:getAsString name="title"/></title>
I would like to localize with Spring tag:
<spring:message>
Are there any "best practices" how to do that?
Did you ever tried to put the message key in you tiles variable and use it as key for the spring message tag.
Something like that:
<definition name="welcome.page" extends="main.page">
<put-attribute name="titleKey" value="page.main.title"/>
<put-attribute name="body" value="/pages/welcome.jsp"/>
</definition>
jsp:
<set var"titleKey"><tiles:getAsString name="titleKey"/></set>
<title><spring:message code=${titleKey} /></title>
The previous answer contains several little mistakes
tiles.xml
<definition name="main" template="/WEB-INF/jsp/template.jsp">
<put-attribute name="titleKey" value="main.title" />
<put-attribute name="body" value="/WEB-INF/jsp/main.jsp" />
</definition>
jsp (/WEB-INF/jsp/template.jsp)
<c:set var="titleKey"><tiles:getAsString name="titleKey"/></c:set>
<title><spring:message code="${titleKey}"></spring:message> </title>

Resources