Tuesday, February 20, 2007

Writing your own JSP Tag Library

Writing your own JSP Tag Library:
This is not too hard to write your own custom tag libraries that can be reused over and over also it is simple enough to do so. Just go step by step and do as said in the tutorial. I have used Tomcat Server so the directory structure may need to be changed.

Step 1:
Write a file with .tld extension that will explain the feature of your tag that you are going to build and place it in tld folder under WEB-INF directory and Name it whatever you want. An example bnk.tld file is :


*********************** Bnk.tld *************************

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>BNKTagLib</shortname>
<info>BNK Tag library</info>
<tag>
<name>Repeater</name>
<tagclass>BNK.TAGS.Repeater</tagclass>
<bodycontent>empty</bodycontent>
<info>
This is a simple BNK tag.
</info>
<!-- Optional attributes -->
<!-- personalized name -->
<attribute>
<name>sqlQuery</name>
<required>true</required>
<rtexpvalue>false</rtexpvalue>
</attribute>
<attribute>
<name>cssClass</name>
<required>false</required>
<rtexpvalue>false</rtexpvalue>
</attribute>
</tag>
</taglib>

********************* Bnk.tld **********************

Step 2:

Create a java file that will explain the function as you want by your tag. For example my tag will create a table that will display all the information returned by a query.
And the query is the parameter passed to my tag with the class applied to the tag. These classes need to be placed within the classes subfolder of WEB-INF directory.

********************* Repeater.java **********************
The Repeater.java file will look like this:


package BNK.TAGS;

import javax.servlet.jsp.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.tagext.*;
import javax.servlet.ServletResponse;
import java.sql.*;
import BNK.TAGS.DataAccess;

public class Repeater extends TagSupport
{

private String sqlQuery;
private String cssClass;
/*
Getter Setter for the attributes
*/
public String getSqlQuery()
{
return this.sqlQuery;
}
public void setSqlQuery(String query)
{
this.sqlQuery = query;
}

public String getCssClass()
{
return this.cssClass;
}
public void setCssClass(String css)
{
this.cssClass = css;
}




public int doStartTag() throws JspTagException
{
getSqlQuery();
DataAccess da = new DataAccess(this.sqlQuery);

//DataAccess.DataAccessClassName();
//da.sqlQuery = this.sqlQuery;
ResultSet rs = da.DataAccessQueryFunction();

JspWriter out = pageContext.getOut();
try
{

if (rs != null)
{
int i = 1;

out.println("<table cellpadding='2' border='1' cellspacing='0'" + "class=" + "'"+ cssClass +"'" + ">");

while (rs.next())
{

out.println("<tr>");

out.println("<td>");
out.println(rs.getString("SKILL_ID"));
out.println("</td>");

out.println("<td>");
out.println(rs.getString("SKILL_NAME"));
out.println("</td>");

out.println("</tr>");
i ++;
}

out.println("</table>");
}
else
{
out.println(rs);
}
}
catch (Exception ex)
{
throw new JspTagException("All is not well in the world." + ex.toString() );
}
// Evaluate the body if there is one
return SKIP_BODY;
}

/**
* doEndTag is called by the JSP container when the tag is closed
*/
public int doEndTag(){
try {
//JspWriter out = pageContext.getOut();
//out.println("</table>");
} catch (Exception ex){
throw new Error("All is not well in the world.asdasd");
}
return SKIP_BODY;
}
}
********************* Repeater.java **********************



Also I have used a reference to the DataAccess class that will provide the interface to perform queries to the database and will return a ResultSet containing the result.
This is also need to be placed in the same directory where we put our Repeater.java file.

********************* DataAccess.java *********************
package BNK.TAGS;

import java.sql.*;

public class DataAccess
{
private static String URL = "jdbc:mysql://localhost:3306/Testing?autoReconnect=true";
private static String user = "userName";
private static String password = "password";

public ResultSet results = null;
public String error = "";
public String sqlQuery = "";

public DataAccess(String sql)
{
this.sqlQuery = sql;
}

public ResultSet DataAccessQueryFunction()
{
error += sqlQuery;
try
{
Class.forName ("com.mysql.jdbc.Driver").newInstance();
}

catch (Exception e)
{

}
finally
{
}
try
{
Connection connection = DriverManager.getConnection(URL, user, password);


Statement statement = connection.createStatement();

results = statement.executeQuery(this.sqlQuery);
}
catch (SQLException e)
{
System.err.println("Exception " +e.toString());
error += "<br />" + e.toString();
}

return results;
}
}



********************* DataAccess.java *********************

Step 3:
Calling the tag………………

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>

<%--
The next line calls our bnk.tld file so that the repeater control will be available here.
--%>

<%@ taglib uri="/WEB-INF/tld/bnk.tld" prefix="bnk" %>

<!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=UTF-8">
<title>BNK Sample Tag Library</title>
</head>
<body>

<h1> BNK Sample Tag Library </h1>

<bnk:Repeater sqlQuery = "select * from tablename" cssClass="tableClass" />

</body>
</html>

Just watch the output on your web page.

So now you can use this tag wherever required.
Isn’t it simple enough !