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