Pages

reuse of visual content in java projects

Hm.. what are my options when you want to reuse some visual content rendered by some other runtime component?

Let’s say you have war A that renders some pages. Let’s say you’re writing another war (B)  and you suddenly want to reuse some ot the content from A. Let’s say you want to inherit, but also tweak. Parameterize I guess. I could..

  • do: jstl <c:import url=”<absolute or relative url>”/>in a jsp page. This includes rendered content however, so you don’t get to influence the content before rendering.
  • do: response.sendRedirect(<absolute or relative url); on the server side. Ditto disadvantage as above.
  • make a jsp taglib. I principle I guess you may put anything in the start and end tag methods, but in practice it is at best an unelegant method for reusing visual content with some size and layout
  • use maven2’s war plugin’s overlay functionality. This works, but is somewhat crude, and requires good control over naming and directories.
  • make a (jsf 2.0+) facelet taglib. No disadvantages, but a huge added bonus that you may include all kinds of fancy layout and composition as you would normally do with facelets. And paramterization works just fine. :-D

So this last option is the only good option in my opinion. Let’s have a look;

Component A

In web.xml you define the taglib;

<context-param>
 <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
 <param-value>
 /META-INF/mfoTags.taglib.xml
 </param-value>
 </context-param>

In META-INF (nowhere else, or the inter-module/war dependency will not work) you define mfoTags.taglib.xml (and it needs to have both taglib and xml as postfixes) :

<?xml version="1.0" encoding="UTF-8"?>
 <facelet-taglib>
 <namespace>http://yarc.name/mfoFaceletTags</namespace>
 <tag>
 <tag-name>siteNav</tag-name>
 <source>../WEB-INF/tags/siteNav.xhtml</source>
 </tag>
 </facelet-taglib>

..and you need (at least) an empty faces-config.xml:

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
 "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
 "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
</faces-config>

Finally, you need to package this as a jar (not a war). My solution here was to make a symbolic link since I wanted component A to remain a war since it is used as a war component on it’s own.

That’s it. Now for the user of this component;

Component B

You need to include a classpath ref to the above mentioned jar.

In the .xhtml file you’re going to refer to the facelet tag

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:mf="http://yarc.name/mfoFaceletTags"

...

>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 ...
 </head>
 <body>
 ...
 <mf:siteNav/>
 </body>
 </html>

If that isn’t simple and beautiful, then I don’t know what. Almost poetry. :-)

Week-end time!

Thanks to Laliluna for small tricks and hints and the excellent facelet documentation.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>