Matt RaibleMatt Raible is a Java Champion and Developer Advocate at Okta. developer.okta.com

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

My Tiles to SiteMesh Migration

I spent a few hours last night replacing Tiles with SiteMesh in AppFuse. I had the Struts version done in 2 hours, and most of the Spring version done in an additional hour. Then I spent another 3 hours today twiddling with things and getting it just right. During this process, I discovered a few things I thought I'd share. Keep in mind that I'm pretty much a SiteMesh rookie. Hopefully, implementing and using it in AppFuse will help me to fully understand its power.

  • SiteMesh lacks injection. Tiles allows you to inject JSP fragments into your base layout on a per-page basis. I didn't use this feature much, but I did use it to determine which menu should show up on what pages. For example, the login page would get a "projects used" menu, the signup page wouldn't have a menu, and all other pages would get the standard site menu. With SiteMesh, all of this seems to be done best with JSP includes and some <c:if> logic in your decorator. I ended up using <c:import> in my login.jsp for the login menu, importing nothing for signup, and using <c:if> statements in my decorator to see if the user was logged in. If they were, then I import the site menu and its necessary scripts and styles. In the end, this worked fine and it's probably easier for new AppFuse users to understand - so that's a good thing.
  • Injecting scripts and stylesheets. With Tiles, I was able to easily control which scripts and stylesheets were shown on each page. With SiteMesh, this is pretty easy to do by putting them in the <head> element of your page. However, what I would've really liked to see is the ability to put these in an included JSP and have them end up in the <head> of the final document. I know it's virtually impossible, but it would be cool.
  • Headings. Adding a <title> title element per-page works great using the <title> tag. However, if you want to add a heading (which I specify with an <h1> tag), you have to use a <content> tag. It would be cool if I could somehow use <h1> or <heading> in my page to indicate a heading. I ended up going with the following in each page to specify the title and heading:
    <title><fmt:message key="mainMenu.title"/></title>
    <content tag="heading"><fmt:message key="mainMenu.heading"/></content>
    There's probably an easier way to do this, but this works for now.
  • Injecting <body> ids. Using body ids to set styles on a per-page basis is a great way to control CSS. With Tiles, I set this as an attribute in tiles-config.xml and then grabbed/used it with the following JSTL code:
        <c:set var="bodyId" scope="request">
            <tiles:getAsString name="body.id" ignore="true"/>
        </c:set>

    <body<c:if test="${not empty bodyId}"> id="<c:out value="${bodyId}"/>"</c:if>>
    Yeah, it's ugly, but it works. With SiteMesh, you can easily set a body id by using <body id="name">. In fact, you don't even need to wrap your content with it, you can simpley do <body id="name"/>. I'm grabbing and using this in my decorator with the following code. This works, but it would be cool if I could check for the existence of the attribute first - so I could eliminate id="" when no body id is set.
    <body id="<decorator:getProperty property='body.id'/>">
  • Inheritance. With Tiles, you could extend page definitions and override attributes. This feature seems to be completely lacking in SiteMesh. I don't know how you could implement it, but it would be nice to have something where you could specify the parent - for instance, to use the same <head> content.
  • Error page decoration. SiteMesh seems to be incapable of decorating error pages (i.e. 404) in Tomcat 5.0.x (even if I add <dispatcher>ERROR</dispatcher> to the filter-mapping). A workaround is to use wrap the error page with a <page:applyDecorator> tag. This works, but if you specify elements in <head>, they will end up in the body of page, rather than in the decorator's header.
  • SiteMesh simplifies. Switching from Tiles to SiteMesh allowed me to delete somewhere around 8 JSPs. AppFuse has 34 after committing everything. Most of these were JSPs that sat in the root folder and had a one-liner to pull in a Tiles definition. However, it also eliminated 11 JSPs from the Spring MVC install - allowing reduction of duplication. The Spring MVC install now has 17 JSPs.

So there you have it. AppFuse now uses SiteMesh instead of Tiles! I'm sure the implementation will get cleaner and more refined as more folks use it. I'm looking forward to deleting some chunks out of AppFuse's tutorials because SiteMesh makes page development so much easier. The hardest part of SiteMesh is setting up the infrastructure. Once you're got that done, you hardly ever touch it again.

Next task: WebWork integration.

Posted in Java at Aug 21 2004, 11:50:50 PM MDT 14 Comments
Comments:

  • I don't know what injection in Tiles does, but it sounds like exactly what jsp:include is for....
  • Can't you put the scripts in or jsp:include them in the decorator? The decorator can control the head, etc...
  • You can put the contents of the <title> from the decorated page both into the title of your final page and put it in the page and wrap it in <h1> tags... Not sure if I missed your point
  • For inheritance, you could use the applyDecorator JSP tag to use another decorator within the main decorator... not exacly inheritance, but it might help
Glad to hear Sitemesh is going well... I don't contribute to that project, but I use it and I'm glad to see another OpenSymphony project getting good press....

Posted by Jason Carreira on August 22, 2004 at 12:05 PM MDT #

AppFuse + Spring + WebWork... now we're talking business...

One question though. I've been struggling around with WebWork tags working inside decorators. Am I missing something or this simply doesn't work?

I wasn't to get a simple "administrator.username" property to be shown in all my pages through the decorator. :-(

Posted by Alexandre Jacques on August 22, 2004 at 03:11 PM MDT #

Regarding checking if the id property exists, you should be able to use the writeEntireProperty attribute of getProperty decorator:getProperty property="body.id" will write the contents of the "id" property, if one exists decorator:getProperty property="body.id" writeEntireProperty="true" will write id="(contents of the property)" if one exists So (assuming that I can post a comment with HTML entities correctly), you could try: <body<decoratory:getProperty property="body.id" writeEntireProperty="true"/>> to get the effect you want.

Posted by Greg on August 22, 2004 at 03:18 PM MDT #

Greg - thanks for the <em>writeEntireProperty</em> tip - it's exactly what I was looking for to achieve the desired functionality.

Posted by Matt Raible on August 22, 2004 at 03:57 PM MDT #

I don't know if this is what you mean by injection, but the various chunks of the Confluence UI (breadcrumbs, right-hand toolbars) are passed from the page to the decorator via the <content> tag, and drawn separately. The script gets run in the context of the page, rather than the decorator, but that's probably more useful in the long run.

Posted by Charles Miller on August 22, 2004 at 04:26 PM MDT #

Mate,

Good post - great to see SiteMesh getting positive press. It is truly an awesome component.

Regarding your page chunking (headings etc) - you can already do this via the content blocks feature. Simply put <content tag="x">content here</content> into your page, and it will be available to your decorator as 'page.x'. Also useful because without decoration browsers will ignore the <content> tag, hence you can still preview your pages.

You can use this technique for all sorts of things, for example you could use it to aggregate stylesheets as you talked about using <content tag="stylesheet">...</content> and then in your decorator display all of the stylesheets in your head tag - or something like that.

I do realise that content tags are largely undocumented - we'll try to fix that! :)

FWIW My TSSS presentation on SiteMesh may be of use to people seeking an overview of SiteMesh, including details on 'how it works' under the hood and how we use it at Atlassian - I've uploaded it to the SiteMesh wiki here - http://wiki.opensymphony.com/display/SM/Index. Please do let me know if anything in it is confusing.

Cheers, Mike

PS If you need any help on the webwork integration, we've done that too! See the mailing list archives or email me with q's.

Posted by Mike Cannon-Brookes on August 22, 2004 at 06:44 PM MDT #

Yeah, I'm using <content> blocks right now for headers (<h1>). They work, but I think an h1 should be given the same priority as <title>. Obviously, this is not a big deal.

Posted by Matt Raible on August 22, 2004 at 07:47 PM MDT #

Have the SiteMesh guys acknowledged that the error page decoration issue a SiteMesh bug? I didn't see it listed as an outstanding item on their issues listing and according to this guy - http://64.233.179.104/search?q=cache:cu_6FCCat2sJ:sourceforge.net/mailarchive/message.php%3Fmsg_id%3D6834689+sitemesh+decorate+error+page&hl=en - it's a Tomcat thing. Just wondering...

Posted by John Alchin on August 26, 2004 at 11:02 AM MDT #

Well, i m new to sitemesh. But when i was looking at the FAQs at Sitemesh project. I got this faq How do I enable SiteMesh to decorate error pages on Tomcat 5? If error page problem is with this, hope it helps. regards aks

Posted by Aks on August 27, 2004 at 06:17 AM MDT #

Any updates on sitemesh and error pages not being decorated?

Posted by 2devnull on October 24, 2004 at 05:56 PM MDT #

Any updates on sitemesh and error pages not being decorated?

Posted by 2devnull on October 24, 2004 at 08:47 PM MDT #

This also happens on WebSphere 5.1.1

Posted by 2devnull on October 25, 2004 at 09:58 AM MDT #

Aloha Matt,
I can inform you that when you add the following to your web.xml then error pages will be decorated (when using Tomcat 5.5.X):

<filter-mapping>
	<filter-name>sitemesh</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
	<dispatcher>ERROR</dispatcher>
</filter-mapping>

Best Regards,
j3ns
(I know - this post is almost 2 years too late )

Posted by j3ns on June 22, 2006 at 03:43 AM MDT #

I have the same detail page that can be used for detail, insert, modify, delete functions. Thank to Tiles I can write more definitions that use the same page, so: detailProductDefinition, changeProductDefinition, detailProductDefinition, newProductDefinition, etc... In each one of these I use properties to change title, header, button bar configurations, etc... How to achieve this with siteMesh ? I know that is possible to use META tags that reside in the body page, but in my case the page is the same (I have to conditionally write METAs?). Another things: Tiles allows to use inheritance between definitions, so for me was possible to create only one layout for homePage, loginPage, popupPage, etc..., with SiteMesh I have to write more decorator pages with code duplications of common parts.

Posted by Emilio on December 30, 2006 at 06:31 AM MST #

Post a Comment:
  • HTML Syntax: Allowed