How to create a custom Tag in Java?

Here is how..

This is the directory layout I have:

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
 
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>biz.tugay</groupId>
    <artifactId>customTagEx</artifactId>
    <packaging>war</packaging>
 
    <version>1.0-SNAPHOST</version>
 
    <name>customTagEx Maven Webapp</name>
    <url>http://maven.apache.org</url>
 
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>javax.servlet.jsp.jstl-api</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
 
    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
 
    <build>
        <finalName>customTagEx</finalName>
    </build>
 
</project>

web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
 
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <page-encoding>UTF-8</page-encoding>
            <scripting-invalid>true</scripting-invalid>
            <trim-directive-whitespaces>true</trim-directive-whitespaces>
            <default-content-type>text/html;charset=UTF-8</default-content-type>
        </jsp-property-group>
    </jsp-config>
 
</web-app>

selectTag.tld
<?xml version="1.0" encoding="UTF-8"?>
 
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                            http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">
 
    <tlib-version>1</tlib-version>
    <short-name>formTemplates</short-name>
    <uri>http://www.tugay.biz/custom/selecttag</uri>
 
    <tag>
        <name>select</name>
        <tag-class>biz.tugay.taghandler.SelectTagHandler</tag-class>
        <body-content>empty</body-content>
 
        <attribute>
            <name>size</name>
            <required>true</required>
            <type>int</type>
        </attribute>
 
        <attribute>
            <name>name</name>
            <required>true</required>
            <type>java.lang.String</type>
        </attribute>
 
        <attribute>
            <name>optionList</name>
            <required>true</required>
            <rtexprvalue>true</rtexprvalue>
        </attribute>
 
    </tag>
 
</taglib>

SelectTagHandler.java
package biz.tugay.taghandler;
 
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 8/5/2016
 * Time: 9:02 PM
 */
public class SelectTagHandler extends SimpleTagSupport {
 
    private List<String> optionList;
    private String name;
    private int size;
 
    @SuppressWarnings("unused")
    public void setOptionList(List<String> optionList) {
        this.optionList = optionList;
    }
 
    @SuppressWarnings("unused")
    public void setName(String name) {
        this.name = name;
    }
 
    @SuppressWarnings("unused")
    public void setSize(int size) {
        this.size = size;
    }
 
    @Override
    public void doTag() throws JspException, IOException {
        final PageContext pageContext = (PageContext) getJspContext();
        final JspWriter out = pageContext.getOut();
        out.print("<select name='" + name + "' size='" + size + "'>");
        for (String optionValue : optionList) {
            out.print("<option value='" + optionValue + "'>" + optionValue + "</option>");
        }
        out.print("</select>");
    }
}

EncodingFilter.java
package biz.tugay;
 
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 8/5/2016
 * Time: 8:16 PM
 */
 
@WebFilter(urlPatterns = "/*")
public class EncodingFilter implements Filter {
 
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        if (request.getCharacterEncoding() == null) {
            request.setCharacterEncoding("utf-8");
        }
        chain.doFilter(request, response);
    }
 
    public void destroy() {
    }
}

MyServlet.java
package biz.tugay;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
/**
 * User: Koray Tugay (koray@tugay.biz)
 * Date: 8/5/2016
 * Time: 8:15 PM
 */
 
@WebServlet(urlPatterns = "/")
public class MyServlet extends HttpServlet {
 
    private final List<String> colors = new ArrayList<String>();
 
    @Override
    public void init() throws ServletException {
        super.init();
        colors.add("Brown");
        colors.add("Red");
        colors.add("Green");
        colors.add("Black");
        colors.add("Pink (Color of fashion)");
    }
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        req.setAttribute("colorList", colors);
        req.getRequestDispatcher("/hello.jsp").forward(req, resp);
    }
}

hello.jsp
<%--
    User: Koray Tugay (koray@tugay.biz)
    Date: 8/5/2016
    Time: 9:12 PM
--%>
 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="customSelect" uri="http://www.tugay.biz/custom/selecttag" %>
 
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Hello</title>
</head>
<body>
<customSelect:select size="1" name="color" optionList="${requestScope.colorList}"/>
</body>
</html>


In Action


Generated page source is as follows:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Hello</title>
</head>
<body>
    <select name='color' size='1'>
        <option value='Brown'>Brown</option>
        <option value='Red'>Red</option>
        <option value='Green'>Green</option>
        <option value='Black'>Black</option>
        <option value='Pink (Color of fashion)'>Pink (Color of fashion)</option>
    </select>
</body>
</html>