Archive

Archive for the ‘Java’ Category

Hibernate hard facts – Part 5

March 1st, 2010 Nicolas Frankel No comments

In the fifth article of this serie, I will show you how to manage logical DELETE in Hibernate.

Most of the time, requirements are not concerned about deletion management. In those cases, common sense and disk space plead for physical deletion of database records. This is done through the DELETE keyword in SQL. In turn, Hibernate uses it when calling the Session.delete() method on entities.

Sometimes, though, for audit or legal purposes, requirements enforce logical deletion. Let’s take a products catalog as an example. Products regularly go in and out of the catalog. New orders shouldn’t be placed on outdated products. Yet, you can’t physically remove product records from the database since they could have been used on previous orders.

Some strategies are available in order to implement this. Since I’m not a DBA, I know of only two. From the database side, both add a column, which represents the deletion status of the record:

  • either a boolean column which represent either active or deleted status
  • or, for more detailed information, a timestamp column which states when the record was deleted; a NULL meaning the record is not deleted and thus active

Managing logical deletion is a two steps process: you have to manage both selection so that only active records are returned and deletion so that the status marker column is updated the right way.

Selection

A naive use of Hibernate would map this column to a class attribute. Then, selecting active records would mean a WHERE clause on the column value and deleting a record would mean setting the attribute and calling the update() method. This approach has the merit of working. Yet, it fundamentally couples your code to your implementation. In the case you migrate your status column from boolean to timestamp, you’ll have to update your code everywhere it is used.

The first thing you have to do to mitigate the effects of such a migration is to use a filter.

Hibernate3 provides an innovative new approach to handling data with “visibility” rules. A Hibernate filter is a global, named, parameterized filter that can be enabled or disabled for a particular Hibernate session.

Such filters can the be used throughout your code. Since the filtering criteria is thus coded in a single place, updating the database schema has only little incidence on your code. Back to the product example, this is done like this:

@Entity
@FilterDef(name = "activeProducts")
@Filter(name = "activeProducts", condition = "DELETION_DATE IS NULL")
public class Product {

  @Id
  @Column(nullable = false)
  @GeneratedValue(strategy = AUTO)
  private Integer id;

...
}

Note: in the attached source, I also map the DELETION_DATE on an attribute. This is not needed in most cases. In mine, however, it permits me to auto-create the schema with Hibernate.

Now, the following code will filter out logically deleted records:

session.enableFilter("activeProducts");

In order to remove the filter, either use Session.disableFilter() or use a new Session object (remember that factory.getCurrentSession() will probably use the same, so factory.openSession() is in order).

Deletion

The previous step made us factorize the “select active-only records” feature. Logically deleting a product is still coupled to your implementation. Hibernate let us decouple further: you can overload any CRUD operations on entities! Thus, deletion can be overloaded to use an update of the right column. Just add the following snippet to your entity:

@SQLDelete(sql = "UPDATE PRODUCT SET DELETION_DATE=CURRENT_DATE WHERE ID=?")

Now, calling session.delete() on an Product entity will produce the updating of the record and the following output in the log:

UPDATE PRODUCT SET DELETION_DATE=CURRENT_DATE WHERE ID=?

With CRUD overloading, you can even suppress the ability to select inactive records altogether. I wouldn’t recommend this approach however, since you wouldn’t be able to select inactive records then. IMHO, it’s better to stick to filters since they can be enabled/disabled when needed.

Conclusion

Hibernate let you loosen the coupling between your code and the database so that you can migrate from physical deletion to logical deletion with very localized changes. In order to do this, Hibernate offers two complementary features: filters and CRUD overloading. These features should be part of any architect’s bag of tricks since they can be lifesavers, like in previous cases.

You can find the sources of this article here in Maven/Eclipse format.

To go further:

Categories: Java Tags:

Clustering Tomcat

February 24th, 2010 Nicolas Frankel No comments

In this article, I will show you how to use Apache/Tomcat in order to set up a load balancer. I know this has been done a zillion time before, but I will use this setup in my next article (teaser, teaser) so at least I will have it documented somewhere.

Apache Tomcat is the reference JSP/container since its inception. Despite a lack of full JEE support, it certainly has its appeal. The reasons behind using a full-featured commercial JEE application server are not always technical ones. With lightweight frameworks such as Spring being mainstream, it is not unusual to think using Tomcat in a production environment. Some companies did it even before that.

When thinking production, one usually think reliability and scalability. Luckily, both can be attained with Apache/Tomcat through the set up of a load-balancing cluster. Reliability is thus addressed so that if a Tomcat fails, following requests can be directed to a working Tomcat. Requests are dispatched to each Tomcat according to a predefined strategy. If the need be, more Tomcat can be added at will in order to scale.

In the following example, I will set up the simplest clustering topology possible: an Apache front-end that balances 2 Tomcat instance on the same physical machine.

Set up Apache

The first step is to configure Apache to forward your requests to Tomcat. There are basically 2 options in order to do this (I ruled out the pre-shipped load-balancer webapp):

  • use mod_jk, the classic Apache/Tomcat module
  • use mod_proxy, another Apache module

I’m not a system engineer, so I can’t decide on facts whether to use one or the other: I will use mod_jk since I’ve already used it before.

  • Download the mod_jk that is adapted to your Apache and Tomcat versions
  • Put it in the ‘modules’ folder of your Apache installation
  • Update your httpd.conf configuration to load it with Apache
    LoadModule jk_module modules/mod_jk-1.2.28-httpd-2.2.3.so
  • Configure Apache. Put these directive in the httpd.conf:
    JkWorkersFile	conf/worker.properties
    JkShmFile	logs/mod_jk.shm
    JkLogLevel	info
    JkLogFile logs/mod_jk.log
    JkMount		/servlets-examples/* lb

This configuration example is minimal but needs some comments:

Parameter Description
JkWorkersFile Where to look for the module configuration file (see below)
JkShmFile Where to put the shared memory file
JkLogLevel Module log level (debug/error/info)
JkLogFile Log file location. It is the default but declaring it avoid the Apache warning
JkMount Which url pattern will be forwarded to which worker

Since mod_jk can be used in non-clustered setups, there could be any JkMount, each forwarding to its own worker (see below). In our case, it means any request beginning with /servlets-examples/ (the trailing slash is needed) will be forwarded to the ‘lb’ worker .

Configure the workers

Workers are destination routes as viewed by Apache. They’re are referenced by an unique label in the httpd.conf and parameteirzed under the same label in the worker.properties file.
My workers.properties is the following:

worker.list=lb

worker.worker1.port=8010
worker.worker1.host=localhost
worker.worker1.type=ajp13

worker.worker2.port=8011
worker.worker2.host=localhost
worker.worker2.type=ajp13

worker.lb.type=lb
worker.lb.balance_workers=worker1,worker2

I define 3 workers in this file: lb, worker1 and worker2. The ‘lb’ worker is the load-balancing worker: it is virtual and it balances the latter two. Both are configured to point to a real Tomcat instance.

Now, with the Apache configuration in mind, we see that requests beginning with /servlets-examples/ will be managed by the load balancer worker which will in turn forward to a random worker.

Note: one can also put weight on workers hosted by more powerful machines so that these are more heavily loaded than less powerful ones. In our case, both are hosted on the same machine so it has no importance whatsoever.

Configure the Tomcat instances

The last step consist of the configuration of Tomcat instances. In order to do so, I shamelessly copied entire Tomcat installations (I’m on Windows). While editing the server.xml of the Tomcat instances, three points are worth mentioning:

  • The Engine tag has a jvmRoute attribute. It’s value should be the same as the worker’s name used in both httpd.conf and worker.properties. Otherwise, sessions will be recreated for each request
  • Look out for duplicated port numbers if all Tomcat instances are on the same machine. For example, use an incremental rule to configure every stream on a different port
  • Be sure that the tcpListenPort attribute of the Receiver is unique across all Tomcat instances

Use it!

With the previous set up, one can now start both Tomcat and Apache, then browse to the servlet-examples webapp, and more precisely to the Session page. Look there for Tomcat 5.5 and there for Tomcat 6. The servlet-example page page displays the associated session ID:

ID de Session: 324DAD12976045D197435033A67C025D.worker2
Crée le: Tue Feb 23 23:15:13 CET 2010
Dernier accès: Tue Feb 23 23:31:47 CET 2010

Notice that on my Tomcat instance, the worker’s name is part of the session ID.

If everything went fine, two interesting things should take place: first, when refreshing the page, the session ID should not change because of the sticky session (enabled by default). Morevoer, if I shutdown the Tomcat instance associated with the worker (the second in my case), and if I try to refresh the page, I still can access my application, but under a new session.

Thus, I lose all the information I stored under my session! In my following article, I will study how on can try to remedy to this.

To go further:

Categories: JEE Tags: ,

Hibernate hard facts – Part 4

February 17th, 2010 Nicolas Frankel No comments

In the fourth article of this serie, I will show the subtle differences between get() and load() methods.

Hibernate, like life, can be full of suprises. Today, I will share one with you: have you ever noticed that Hibernate provides you with 2 methods to load a persistent entity from the database tier? These two methods are get(Class, Serializable) and load(Class, Serializable) of the Session class and their respective variations.

Strangely enough, they both have the same signature. Strangely enough, both of their API description starts the same:

Return the persistent instance of the given entity class with the given identifier.

Most developers use them indifferently. It is a mistake since, if the entity is not found, get() will return null when load() will throw an Hibernate exception. This is well described in the API:

Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. You should not use this method to determine if an instance exists (use get() instead). Use this only to retrieve an instance that you assume exists, where non-existence would be an actual error.

Truth be told, the real difference lies elsewhere: the get() method returns an instance, whereas the load() method returns a proxy. Not convinced? Try the following code snippet:

Session session = factory.getCurrentSession();

Owner owner = (Owner) session.get(Owner.class, 1);

// Test the class of the object
assertSame(owner.getClass(), Owner.class);

The test pass, asserting that the owner’s class is in fact Owner. Now, in another session, try the following:

Session session = factory.getCurrentSession();

Owner owner = (Owner) session.load(Owner.class, 1);

// Test the class of the object
assertNotSame(owner.getClass(), Owner.class);

The test will pass too, asserting that the owner’s class is not Owner. If you spy the object in the debugger, you’ll see a Javassist proxyed instance and that fields are not initialized! Notice that in both cases, you are able to safely cast the instance to Owner. Calling getters will also return expected results.

Why call the load() method then? Because since it is a proxy, it won’t hit the DB until a getter method is called.

Moreover, these features are also available in JPA from the EntityManager, respectively with the find() and getReference() methods.

Yet, both behaviours are modified by Hibernate’s caching mechanism. Try the following code snippet:

// Loads the reference
session.load(Owner.class, 1);

Owner owner = (Owner) session.get(Owner.class, 1);

According to what was said before, owner’s real class should be the real McCoy. Dead wrong! Since Hibernate previously called load(), the get() looks in the Session cache (the 1st level one) and returns a proxy!

The behaviour is symmetrical with the following test, which will pass although it’s counter-intuitive:

// Gets the object
session.get(Owner.class, 1);

// Loads the reference, but looks for it in the cache and loads
// the real entity instead
Owner owner = (Owner) session.load(Owner.class, 1);

// Test the class of the object
assertSame(owner.getClass(), Owner.class);

Conclusion: Hibernate does a wonderful job at making ORM easier. Yet, it’s not an easy framework: be very wary for subtle behaviour differences.

The sources for the entire hard facts serie is available here in Eclipse/Maven format.

Categories: Java Tags: , , , ,

Context root tweaking

February 1st, 2010 Nicolas Frankel No comments

JEE never ceases to amaze me. Even when I think I’m on top and I know all there’s to know about webapps, I’m in for a surprise. Good news is, whatever you think you know about a subject, there’s still room for one more fact. Bad news is, I’m deeply disturbed by what I learned.

Fact is: web applications context root can contain the / characte, meaning an URL such as http://localhost/multipart/context can refer to the root of the multipart/context webapp as well as to the context servlet mapping of the http://localhost/multipart webapp. When I was told that, my first reaction was disbelief. I immediately hurried to run a few tests on the JOnAS and JBoss application servers and it confirmed that was entirely possible.

In fact, if you look at the application.xml XML Schema, you see that the context-root is of a type that extends string (with an id) :

This means the context root can effectively contains anything, including slashes, backslashes and what have you.

The J2EE 1.4 specifications does not enforce additional constraints (p 125) :

Each web module must be given a distinct and non-overlapping name for its context root. [...] See the servlet specification for detailed requirements of context root naming.

I did not see additional requirements in the Servlet 1.4 specifications for the context root.

Tomcat even takes this tweak into account when creating Context with individual XML files. It calls it “multi-level context paths” :

In individual files (with a “.xml” extension) in the $CATALINA_HOME/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml) extension will be used as the context path. Multi-level context paths may be defined using #, e.g. foo#bar.xml for a context path of /foo/bar.

So, in order to deploy the context.war under the multipart/context root, you’ll have to name the context XML file multipart#context.xml.

The content of the file is the following:

<?xml version='1.0' encoding='utf-8'?>
<Context docBase="${catalina.home}/context.war" />
<!-- this means the context.war should be available at the root of Tomcat -->

In the tests I’ve made, if the multi-level context path shadows a classic context-root with a servlet mapping, the former takes precedence. I do not advise using this since the case is not specified in the specification, it could be handled differently from product to product.

OK, now we’ve established these facts, what is the point in knowing this, aside from setting you as the übergeek in a JEE geek convention? Since http://localhost/multipart/context and http://localhost/multipart are clearly separated web applications, they do not even share context.

In my case, that was the solution for a simple use-case. Imagine monitoring web applications: you know the URL you have to monitor. Now a product, developped in-house for diagnostics purpose, is deployed side-by-side with each webapp in webapp form. It would be very nice if you could reach the diagnostics webapp without looking at the documentation to know its URL. Let’s say it is the business webapp’s URL appended with /diag.

So, if the main webapp’s URL is http://myserver.com/mywebapp and the person in charge of monitoring knows about it, he knows he has to access http://myserver.com/mywebapp/diag and he gets what he wants! On the development side, it means both webapps are different products, are developed by different teams and have different lifecycles.

Categories: JEE Tags: , , ,

Discover Spring authoring

December 29th, 2009 Nicolas Frankel No comments

In this article, I will describe a useful but much underused feature of Spring, the definition of custom tags in the Spring beans definition files.

Spring namespaces

I will begin with a simple example taken from Spring’s documentation. Before version 2.0, only a single XML schema was available. So, in order to make a constant available as a bean, and thus inject it in other beans, you had to define the following:

<bean id="java.sql.Connection.TRANSACTION_SERIALIZABLE"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />

Spring made it possible, but realize it’s only a trick to expose the constant as a bean. However, since Spring 2.0, the framework let you use the util namespace so that the previous example becomes:

<util:constant static-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>

In fact, there are many namespaces now available:

Prefix Namespace Description
bean http://www.springframework.org/schema/bean Original bean schema
util http://www.springframework.org/schema/util Utilities: constants, property paths and collections
util http://www.springframework.org/schema/jee JNDI lookup
lang http://www.springframework.org/schema/lang Use of other languages
tx http://www.springframework.org/schema/tx Transactions
aop http://www.springframework.org/schema/aop AOP
context http://www.springframework.org/schema/context ApplicationContext manipulation

Each of these is meant to reduce verbosity and increase readibility like the first example showed.

Authoring

What is still unknown by many is that this feature is extensible that is Spring API provides you with the mean to write your own. In fact, many framework providers should take advantage of this and provide their own namespaces so that integrating thier product with Spring should be easier. Some already do: CXF with its many namespaces comes to mind but there should be others I don’t know of.

Creating you own namespace is a 4 steps process: 2 steps about the XML validation, the other two for creating the bean itself. In order to illustrate the process, I will use a simple example: I will create a schema for EhCache, the Hibernate’s default caching engine.

The underlying bean factory will be the existing EhCacheFactoryBean. As such, it won’t be as useful as a real feature but it will let us focus on the true authoring plumbing rather than EhCache implementation details.

Creating the schema

Creating the schema is about describing XML syntax and more importantly restrictions. I want my XML to look something like the following:

<ehcache:cache id="myCache" eternal="true" cacheName="foo"
maxElementsInMemory="5" maxElementsOnDisk="2" overflowToDisk="false"
diskExpiryThreadIntervalSeconds="18" diskPersistent="true" timeToIdle="25" timeToLive="50"
memoryStoreEvictionPolicy="FIFO">
  <ehcache:manager ref="someManagerRef" />
</ehcache:echcache>

Since I won’t presume to teach anyone about XML, here’s the schema. Just notice the namespace declaration:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://blog.frankel.ch/spring/ehcache" xmlns="http://blog.frankel.ch/spring/ehcache"
  elementFormDefault="qualified">
  <xsd:complexType name="cacheType">
    <xsd:sequence maxOccurs="1" minOccurs="0">
      <xsd:element name="manager" type="managerType" />
    </xsd:sequence>
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="cacheName" type="xsd:string" />
    <xsd:attribute name="diskExpiryThreadIntervalSeconds" type="xsd:int" />
    <xsd:attribute name="diskPersistent" type="xsd:boolean" />
    <xsd:attribute name="eternal" type="xsd:boolean" />
    <xsd:attribute name="maxElementsInMemory" type="xsd:int" />
    <xsd:attribute name="maxElementsOnDisk" type="xsd:int" />
    <xsd:attribute name="overflowToDisk" type="xsd:boolean" />
    <xsd:attribute name="timeToLive" type="xsd:int" />
    <xsd:attribute name="timeToIdle" type="xsd:int" />
    <xsd:attribute name="memoryStoreEvictionPolicy" type="memoryStoreEvictionPolicyType" />
  </xsd:complexType>
  <xsd:simpleType name="memoryStoreEvictionPolicyType">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="LRU" />
      <xsd:enumeration value="LFU" />
      <xsd:enumeration value="FIFO" />
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:complexType name="managerType">
    <xsd:attribute name="ref" type="xsd:string" />
  </xsd:complexType>
  <xsd:element name="cache" type="cacheType" />
</xsd:schema>

And for those, like me, that prefer a graphic display:

Mapping the schema

The schema creation is only the first part. Now, we have to make Spring aware of it. Create the file META-INF/spring.schemas and write in the following line is enough:

http\://blog.frankel.ch/spring/schema/custom.xsd=ch/frankel/blog/spring/authoring/custom.xsd

Just take care to insert the backslash, otherwise it won’t work. It maps the schema declaration in the XML to the real file that will be used from the jar!

Before going further, and for the more curious, just notice that in spring-beans.jar (v3.0), there’s such a file. Here is it’s content:

http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd

It brings some remarks:

  • Spring eat their own dogfood (that’s nice to know)
  • I didn’t look into the code but I think that’s why XML validation of Spring’s bean files never complain about not finding the schema over the Internet (a real pain in production environment because of firewall security issues). That’s because the XSD are looked inside the jar
  • If you don’t specify the version of the Spring schema you use (2.0, 2.5, 3.0, etc.), Spring will automatically upgrade it for you with each major/minor version of the jar. If you want this behaviour, fine, if not, you’ll have to specify version

Creating the parser

The previous steps are only meant to validate the XML so that the eternal attribute will take a boolean value, for example. We still did not wire our namespace into Spring factory. This is the goal of this step.

The first thing to do is create a class that implement org.springframework.beans.factory.xml.BeanDefinitionParser. Looking at its hierarchy, it seems that the org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser is a good entry point since:

  • the XML is not overly complex
  • there will be a single bean definition

Here’s the code:

public class EhCacheBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {

  private static final List&amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;gt; PROP_TAG_NAMES;

  static {

  PROP_TAG_NAMES = new ArrayList();

    PROP_TAG_NAMES.add("eternal");
    PROP_TAG_NAMES.add("cacheName");
    PROP_TAG_NAMES.add("maxElementsInMemory");
    PROP_TAG_NAMES.add("maxElementsOnDisk");
    PROP_TAG_NAMES.add("overflowToDisk");
    PROP_TAG_NAMES.add("diskExpiryThreadIntervalSeconds");
    PROP_TAG_NAMES.add("diskPersistent");
    PROP_TAG_NAMES.add("timeToLive");
    PROP_TAG_NAMES.add("timeToIdle");
  }

  @Override
  protected Class getBeanClass(Element element) {

    return EhCacheFactoryBean.class;
  }

  @Override
  protected boolean shouldGenerateIdAsFallback() {

    return true;
  }

  @Override
  protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {

    for (String name : PROP_TAG_NAMES) {

      String value = element.getAttribute(name);

      if (StringUtils.hasText(value)) {

        builder.addPropertyValue(name, value);
      }
    }

    NodeList nodes = element.getElementsByTagNameNS("http://blog.frankel.ch/spring/ehcache", "manager");

    if (nodes.getLength() &amp;amp;amp;amp;amp;amp;gt; 0) {

      builder.addPropertyReference("cacheManager",
        nodes.item(0).getAttributes().getNamedItem("ref").getNodeValue());
    }

    String msep = element.getAttribute("memoryStoreEvictionPolicy");

    if (StringUtils.hasText(msep)) {

      MemoryStoreEvictionPolicy policy = MemoryStoreEvictionPolicy.fromString(msep);

      builder.addPropertyValue("memoryStoreEvictionPolicy", policy);
    }
  }
}

That deserves some explanations. The static block fills in what attributes are valid. The getBeanClass() method returns what class will be used, either directly as a bean or as a factory. The shouldGenerateIdAsFallback() method is used to tell Spring that when no id is supplied in the XML, it should generate one. That makes it possible to create pseudo-anonymous beans (no bean is really anonymous in the Spring factory).

The real magic happen in the doParse() method: it just adds every simple property it finds in the builder. There are two interesting properties though: cacheManager and memoryStoreEvictionPolicy.

The former, should it exist, is a reference on another bean. Therefore, it should be added to the builder not as a value but as a reference. Of course, the code doesn’t check if the developer declared the cache manager as an anonymous bean inside the ehcache but the schema validation took already care of that.

The latter just uses the string value to get the real object behind and add it as a property to the builder. Likewise, since the value was enumerated on the schema, exceptions caused by a bad syntax cannot happen.

Registering the parser

The last step is to register the parser in Spring. First, you just have to create a class that extends org.springframework.beans.factory.xml.NamespaceHandlerSupport and register the handler under the XML tag name in its init() method:

public class EhCacheNamespaceHandler extends NamespaceHandlerSupport {

  public void init() {

    registerBeanDefinitionParser("cache", new EhCacheBeanDefinitionParser());
  }
}

Should you have more parsers, just register them in the same method under each tag name.

Second, just map the formerly created namespace to the newly created handler in a file META-INF/spring.handlers:

http\://blog.frankel.ch/spring/ehcache=ch.frankel.blog.spring.authoring.ehcache.EhCacheNamespaceHandler

Notice that you map the declared schema file to the real schema but the namespace to the handler.

Conclusion

Now, when faced by overly verbose bean configuration, you have the option to use this nifty 4-steps techniques to simplify it. This technique is of course more oriented toward product providers but can be used by projects, provided the time taken to author a namespace is a real time gain over normal bean definitions.

You will find the sources for this article here in Maven/Eclipse format.

To go further

  • Spring authoring: version 2.0 is enough since nothing changed much (at all?) with following versions
  • Spring’s Javadoc relative to authoring

HTML UI over a REST backend

December 26th, 2009 Nicolas Frankel No comments

In this article, I will show you that forms sent by browsers to a server can only use GET and POST HTTP methods and which workaround to apply in order to still use a REST backend.

REST web-services are becoming more and more common in today’s landscape. We can only imagine the reasons, but I guess that SOAP’s structured approach is only useful in the most complex use-cases and is overkill the rest of the time. On the contrary, REST is quite easy to setup.

In the Java world, REST has its own specification, JAX-RS with JSR 311, and is supported by all major frameworks :

In my humble opinion, it is not inconceivable that, given the adoption of REST, the next step would be the development of REST backends accessible by standard clients and browsers alike, in order to factorize code and thus decrease costs.

Traditionallly, making a resource accessible on the web is realized through a hyperlink. Hyperlinks use the GET method. Likewise, REST is based on using the HTTP methods where each has an associated verb:

HTTP method Verb
POST Create
GET Read
PUT Update
DELETE Delete

Unluckily, the real world comes into play. In order for this to work, the HTML 4 specification is a big obstacle in the way:

The FORM element [...]

Method: this attribute specifies which HTTP method will be used to submit the form data set. Possible (case-insensitive) values are “get” (the default) and “post”.

The implication is that HTML 4 compliant browsers will only let you read and create but not update nor delete. For example, the versions of Firefox and Internet Explorer I used, respectively 3.5.6 and 6.0 (!) use POST for POST and GET for everything else. That’s a real case against using REST. There are some workarounds, though.

The first one is not to use the HTTP method for the verb but to put it in the URL. Thus

  • to access a customer, one would use http://frankel.ch/get/customer/1
  • and to remove one, http://frankel.ch/delete/customer/1

This clearly violates REST’s principle of using the HTTP method for the verb but this works for simple cases.

The second workaround is a bit more complex but it has two big advantages: it conforms to REST principles and it is usable with most modern-days browsers.

The trick is to use a neat little object created by Microsoft but now implemented everywhere, the XMLHttpRequest object. Yes, this is the object at the foundation of Ajax but is is also the solution of our problem. XMLHttpRequest’s open() method takes two parameters, the first being the HTTP method to use for accessing the url (which is the second parameter). Now you can pass the verb you want, like the following example.

xmlhttp = new XMLHttpRequest();
xmlhttp.open('DELETE', 'http://frankel.ch/customer/1');
xmlhttp.send(null);

Morevover, you can not only use the 4 CRUD verbs but also any verb you want.

This solution has two main limitations:

  • it requires modern-day browsers since the XMLHttpRequest object is not available in more ancient ones
  • it requires JavaScript, so you need to enable it on client browsers and you need to manage browser compatibilities. For example, the above script with Firefox 3.5 but not IE 6 (and to be blunt, I’m not really bothered by it)

It seems this hack will be rendered useless by the HTML 5 specifications which declares (in their draft state) that all 4 basic CRUD verbs will have to be supported.

You can find an example for this article here. Tu use, navigate to http://localhost:8080/httpmethods/ if deployed in Eclipse. It was tested on Firefox 3.5 and works on it flawlessly. On the contrary, it doesn’t work for IE 8 since my script is not crafted to be cross-browsers. For Tomcat users, you have to add JSTL capabilities to Tomcat (meaning adding standard.jar and jstl.jar in the commons/lib directory).

To go further :

Categories: JEE Tags: ,

Hibernate hard facts part 3

December 13th, 2009 Nicolas Frankel No comments

Hibernate LogoIn the third article of this serie, I will show how to tweak Hibernate so as to convert any database data types to and from any Java type and thus decouple your database model from your object model.

Custom type mapping

Hibernate is a very powerful asset in any application needing to persist data. As an example, I was tasked this week to generate the Object-Oriented model for a legacy database. It seemed simple enough, at first glance. Then I discovered a big legacy design flaw: for historical reasons, dates were stored as number in the YYYYMMDD format. For example, 11th december 2009 was 20091211. I couldn’t or rather wouldn’t change the database and yet, I didn’t want to pollute my neat little OO model with Integer instead of java.util.Date.

After browsing through Hibernate documentation, I was confident it made this possible in a very simple way.

Creating a custom type mapper

The first step, that is also the biggest, consist in creating a custom type. This type is not a real “type” but a mapper that knows how to convert from the database type to the Java type and vice-versa. In order to do so, all you have is create a class that implements org.hibernate.usertype.UserType. Let’s have a look at each implemented method in detail.

The following method gives away what class will be returned at the end of read process. Since I want a Date instead of an Integer, I naturally return the Date class.

public Class returnedClass() {

  return Date.class;
}

The next method returns what types (in the Types constants) the column(s) that will be read fromhave. It is interesting to note that Hibernate let you map more than one column, thus having the same feature as the JPA @Embedded annotation. In my case, I read from a single numeric column, so I should return a single object array filled with Types.INTEGER.

public int[] sqlTypes() {

  return new int[] {Types.INTEGER};

}

This method will check whether returned class instances are immutable (like any normal Java types save primitive types and Strings) or mutable (like the rest). This is very important because if false is returned, the field using this custom type won’t be checked to see whether an update should be performed or not. It will be of course if the field is replaced, in all cases (mutable or immutable). Though there’s is a big controversy in the Java API, the Date is mutable, so the method should return true.

public boolean isMutable() {

  return true;

}

I can’t guess how the following method is used but the API states:

Return a deep copy of the persistent state, stopping at entities and at collections. It is not necessary to copy immutable objects, or null values, in which case it is safe to simply return the argument.

Since we just said Date instances were mutable, we cannot just return the object but we have to return a clone instead: that’s made possible because Date’s clone() method is public.

public Object deepCopy(Object value) throws HibernateException {

  return ((Date) value).clone();
}

The next two methods do the real work to respectively read from and to the database. Notice how the API exposes ResultSet object to read from and PreparedStatement object to write to.

public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {

  Date result = null;

  if (!rs.wasNull()) {

    Integer integer = rs.getInt(names[0]);

    if (integer != null) {

      try {

        result = new SimpleDateFormat("yyyyMMdd").parse(String.valueOf(integer));

      } catch (ParseException e) {

        throw new HibernateException(e);
      }
    }
  }

  return result;
}

public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {

  if (value == null) {

    statement.setNull(index, Types.INTEGER);

  } else {

    Integer integer = Integer.valueOf(new SimpleDateFormat("yyyyMMdd").format((String) value));

    statement.setInt(index, integer);
  }
}

The next two methods are implementations of equals() and hasCode() from a persistence point-of-view.

public int hashCode(Object x) throws HibernateException {

  return x == null ? 0 : x.hashCode();
}

public boolean equals(Object x, Object y) throws HibernateException {

  if (x == null) {

    return y == null;
  }

  return x.equals(y);
}

For equals(), since Date is mutable, we couldn’t just check for object equality since the same object could have been changed.

The replace() method is used for merging purpose. It couldn’t be simpler.

public Object replace(Object original, Object target, Object owner) throws HibernateException {

  Owner o = (Owner) owner;

  o.setDate(target);

  return ((Date) original).clone();
}

My implementation of the replace() method is not reusable: both the owning type and the name of the setter method should be known, making reusing the custom type a bit hard. If I wished to reuse it, the method’s body would need to use the lang.reflect package and to make guesses about the method names used. Thus, the algorithm for creating a reusable user type would be along the lines of:

  1. list all the methods that are setter and take the target class as an argument
    1. if no method matches, throw an error
    2. if a single method matches, call it with the target argument
    3. if more than one method matches, call the associated getter to check which one returns the original object

The next two methods are used in the caching process, respectively in serialization and deserialization. Since Date instances are serializable, it is easy to implement them.

public Serializable disassemble(Object value) throws HibernateException

  return (Date) ((Date) value).clone();
}

public Object assemble(Serializable cached, Object owner) throws HibernateException {

  return ((Date) cached).clone();
}

Declare the type on entity

Once the custom UserType is implemented, you need to make it accessible it for the entity.

@TypeDef(name="dateInt", typeClass = DateIntegerType.class)
public class Owner {

  ...
}

Use the type

The last step is to annotate the field.

@TypeDef(name="dateInt", typeClass = DateIntegerType.class)

public class Owner {

  private Date date;

  @Type(type="dateInt")
  public Date getDate() {

    return date;
  }

  public void setDate(Date date) {

    this.date = date;
  }
}

You can download the sources for this article here.

To go further:

Lombok reduces your boilerplate code

December 6th, 2009 Nicolas Frankel Comments off

In this article, I show you the power of the product I stumbled upon this week: Project Lombok enables you to modify bytecode at compile code. First, I will detail what features Lombok brings you out-of-the-box. In the second part of this article, I will describe how to extend it to generate you own code.

Introduction

Since the dawn of JEE, complaints have been filed regarding the complexity of coding components. I consider EJB v2 a very good example of this complexity: for just a simple EJB, you have to provide the EJB class itself and a home and an interface for each access type (local and remote). This makes it complex, error-prone and more importantly gives you less time to focus on business code where the real value is. Two initiatives show the will to decrease the amount of boilerplate code needed when coding:

  • the Spring Framework’s motto is to decrease JEE complexity. The boilerplate code is written once in the Spring framework and only used by projects.
  • EJB v3 has taken into account the lessons from Spring and aim to reduce boilerplate code too, making local and remote interfaces unnecessary. Eventually, the next version of the specification will make the local and remote home optional too.

The goal of Project Lombok is exactly the same as the previous initiatives but in order to do so, it uses another mechanism.

Annotation processing

Version 5 of the Java language introduced the concept of annotations, code meta-data that could be processed at compile time and/or runtime. Unfortunately, in JDK 5, processing annotations at compile is a 2-step process. First, you have to run the apt executable to process annotations, perhaps creating or modifying source files, then compile your sources with javac. That was not the best approach, so Java 6 removes apt and make javac able to manage annotations, streamlining the process to obtain a simpler single step computing. This is the path taken by Lombok.

Project Lombok

Lombok’s driving feature is to create code you need from annotations in order to reduce the amount of boilerplate code you have to write. It provides you with the following annotations that will change your code (if not your life) forever:

For example, while learning to code the OO way, you were drilled into making your fields private and into writing public accessors to access these fields:

public class Person {

  private String name;

  public String getName() {

    return name;
  }

  public void setName(String name) {

    this.name = name;
  }
}

Since this is a bother to write, some (if not all) IDE have a feature to generate the accessors. It has some drawbacks:

  • You have to manually remove the accessors if you remove the field
  • It clutters your real code with boilerplate code
  • Corollary: it takes a real effort to check whether an accessor already exist for a field in a long class

Moreover, creating accessors manually is error-prone: I once searched for hours for a bug in code developed by a fellow developer and finally found the setter was wrong.

Since getter / setter is only meta-data for a field, Lombok’s stance is to treat it like such: in Java, meta-data is managed with annotations. Look at the following code:

import org.lombok.Getter;
import org.lombok.Setter;

public class Person {

  @Getter @Setter
  private String name;
}

I decompiled the generated class (using JAD) and it creates exactly the same bytecode, only the source code is more concise and less error-prone.

When thinking, I found 3 arguments against using Lombok:

  1. The first argument against using such a strategy is that you can’t create a protected accessor like that. You’re wrong, Lombok is configurable:
  2. import lombok.AccessLevel;
    import org.lombok.Getter;
    import org.lombok.Setter;
    
    public class Person {
    
      @Getter @Setter(AccessLevel.PROTECTED)
      private String name;
    }

    And its true for all the provided annotations! Just look at them.

  3. The second argument against using Lombok is that you don’t know what it does behind the scene. It’s true, but the same could be said for AOP or CGLIB or whatever framework you’re using.
  4. The last argument and IMHO the only one valid enough is that it renders debugging more complex: but so is the use of Java dynamic proxies that Spring uses throughout its code, and still many projects use them.

Use and installation

Using Lombok is a 3-step process:

  1. Put the JAR on the classpath
  2. Add the annotation you want to use
  3. Compile with javac

There’s a catch, though. Notice the last statement and the emphasis on javac. Since most (if not all) the developers you and I know focus a little bit on productivity, chances are you’re using a IDE. I do not know about NetBeans and fellows, but my favorite IDE Eclipse does not use javac to compile but its own internal compiler.

Our friends from Lombok thought about that and Lombok is able to hook into Eclipse compiling process too. In order to do so, just launch lombok.jar and follow the instructions on you screen: it will just add 2 lines to your eclipse.ini.

A word of advice (since I made the mistake): if you launch Eclipse with a command that takes parameters, such as a Windows shortcut, these parameters take precedence and eclipse.ini is silently ignored. Just to let you know…

Lombok extensions

To my knowledge, there’s currently only a single extension of Lombok called Morbok. It lets you create your classical private static final logger with just an annotation.

The advantage of this is that Morbok automatically uses the fully qualified class name as the name of the logger so no more copy paste error. The disadvantage is that if you do not use Commons Logging as you logging framework, you have to configure each @Logger annotation with the framework you want to use, there’s no overall configuration: IMHO, that’s something that could be covered in the next version (is there’s one).

Architecture

First things first, Lombok needs a JDK 6 to compile since annotation processing is done in Java 5 with APT. For now, Lombok hooks into the compiling process immediately after the environment has built the AST for the class.

It then passes the structure thus formed to each of its referenced handlers. There’s a single handler for each annotation: HandleGetter for @Getter, HandlerSetter for @Setter and so on. Handlers are, guess what, responsible for handling annotations.

Extending Lombok

Extending Lombok is a 3-step process:

  1. Create the annotation. Since the annotation is used at compile-time, it can be safely be discarded afterwards so its retention policy can be left to its default value (namely RetentionPolicy.SOURCE)
  2. Create the handler. A handler is a class that directly implements lombok.javac.JavacAnnotationHandler<T extends Annotation>. Why directly? Because Lombok uses the ServiceProvider service and it’s one of its limitations
  3. Reference the fully qualified class name of the handler in a file named lombok.javac.JavacAnnotationHandler under META-INF/services

The real coding takes place in step 2: the interface has a single method handle(AnnotationValues<T> annotation, com.sun.tools.javac.tree.JCTree.JCAnnotation ast, JavacNode annotationNode). Notice the 2nd parameter package? It’s denotes Sun private implementation. It has some big drawbacks:

  • The documentation is sparse if not completely unavailable. You go into unknown territory here
  • Since the com.sun.tools.javac is not part of the public API, it can change at a moment’s notice. You can break your code with each update
  • Remember that previously, I talked about this being only good for Java? That’s still true. If you want this new annotation to work under Eclipse, that’s another handler to write

Example

As an example, I coded an embryo for a @Delegate annotation. Such an annotation on a field indicates that the declaring class should have the same public methods as the field’s class and each method’s body should be a call to its delegate’s method.

public class Delegator {

  @Delegate
  private DelegateObject object;

  ...
}

public class DelegateObject {

  public void doSomething() {
    ...
  }
}

The previous code should generate the same bytecode as the following code:

public class Delegator {

  private DelegateObject object;

  public void doSomething() {

    object.doSomething();
  }
  ...
}

As yet:

  • it does not handle generics
  • the only handler provided is for javac
  • it is not configurable

The final implementation is left for the brave readers: original sources are here in Eclipse/Maven format.

Conclusion

Some improvements could quickly be made to Lombok. First, I don’t like the monolithic structure the JAR has. IMHO, it could be nicely decoupled into 3 separate JARs: the Lombok agent itself, the provided annotations and associated handlers and finally, the installer.

Moreover, coding two handlers for each annotation is a lost of time. What if you need to support NetBeans too? Perhaps using the Service Provider is a mistake…

Finally, depending on Sun’s internal compiler API is too big a risk. I think that if Lombok could provide a facade to this API, it could be less risky for enterprise to take this road and the bridging could be made by people who understand the API (the Lombok team) and not base developers (like myself).

All in all, and despite these flaws, Lombok looks like a very promising project that could well mimic Spring’s success. That’s what I wish it anyway because it’s real sideway thinking that brings much added value: good luck for the future!

To go further:

Thoughts on Java logging and SLF4J

November 21st, 2009 Nicolas Frankel 7 comments

In this post, I will ramble on logging in Java, how it was done in the old days and what can a library like SLF4J can bring.

Logging is a basic need when you create software. Logging use-cases are:

  • debugging the software during development,
  • help diagnose bugs during production
  • trace access for security purposes
  • create data for statistical use
  • etc.

Whatever the use, logs should be detailed, configurable and reliable.

History

Historically, Java logs where done with System.out.println(), System.err.println() or e.printStackTrace() statements. Debug logs where put in System.out and error logs in System.err. In production, both were redirected: the former on the null output, the latter to the desired error log file. So they were useful enough but they suffered from a big drawback: they were not very configurable. It was an all or nothing switch, either log or don’t. You could not focus detailed logs on a particular layer or package.

Log4J came to the rescue. It was everything one could ever want from a logging framework. It invented many concepts still used in today’s logging frameworks (it was the first framework I used so please bear with me if a concept was not invented by it):

  • the concept of Logger so that each logger can be configured independently
  • the concept of Appender so that each appender can log wherever it wants (file, database, message, etc.)
  • the concept of Level so that one can configure the logging (or not) of each message separately

After that, Sun felt the need for a logging feature inside the JDK but, instead of using log4j directly, it created an API inspired by it. However, it was not not so well finished as Log4J. If you want to use JDK 1.4 logging, chances are you’ll have to write your own Appenders – called Handlers – since the only handlers available are Console and File out-of-the-box.

With both frameworks available, you needed to configure both of them since whatever framework you used, there was surely at least one dependency of your project that used the other. Apache Commons Logging is an API bridge that connects itself to supported logging frameworks. Libraries should use commons-logging so that the real framework used is the choice of the project, and is not imposed by the dependencies. This is not always the case, so Commons Logging does not solve the double configuration problem. Morevoer, Commons Logging suffer from some class-loading problems, leading to NoClassDefFoundError errors.

Finally, the lead programer from Log4J quit the project for reasons I will not detail here. He created another logging framework, namely SLF4J, that should have been Log4J v2.

Some strange facts

The following facts are things that bother me with the previous frameworks. They are not drawbacks per se but are worth mentioning:

  • Log4J has Maven dependencies on JMS, Mail and JMX that are not optional, meaning they will appear on your classpath if you do not bother to exclude them
  • Likewise, Commons Logging has Maven dependencies on Avalon (another logging framework), Log4J, LogKit and Servlet API (!) that are not optional
  • A Swing log viewer is included in Log4J jar, even if you it is used in an headless environment, such as a batch or an application server
  • Log4J v1.3 main page redirects to v1.2 while Log4 v2.0 is experimental

Which framework to use ?

Log4J would be the framework of choice (and is for most) but it is no longer developed. Version 1.2 is the reference, version 1.3 is abandoned and version 2.0 is still in its early stage.

Commons Logging is a good choice for a library (as opposed to an application) but I suffered once classloaders issues, and once is enough to veto it (finally, i threw Commons Logging out and used Log4J directly).

JDK 1.4 Logging is a standard and does not raise concurrent versions problems. But it lacks so many features, it cannot be used without redeveloping some such as a database adapter and such. Too bad… but it does not answers the question: which framework to use?

Recently, architects of my company decided for SLF4J. Why such a choice?

SLF4J

SLF4J is not as widespread as Log4J because most architects (and developers alike) know Log4J well and either don’t know about SLF4J, or don’t care and stick to Log4J anyway. Moreover, for most projects Log4J fulfills all logging’s needs. Yet, interestingly enough, Hibernate uses SLF4J. It has some nice features that are not present in Log4J.

Simple syntax

Take the following Log4J example:

LOGGER.debug("Hello " + name);

Since String concatenation is frowned upon, many companies enforce the following syntax, so that the concatenation only does take place when in DEBUG level:

if (logger.isDebugEnabled()) {

  LOGGER.debug("Hello " + name);
}

It avoids String concatenation but it’s a bit heavy, isn’t it? In contrast, SLF4J offers the following simple syntax:

LOGGER.debug("Hello {}", name);

It’s like the first syntax but without the concatenation cost nor the heavy syntax burden.

SLF4J API and implementation

Moreover, SLF4 nicely decouples API from implementation so that you can use the API that works best with your development with the back-end that suits best your production team. For example, you could enforce the use of the SL4J API while letting the production still reuse the old log4j.properties they’ve known for ages. SLF4J’s logging implementation is known as LogKit.

SLF4J bridging

SLF4J has a bridging feature sor you can remove all log4j and commons-logging dependencies from your project’s dependencies and use only SLF4J.

SLF4J offers a JAR for each logging framework: they mimic its API but reroute the calls to the SLF4J API (which in turn uses the real framework). A word of warning: you could run into a cycle so beware to not have the bridging library along the implementation library in your classpath. For example, if you use the Log4J bridge, each Log4J API call will be rerouted to SLF4J. But if the SLF4J Log4J implementation is present, it will be routed back to Log4J then again, and again.

SLF4J API with Log4J implementation

Taking all these facts into account, my advice is to use SLF4J API and Log4J implementation. This way, you still configure logging the old Log4J way but you have access to SLF4J’s simpler API. In order to do so, you’ll have to:

Action Location Description
Add to classpath slf4j-api.jar* Main API without which you cannot use SLF4J
slf4j-log4j.jar* SLF4J Log4J implementation
jul-to-slf4j.jar* Enables rerouting JDK 1.4 logging calls to SLF4J
jcl-over-slf4j.jar* Reroutes commons-logging calls to SLF4J
Remove from classpath commons-logging.jar* Would conflict with commons-logging API in jcl-over-slf4j.jar
SLF4JBridgeHandler.install()** Main application Redirect JDK 1.4 logging calls to SLF4J
* Jar name will likely includes version
** 20% overhead advertised so do only if you need the single entry point and if there are a few calls

In you run inside an application server, you’ll probably have to change its libraries and / or its configuration to reach this situation.

To go further:

Simple templating solution with SiteMesh

October 24th, 2009 Nicolas Frankel No comments

In this article, I will show you how to use SiteMesh in your JEE web sites in order to bring a sense of unity to them.

When talking about templating, the method everyone uses at first is to use <@include> tags throughout the JSP pages. This course of action is flawed from the start since all JSPs are responsible to call includes and thus, there’s no real enforcement to use the correct ones.

The most used method is Apache Tiles. To be frank, I didn’t have a look at Tiles since it went from Struts to Apache. Struts Tiles were meant to be used in conjunction with Struts. Apache Tiles seems to support many more technologies (JSP, Velocity, Freemarker, …) but I didn’t see any JSF support out-of-the-box though there seem to exist plenty of articles that tackle the subject and its problems.

When I used Struts Tiles, I found it was a very powerful framework, yet many junior developers had some problems with it. In most projects I worked on, a senior developer assembled tiles while junior ones created the pages themselves. I found Tiles very configurable but this came at the cost of complexity. In most cases, I didn’t need all the functionalities of Tiles: I only wanted to have a header, a footer and a menu nicely crafted around my main page.

When investigating AppFuse, I stumbled upon a nice templating tool that just does that: SiteMesh. SiteMesh is technology-neutral, meaning it can be used with whatever view framework is used, JSF included. It is based on the very simple concept of servlet filters. An XML file forms the basis of the template’s configuration. This configuration holds what pages are decorated and with what templates.

The templating mechanism is made so each page is seen as complete either when viewed standalone or when viewed through the filter. For example, when you write the page normally, you provide the title’s text (what is displayed in most browser’s title bar). If you are using SiteMesh, nothing changes. At runtime, the servlet filter reads the title’s text value from the source HTML (which can come from a dynamic source) and outputs the decorated page with the same title’s text value, although the page design will be different.

The following example shows how it is achieved in the template:

<html>
  <head>...</head>
  <body>
    <div id="top">Header</div>
    <h1><decorator:getProperty property="title" /></h1>
    ...
  </body>
<html>

Nothing could be simpler. Yet, the solution decouples the standalone view from the decorated view. The former has no need to know about the latter!

A common use-case is to put common CSS and JavaScript declarations in the template.

Moreover, the choice of which decorator(s) to use can come from different strategies:

  • configuration files,
  • cookies,
  • browser language,
  • display agent (browser or printer),
  • etc.

The simplicity and the robustness of the solution is what will make me deeply think about using it if I have simple templating needs. On the opposite site, if you have complex templating requirements, SiteMesh won’t be enough.

You will find a very simple project here in Maven/Eclipse format.

To go further: