Giving it some front

Front-end modularization with JSPs

ChristianRobert
slices

Modularization of a web application can be tricky when working with JSP templates. Christian Robert helps make the process less painful.

Introduction

When faced with the modularization of a web application, we often encounter a scenario where the back-end services and other back-end resources are well structured and grouped into some kind of module structure.

However, the front-end part, in our case consisting of JSP templates, lacks proper modularization. Yes, there is the possibility of includes, but a real module structure is often missing. However, let’s first think about what a “real” module structure means to us.

When slicing a JSP template file into modules, we will arbitrarily define two kinds of module elements: fragments and components. Let’s start with the latter: A component represents the smallest part any piece of content can be made of. For example a component might be an input field, a select box or simply a label. Internally a component might use other components to display it’s content but from a conceptual standpoint a component is the smallest part a web developer should use when slicing a large HTML page into manageable pieces.

A fragment on the other hand is a group of logically associated components. A regular webpage for example might be composed of three fragments: A header, the content and a footer. Each fragment might be subdivided into sub fragments. Ie. the header fragment might consist of an info fragment that shows a logo image and a title, a login fragment which allows the user to enter his username and password on every page and a menu fragment from which the user can select a link to a specific page. The menu fragment itself might consist of another set of fragments: the main menu fragment, the profile data fragment and the help menu fragment. And so on.

Each of these fragments is made up of components: The login fragment, for example, might be made up of an input field component for the username, an input field component for the password, and a button component that triggers the action to perform the login.

When creating an index page, we might end up with the following page:

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <jsp:include page="header.jsp" />

    <section id="content">
      Hello World!
    </section>

    <jsp:include page="footer.jsp" />
  </body>
</html>

index.jsp

We can see the fragments we defined above. The header fragment is located in the included header.jsp file, the footer fragment is located in the included footer.jsp and the content fragment is the remaining content in the page itself.

Now let’s take a look into the header.jsp file and the login-form.jsp file which is referenced in it containing the login page fragment:

<header>
  <jsp:include page="header-title.jsp" />
  <jsp:include page="login-form.jsp" />
</header>

header.jsp

<%@ taglib prefix="comp" tagdir="/WEB-INF/tags/components" %>
<form name="login-form" action="/login">
  <comp:fieldPlusLabel name="username" type="text" label="Username" />
  <comp:fieldPlusLabel name="password" type="password" label="Password" />
  <comp:button type="submit" formName="login-form" />
</form>

login-form.jsp

The header.jsp just includes two other fragments, the login-form.jsp consist of three components. In this example the fragments so far were realized as simple include while the components are realized as JSP tags. We might also use tag based composition for fragments or include based composition for components. Conceptually it doesn’t really matter – both ways a valid and both ways work. However the tag based composition is a lot less verbose so you should, whenever possible, try to use it.

Back to content: So far, from a web developer’s point of view we have reached the end of the slicing process: As we’ve defined at the beginning a component is the smallest piece of information from which we want to compose our page. However, let’s peek into a component and look how it is built internally:

<%@ tag description="Displays a field including a label" %>
<%@ attribute name="name" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ attribute name="type" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ attribute name="label" required="false" type="java.lang.String" rtexprvalue="true" %>
<div class="field-plus-label">
  <label for="${name}">${label}</label>
  <input class="field" type="${type}" name="${name}" />
</div>

Tag implementation file for fieldPlusLabel

Adding Layout

We’ve seen how to compose the page structurally from a set of fragments and components. However, what we’ve completely missed so far is the layout. We do want the page to look nice and cozy and therefore we need to define the CSS styles for our fragments and components.

This is where the real trouble begins. Usually a CSS stylesheet is added in the head section of an HTML page. If we do this in our example, the index.jsp page would look like this:

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="/resources/styles.css" />
  </head>
  <body>
    <jsp:include page="header.jsp" />

    <section id="content">
      Hello World!
    </section>

    <jsp:include page="footer.jsp" />
  </body>
</html>

index.jsp

So far so good – but this completely ignores our modularization strategy. Especially in a mobile environment, we want the stylesheet to reflect the fragments and components that we’ve included in our page and do not want a lot of “ballast” to be included. In this example, the stylesheet has to contain all the styles for all available fragments and components. But if we have a large project with a large set of components who all require some kind of CSS styles. Do we really want to include CSS for, let’s say, 100 components, if our page just uses a tiny fraction of this?

Furthermore: If we create a new component, we write the logic in the components tag file. Then, we need to add some content into the global stylesheet. So what should actually be defined within a module context now gets separated into a module (the component) and the global stylesheet file. This certainly isn’t what we intended to do.

So let’s take a look at the alternative: Also separating the stylesheet file according to our fragments and components. This means that for each component we need a corresponding stylesheet file. Once again, let’s take a look at the index.jsp:

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="/resources/global.css" />
    <link rel="stylesheet" type="text/css" href="/resources/fragments/header.css" />
    <link rel="stylesheet" type="text/css" href="/resources/fragments/login-form.css" />
    <link rel="stylesheet" type="text/css" href="/resources/fragments/footer.css" />
    <link rel="stylesheet" type="text/css" href="/resources/components/button.css" />
    <link rel="stylesheet" type="text/css" href="/resources/components/fieldPlusLabel.css" />
  </head>
  <body>
    <jsp:include page="header.jsp" />

    <section id="content">
      Hello World!
    </section>

    <jsp:include page="footer.jsp" />
  </body>
</html>

index.jsp

Now we’ve modularized the stylesheet classes matching our fragment and component structure. However, the way the references are included in our page is still not really optimal: In the index.jsp page we now need to know what components and fragments are used in order to allow the declarations in the header area. One of the main reasons however while slicing the page was to keep the fragments and components as individual as possible.

An alternative would be to not declare the stylesheets in the header area at all but include them into the fragment and component:

<%@ tag description="Displays a field including a label" %>
<%@ attribute name="name" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ attribute name="type" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ attribute name="label" required="false" type="java.lang.String" rtexprvalue="true" %>
<link rel="stylesheet" type="text/css" href="/resources/components/fieldPlusLabel.css" />
<div class="field-plus-label">
    <label for="${name}">${label}</label>
    <input class="field" type="${type}" name="${name}" />
</div>

fieldPlusLabel.tag

Now we’ve put the actual logic (the HTML elements) and the stylesheet declaration closer together and managed to enhance the concept of a module to HTML elements plus stylesheet information. But is this the right way? A stylesheet declaration belongs into the header of an HTML page – not the body.

Additionally, if we include a component more than once, we also include the stylesheet reference more than once – which might lead to a lot of overhead when the document is loaded in a browser.

Resolving the problem

The ideal solution would be to simply declare a required stylesheet file in a component and then let the page itself determine which fragments and components are used in a page and which stylesheet files need to be declared in the header area. Each of our fragments and components could register itself (and its required resources) on some kind of parent instance that keeps track of all the fragments and components referenced during the page evaluation. Then, after the evaluation is complete, it can add only references to the resources actually used.

In traditional JSP however, this isn’t possible. The page will be evaluated from top to bottom, which means that the head area will be evaluated (and therefore all content will be written) long before the first component is ever evaluated in the body area. We’re stuck with the chicken and the egg problem.

JSP however gives us a lot of possibilities to customize the evaluation by writing user defined tags. So, what we really need to do is implement three tags of our own: The HtmlTag, the HeadTag and the BodyTag. Each configured differently to what you would expect for a regular evaluation.

Let’s first view the new version of the index.jsp page:

<!DOCTYPE html>
<%@ taglib prefix="n" uri="http://sapient.com/example/jsp" %>
<n:html>
  <n:head>
    <n:stylesheets />
  </n:head>
  <n:body>
    <jsp:include page="header.jsp" />

    <section id="content">
      Hello World!
    </section>

    <jsp:include page="footer.jsp" />
  </n:body>
</n:html>

index.jsp

As we can see, the traditional HTML elements html, head and body have been replaced by specialized tags from our tag library. This also means that they’re not simply added to the resulting HTML document that will be sent to the client but that they’ll be processed specially. That’s where the “magic” of the tag library comes into play.

The HtmlTag from our tag library (which is references via the n:html tag in the JSP) provides two things: First a registry into which children can add content. Secondly, it provides a modified evaluation process. When the tag is encountered by the JSP parser, the Java implementation of our tag library will first set the mode of the h:html tag to body evaluation and then perform a first evaluation of all its children.

During that evaluation two child tags are encountered: The n:head and n:body tag. Since both of these tags are also in our tag library, both can react with a special processing. During the first run (in body evaluation), the n:head tag will do nothing – no evaluation of children, no output into the JSP document, it will simply stay silent. The n:body tag will perform its regular evaluation (including its children) but will no write any output into the generated HTML output but instead buffer the response for later use.

In this evaluation every fragment and component can declare a stylesheet that it requires like the following example:

<%@ tag description="Displays a field including a label" %>
<%@ attribute name="name" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ attribute name="type" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ attribute name="label" required="false" type="java.lang.String" rtexprvalue="true" %>
<%@ taglib prefix="n" uri="http://sapient.com/example/jsp" %>
<n:link rel="stylesheet" type="text/css" href="/resources/components/fieldPlusLabel.css" />
<div class="field-plus-label">
    <label for="${name}">${label}</label>
    <input class="field" type="${type}" name="${name}" />
</div>

fieldPlusLabel.tag

Here we can see a specialized n:link tag. This implementation differs from a regular evaluation in that it doesn’t generate any content into the resulting JSP document but simply registers the defined stylesheet at the n:head tag for further use.

After the n:html has evaluated its content in body evaluation mode, it will switch to header evaluation mode and perform another evaluation of its children. Now the roles are reversed: The n:head tag (which stayed silent during the body evaluation phase) now becomes active and renders it’s content into its own buffer. During that evaluation, the n:stylesheets tag will request the list of stylesheets that have been previously added during the body evaluation phase. For each of these stylesheets it will now add the corresponding link element into the output. This time the n:body tag stays silent and does nothing, just as the n:head tag did during the body evaluation phase.

Following the second run, the n:html tag combines the buffered output from the header evaluation phase and the body evaluation phase to produce a valid HTML document head and body element. This document will then be sent back to the client.

All in all by performing two evaluation runs, where the head area is rendered after the body area we gain the flexibility of registering stylesheets in the body that will actually be appended to the document head. Now we can view a fragment or component independently and define its content and its stylesheet(s) together while the evaluation is actually done independently in the head and body area.

Future prospects

The same logic that we’ve seen for stylesheets can also be applied to JavaScript blocks. These should also be defined once for each module but be appended together in the head area. Another optimization would be to consolidate the references resources into one big file so that the additional overhead of multiple requests can be minimized.

This article shows that with a few minor changes and the integration of the taglib we’re able to implement a proper modularization and allow a much more concise and logical development model – not only in the backend but also the JSP front-end.

Image by Andrew Morrell




Author
Comments
comments powered by Disqus