You may not be happy with the way Roo lays out your web application, and you proba
bly have designs on better layouts, localization, and perhaps a set of themes. No mat
ter: you are in complete control of that as well. In this section we’ll tell you how to prepare your application for localization, how to set up different themes, and how to adjust your layouts.
6.3.1 How Roo resolves scaffold labels
Spring Roo automatically builds support for localized user interfaces. In fact, every scaffolded text element is fetched either from the database (via the entities) or via locale-aware properties files such as application.properties and messages.properties.
Here’s how Roo identifies and renders various elements on the page:
Table names —When Roo renders a scaffolded entry page for a given entity, it uses labels such as “Find by entityName” and “Create new entityName.” This name is held in application.properties under the value label_ appended with the lowercased, fully qualified class name (including package). In the example, it would be label_org_distracted_tracker_model_course. If you’d like to change the way your entity is described, you can modify this file.
Column names —Column names are also stored within the application .properties file in the same way as the singular and plural entity names (the field is appended to the end of the preceding label).
Error messages —Error messages are stored in messages.properties and can be customized to suit.
Remember, Roo won’t overwrite the tag libraries or layouts it creates, but it will attempt to keep fields in sync.
Now, armed with the knowledge of how Roo resolves messages, let’s dig into localization.
6.3.2 Configuring additional locales
Roo supports any valid locale in the WEB-INF/i18n directory. The icons placed in the footer.xhtml file of your standard layouts are automatically generated if you issue the web mvc language command. For example, to configure Spanish, issue
roo> web mvc language --code es
Roo responds by adding a new locale file, messages_es.properties, and configuring it with all standard Roo messages relating to the default layout and features. It will be your responsibility to copy your application.properties file to application_es .properties and translate the field labels and messages to the proper locale. Because all files are mounted in this directory, you don’t need any additional configuration.
Roo also copies an icon for the language flag into the webapp/images directory, and updates the footer to allow you to click on that image to switch locales. You can
also manually switch locales for your browser session using the lang query string parameter. For example, to translate the site to Spanish, you can issue
http://localhost:8080/coursemanager?lang=es
By default this setting is kept in an in-memory browser cookie. If you’d like to make it more permanent, you can switch from the default CookieLocaleResolver to the SessionLocaleResolver. You can store and reload the session for each user from a data store if you wish. You can also use the AcceptHeaderLocaleResolver to automat
ically detect the locale based on the browser’s reported language.
See chapter 11 for details on how to create other language locales by writing an add-on.
Now that we’ve talked about the mechanics of rendering the page contents, we’re ready to discuss page layout concepts. Roo uses Apache Tiles to provide a composite view: a view composed of various individual parts. In this section we’ll take a look at just how Roo works with localized property files; the configuration of Apache Tiles in a Roo application; how you can define page layouts via tiles definitions; and then how to customize individual elements of the Roo layout.
6.3.3 Tiles and Roo
Remember that we told you‚ back in chapter 5‚ to ignore the views.xml files? Although Spring Roo view files are rather small, Roo ends up rendering complex views, com
plete with a menu system, header, footer, and content areas. Tiles does this work for you transparently. It’s installed as a special view resolver, a strategy object that resolves names of views returned by controllers to physical files and other resources. Here’s the TilesViewResolver, defined by Roo in WEB-INF/webmvc-config.xml:
<bean
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layouts/layouts.xml</value>
<!-- Scan views directory for Tiles configurations -->
<value>/WEB-INF/views/**/views.xml</value>
</list>
</property>
</bean>
TilesViewResolver processes view names, emitted in the controller, and attempts to find layout definitions within configuration files specified in the definitions property.
The main layout definitions file, layouts.xml, is what tells Roo about the two main layouts—default and public, as shown in the following listing.
Listing 6.1 Top-level tiles defined in WEB-INF/layouts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN"
169 View layouts, theming, and localization
"http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
<tiles-definitions>
<definition name="default"
template="/WEB-INF/layouts/default.jspx">
<put-attribute name="header"
value="/WEB-INF/views/header.jspx" />
<put-attribute name="menu"
value="/WEB-INF/views/menu.jspx" />
<put-attribute name="footer"
value="/WEB-INF/views/footer.jspx" />
</definition>
<definition name="public"
template="/WEB-INF/layouts/default.jspx">
<put-attribute name="header"
value="/WEB-INF/views/header.jspx" />
<put-attribute name="footer"
value="/WEB-INF/views/footer.jspx" />
</definition>
</tiles-definitions>
In the previous example, each layout is given a physical file that defines the contents of the layout, and values to substitute for various tiles within that file, such as header, footer, and menu.
6.3.4 Roo’s tile layouts
Hang in there, though: Tiles loves levels of indirection! That’s why you can create a number of layouts, assigning them to views, rather quickly by extending or modifying layouts. There are two layouts defined in this file:
default—The standard layout used by most pages in Roo. This includes a header, footer, and menu.
public—The layout used by pages that don’t require a menu bar. This layout gives users a larger amount of screen real estate.
Let’s take a look at the default layout, as defined by WEB-INF/layouts/default.jspx, shown next.
Listing 6.2 The default layout—default.jspx
<html
xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:tiles="http://tiles.apache.org/tags-tiles"
xmlns:spring="http://www.springframework.org/tags"
xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" >
Install taglibs
B
<jsp:output doctype-root-element="HTML"
doctype-system="about:legacy-compat" />
HTML5 compatibility
C
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=8" />
Header defines layout, CSS, JavaScript
Load JavaScripts D
Menu tile
Footer tile
6.3.5
<util:load-scripts /> IE 8
support <spring:message code="application_name" var="app_name"/>
<title>
<spring:message code="welcome_h3" arguments="${app_name}" />
</title>
</head>
<body class="tundra spring">
<div id="wrapper">
Header <tiles:insertAttribute name="header" ignore="true" /> tile
<tiles:insertAttribute name="menu" ignore="true" />
<div id="main"> Body
<tiles:insertAttribute name="body"/> tile
<tiles:insertAttribute name="footer" ignore="true"/>
</div>
</div>
</body>
</html>
This layout defines a very comprehensive page structure, including features such as HTML5 compatibility C, JavaScript and CSS support, the Dojo widget library, DCSS, and preinstalled tag libraries B. The template also includes a set of div elements, each of which defines areas that can be rendered with content at runtime.1
Figure 6.3 shows the layout divs, styled by Roo’s generated stylesheet, in a simple block diagram.
Tiles inserts the content defined in these div elements when it sees the <tiles:insert- Attribute /> tag. For example, in the line
<tiles:insertAttribute name="header
" ignore="true" />
the actual content will be replaced by the file referenced in the attribute header, which is defined in the layouts.xml file:
<put-attribute name="header
" value="/WEB-INF/views/header.jspx" />
Putting it all together
header.jspx
menu.jspx
Your view content
footer.jspx
Figure 6.3 JSPX files involved in the Tiles
At this point, you’re probably wondering just layout process. These files are located in /
how the heck this information is relevant to web-app/WEB-INF/views.
To find out more about Internet Explorer’s support for various modes, see http://mng.bz/jQou.
1
View layouts, theming, and localization 171 you. Yep, you’re right—Tiles is maddeningly distributed. Careful readers also will notice that the attribute for the page content itself isn’t being passed to the defini
tions. So how in the world does it know about the page? Ah, that’s because the crux of the whole matter is that views.xml file in your WEB-INF/views/testdrive directory:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE tiles-definitions PUBLIC " ...
<tiles-definitions>
<definition extends="default" name="throwaway/index">
<put-attribute name="body"
value="/WEB-INF/views/throwaway/index.jspx"/>
</definition>
</tiles-definitions>
Hopefully this is your Tiles eureka! moment... Finally, you see that the layout named default will be used to render the throwaway/index page. The header, footer‚ and menu tiles will be loaded from files based on the settings in WEB-INF/layouts, and the body tile will be loaded using the index.jspx file in the views/throwaway directory.
6.3.6 Customizing the tiles layout engine
You can modify the content in any of these tiles just by changing the view files. Here are a few suggestions for quick modifications you can do:
Add a copyright entry to the footer of every page by editing footer.jspx and add
ing a fragment such as <em>© 2010 Course Management Incorporated</em> in an appropriate place.
Add a menu item for nonscaffolded controllers or views: just edit menu.jspx and add a <menu:item>‚ or if you want to add a menu category (boldfaced headings before groups of related menus) add a <menu:category> element.
Read the documentation at the top of the menu.tagx, category.tagx, and item.tagx files for details.
Change the header to incorporate your logo. Just edit and replace the logo file
name in the banner URL within the header.jspx file. The banner dimensions are 800 pixels long by 75 pixels deep if you would like to develop a drop-in replacement.
Then again, why not completely replace the entire layout? Just modify your tiles layout and related CSS files, and go to town. Realize that there are key elements to the vari
ous tag libraries generated by Roo, so you’ll have to take care and follow Roo’s vari
able naming conventions in order for the Roo-generated components to function.
6.3.7 Theming
Roo also supports the concept of theming, which is closely related to layouts. Two themes are installed: standard and alt. If you look closely at the footer of each Roo page in a web browser, you’ll see two clickable links for these themes. When you click on one of these, Roo uses Spring’s theming support to switch a simple client-side HTTP cookie named theme between the values of standard and alt.
A little too complex for this book, theming boils down to special properties files, stored in WEB-INF/classes in the web application, for each theme. Roo uses a special generated tag, theme.tagx, to generate these links, and the theme resolver accepts clicks to these links, which sets the cookie value for the browser. Each time the browser renders a page, it passes the theme name in a cookie to Spring. Spring accepts it, and the CSS file pointed to in the standard.properties or alt.properties files is used to mount a different stylesheet.
The upshot for you is that you can style two different themes. Currently, the only difference between the CSS layouts is the position of the menu: standard layout puts the menu on the left, and the alternative one puts it on the right. Feel free to custom
ize standard.css and alt.css to suit your needs.