Customising Struts2 JSP tags

Here is a possible way to customise the JSP taglib provided by the Struts2 framework.

The topics covered in this post are:

  • add a custom attribute to a given tag (e.g. TextField)
  • customise the Freemarker template to modify the generated HTML code
  • define new themes and templates
  • generate the new TLD for the customised version of the taglib
  • deploy it in a web application (WAR file)

The sample I have created implements a read-only version of the Struts2 JSP taglib: if a given attribute (i.e. viewMode) is set to true then a simple label (plain text) is rendered, instead of the html code for the input type, making the information on the form not editable.

This, in principle, achieves the same purpose as the disabled attribute but it looks much nicer on the web form.

Introduction

Few words about the elements of the Struts2 UI component framework should help to understand better the scenario.

JSP Tag: implementation of the JSP tag (e.g TextFieldTag). Notice Struts2 has also Velocity and FreeMarker tags

UI Component: actual implementation of the behavior of the component (e.g TextField)

Template: FreeMarker template which renders the html markup (e.g. <input type=”text”….)

Theme: collection of templates (e.g. simple or ajax)

Struts2 UI layer

Create custom TextFieldTag

Extend the org.apache.struts2.views.jsp.ui.TextFieldTag and add your new code.

public class TextFieldTag extends
    org.apache.struts2.views.jsp.ui.TextFieldTag {
  private static final long serialVersionUID = 5811285953670562288L;
  protected String viewmode;
  public Component getBean(ValueStack stack, HttpServletRequest req,
                             HttpServletResponse res) {
    return new TextField(stack, req, res);
  }
  protected void populateParams() {
    super.populateParams();
    TextField textField = ((TextField) component);
    textField.setViewmode(viewmode);
  }
  public void setViewmode(String viewmode) {
    this.viewmode = viewmode;
  }
}

This is the actual implementation of the new JSP tag (which I called with the same name – TextFieldTag – but you don’t have to).

Create custom TextField

Extend the org.apache.struts2.components.TextField and add your new code.

@StrutsTag(name = "textfield",
   tldTagClass = "com.mycompany.struts2.views.jsp.ui.TextFieldTag",
description = "Render an HTML input field of type text",
allowDynamicAttributes = true)
public class TextField extends org.apache.struts2.components.TextField {

    protected String viewmode;

    public TextField(ValueStack stack, HttpServletRequest request,
                     HttpServletResponse response) {
        super(stack, request, response);
    }

    protected void evaluateExtraParams() {
        super.evaluateExtraParams();

        if (viewmode != null) {
            addParameter("viewmode", findValue(viewmode, Boolean.class));
        }
    }

    @StrutsTagAttribute(description = "Viewmode", type = "Boolean",
                                               defaultValue = "false")
    public void setViewmode(String viewmode) {
        this.viewmode = viewmode;
    }
}

Now this is interesting: Struts2 taglib architecture involves the UI components as the base for managing the actual behaviour of the tags. The new component (which again I called with the same name) includes the Struts2 annotations required to document the tags:

@StrutsTag: annotation for marking a Struts tag

@StrutsTagAttribute: annotation for marking an attribute of a Struts tag

Define your own templates (theme)

The actual HTML generated by the JSP tag is stored externally to the tag, in facts it uses FreeMarker, a powerful Java Template Engine.

Browse through the Struts2 core source (/core/src/main/resources/template) to see the provided FreeMarker templates. In my sample I have created a new theme which extends the Struts2 simple theme:

  • create a folder /resources/template/myTheme
  • copy the templates you want to modify (e.g text.ftl, select.ftl, etc..)
  • create a theme.properties which states parent=simple (theme inheritance)

Let’s say we want to modify text.ftl to display a simple text when the viewmode attribute is set to true.

<#if parameters.viewmode?default(false)>
  <#-- viewmode is true: print simple text -->
  <@s.property value="parameters.nameValue"/><#t/>
<#else>
  <#-- viewmode is false (or not provided): invoke parent -->
  <#include "/${parameters.templateDir}/simple/text.ftl" />
</#if>

Generate the TLD file

The TLD is generated with the Tobago plugin.

Deploy taglib in your Web application

Just drop the new taglib jar file in the application WEB-INF/lib (or better define the Maven dependency!).

Additionally in the Web application struts.properties define

struts.ui.theme = myTheme

This allows to set myTheme as the default theme used by the application.

Code the JSP

Finally to use the customised Struts2 tags in your JSP:

<%@ taglib prefix="ss" uri="/extended-struts2-tags" %>
....
....
<ss:textfield name="name" viewmode="true" size="35" />
<ss:select name="type"
           viewmode="true"
           list="allTypes"
           listKey="id"
           listValue="name"/>

Normally the value of the “viewmode” attribute can be set in the Action class, using a boolean (for instance the return of a method which verifies the user privileges).

Download the sample taglib

Download the sample tag lib.

It is a Maven2 project which includes the Java code, the modified Freemarker templates and the POM.xml.

10 Responses to Customising Struts2 JSP tags

  1. Nitish Bansal says:

    Hi,

    I wanted to add custom tag which take String.Can you tell me the changes i have to done.

  2. Pratik says:

    Beppe – Thanks for this post. It really helped me a lot.
    Can you suggest me some Documentation about this so that I can get insight about the way struts tags works.

    • Hello and thanks for visiting 🙂

      The Struts2 tags documentation is pretty good, you should be able to get all info you need to use the tags.
      The extension I built is basically a customisation-by-extension, the source is self-explanatory.

  3. Hernán says:

    Hi, how do I use Tobago to create the TLD file, I have followed the example but I cannot use the tag I created with s:component, I suppose I have to create the TLD file as you did, and then use the tag as an extension…

  4. Hernán says:

    Hello I would like to know what other any step do I have to do if I want to create a freemarker tag insted of a JSP tag. I need to create a tripleselect tag, I have done it but I haven’t created the TLD, is the TLD necessary for a Freemarker tag?

  5. Beppe says:

    There is no textfield.ftl: the template for the textFieldTag is called text.ftl
    Apologies if the image (boxes2.jpg) is confusing: it should read “Text Template” instead “TextField” Template

  6. Justin J says:

    I can’t find the textfield.ftl to overwrite. Where is it?

  7. Beppe says:

    Hello
    it’s in the pom.xml (sample taglib)

    org.apache.struts
    struts2-core
    2.1.6

    B

  8. Alex Rios says:

    Hello, what version of struts 2 you are using?

Leave a reply to Pratik Cancel reply