JSP Tag Library with Scala (TagLib Resurrection User Guide)

Igor Khiblin on
Java developer at ELEKS

What is dead may never die!
― George R. R. Martin, A Song of Ice and Fire

One can argue over what is dead and what is not for a long time. You can argue over anything, the main question is: is it worth doing that when you need to act? Necromancy has always been condemned, and that is actually right. But the cases are different. What would you do when you need the ‘dead’ to go?

JSTL overview

JSP Tag Library is a means of encapsulation of certain actions, which can be applied in Java Server Pages. Also, it should be mentioned that this is an effective means of code reusability, because the created tags can be used multiple times. And those are the things that may be very useful for Java developers working on the web.

It is worth noting that the library of custom tags is not quite a specific thing, but a logical supplement to JSP Standard Tag Library (although it may be vice versa). In fact, it would be strange to call something standard if there was not something non-standard. By the way, somehow it happened that when I heard about TagLib, I was not familiar with JSTL and immediately thought: “Aha, dear foreach, now I’ll implement you once and for all,” but it turned out that it had been already done before me (I cannot say I was very upset). That is why, not to reinvent the wheel, TagLib should be considered from the JSTL view.

To put it mildly, JSTL is an ancient technology, it appeared as early as in Java 1.4, so, if you are interested in details, the manuscripts documentation is always at your disposal. In turn, I will just give a quick overview of the things I’ve found interesting.

Thus, the standard tag library consists of several groups separated by functionality that is implemented by their components.

Core Tags

This group contains expression tags, remove tags (removing scoped variables), conditional tags, the already mentioned foreach, the redirect tag and some more tags the information about which you can find out by yourself.

Formatting tags

This group contains tags used for formatting and output of date, time and text, as well as tags dealing with localization from resources, such as the timeZone tag.

SQL tags

Hmm, don’t even know what to add. In general, the name of this group and <query>, <update> and <transaction> tags should speak for themselves.

XML tags

Pretty much the same as Core tags, but for XML. Except perhaps for the parse tag used to parse XML data from attribute or from tag body.

JSTL functions

These are not exactly tags. Or rather, these are not tags at all. This is just a set of functions used to work with string data. I think that you are familiar with such things as contains, substring, trim… Well, I told you.

Creating a custom tag library

Generally speaking, to create your own tag library you don’t have to do much. Namely, you have to do two things:

  1. Create a .tld file, which is essentially a XML document and describes the structure of your TagLib.
  2. Create a handler class that will describe the internal structure of the tag.

This is it in general. Now let’s consider in more detail what you need to do to come from nothing to the simplest, but working tag.

Tag Library Descriptor

A TLD should be created in the /META-INF/ directory or in any other of its subdirectories. The one, who has read the documentation or tutorial on TagLib, may note that the location of a TLD file depends on how we’re going to pack the project, and will be absolutely right. The method described by me is suitable for the case when the project is packed in a JAR, but if you choose the way of WAR, then the TLD must be in the /WEB-INF/ directory. My choice is explained by the fact that, in my opinion, it’s much more logical, when the library is in a JAR file and can be connected to any project, rather than created and used only in one.
Here is a simple example of a TLD:

<?xml version="1.0" encoding="UTF-8" ?>
<taglib
     xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1">
     <tlib-version>1.0</tlib-version>
     <short-name>scltg</short-name>
     <uri>http://taglib.test.eleks.com</uri>
     <tag>
          <name>smpl</name>
          <tag-class>com.eleks.test.taglib.SimpleHandler</tag-class>
          <body-content>empty</body-content>
     </tag>
</taglib>

All that interests us here is the <uri> tag, the content of which will help us in declaring the library on the JSP and the <tag> tag, remarkable for its almost recursivity, and that it still describes something that we are striving for so hard. In <tag-class>, you should indicate the fully qualified name of the tag handler class.
It should be added that there is a way of describing tags by tag files, but for convenience, I’ve done what I’ve done. If anyone is interested, they can look for the alternative option by themselves.

Tag handler class

There you go. We’ve got around to it. Get ready, there will be a surprise right now.

package com.eleks.test.taglib
import java.io.IOException
import javax.servlet.jsp.tagext.SimpleTagSupport
import javax.servlet.jsp.JspException
class SimpleHandler extends SimpleTagSupport {
     @throws [IOException]
     @throws [JspException]
     override def doTag() {
          getJspContext().getOut()
               .write("Hello, I’m a simple Scala tag!");
     }
}

Strange annotation, strange override def… Yep, it’s Scala.
For those who are greatly worried, I’m showing the same handler code for Java:

public class SimpleHandler extends SimpleTagSupport {

     public void doTag() throws JspException, IOException {
          getJspContext().getOut()
               .write("Hello, I’m a simple Java tag!");
     }
}

I inherited from SimpleTagSupport to facilitate my work. In fact, there is an array of possible outcomes, and as always you can view the documentation for details.

That’s all, it seems. I will also say a few words about how it all works, so you know which way to go.
In order to combine Java and Scala, a separate Maven project was created, which, as I have said, was compiled in a jar file. You can google for tutorials, so I won’t go into details, not to increase the entropy. Ok, but as for Pom.xml ― only things concerning Scala:

<properties>
     <scala.version>2.10.2</scala.version>
</properties>
<repositories>
     <repository>
          <id>scala-tools.org</id>
          <name>Scala-Tools Maven2 Repository</name>
          <url>http://scala-tools.org/repo-releases</url>
     </repository>
</repositories>
<pluginRepositories>
     <pluginRepository>
          <id>scala-tools.org</id>
          <name>Scala-Tools Maven2 Repository</name>
          <url>http://scala-tools.org/repo-releases</url>
     </pluginRepository>
</pluginRepositories>
<dependencies>
     <dependency>
          <groupId>org.scala-lang</groupId>
          <artifactId>scala-library</artifactId>
          <version>${scala.version}</version>
     </dependency>
<dependencies>
<build>
     <sourceDirectory>src/main/scala</sourceDirectory>
     <testSourceDirectory>src/test/scala</testSourceDirectory>
     <plugins>
          <plugin>
               <groupId>org.scala-tools</groupId>
               <artifactId>maven-scala-plugin</artifactId>
               <executions>
                    <execution>
                         <phase>compile</phase>
                         <goals>
                              <goal>compile</goal>
                              <goal>testCompile</goal>
                         </goals>
                    </execution>
               </executions>
               <configuration>
                    <scalaVersion>${scala.version}</scalaVersion>
                    <args>
                         <arg>-target:jvm-1.5</arg>
                    </args>
               </configuration>
          </plugin>
     </plugins>
</build>

To use the tag library I’ve created another Maven project, which stated the following in the pom.xml file:

<dependencies>
     <dependency>
          <groupId>com.eleks.test</groupId>
          <artifactId>taglib</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <scope>import</scope>
     </dependency>
</dependencies>

Using with JSP

So, here is an example of JSP using the library written by us:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://taglib.test.eleks.com" prefix="scltg" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
     <head>
          <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
          <title>Insert title here</title>
     </head>
     <body>
          <scltg:smpl/>
     </body>
</html>

The important points are highlighted in grey. The first thing is what I’ve already mentioned — we declare our TagLib and specify a prefix, with which we will refer to tags. And the second thing is actually our tag call: prefix, colon, tag name. As you see, the tag has no body, it’s just because the following thing was declared in the TLD:

<body-content>empty</body-content>

That’s it.

Pre-conclusion

It was really cool. Moreover, it works. How useful is it? Well, I don’t know. It’s useful the way something useful has to be. Neither more nor less.

Conclusion

Many that live deserve death. And some that die deserve life. Can you give it to them? Then do not be too eager to deal out death in judgement.
― J.R.R. Tolkien, The Fellowship of the Ring

Technologies become obsolete. This is a fact. Those which had no time to become obsolete (and sometimes even just to grow into something really demanded) are forgotten, lost, discarded with outbursts : “But why do we need it, after all, there is the ‘technology name’.” The fashion in the world of IT is as whimsical as any other fashion. And there’s nothing you can do about that. Not so long ago, PC came to replace huge computing machines with access through terminals, then they were followed by laptops, then by netbooks and tablets, then cloud technologies came. The circle has been closed?

Nevertheless, and even more, there is always a need to go back to something old. Why not do it using something new? Maybe I gave the answer for the case of the JSP Tag Library.

tags

Comments