Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Thursday, August 25, 2011

CustomTag to generate <script> and <style> tags with absolute path

Generally we write our javascript and css styles in separate file and include them in JSPs using <script> and <style> tags.
To include those resource we can use either relative URL or absolute URL.

If you use absolute URL you need to include the context root name which is not a good practice.
Later if you want to change the context root name you need to update in several places.

If you use relative URL you may need to prefix the path with ../ or ../../ depending on your current URL which tedious process.

To get rid of this problem we can create a custom which takes absolute URL without including context root name and render the corresponding <script> or <style> tags.

package com.sivalabs.core.web.tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * @author K. Siva Prasad Reddy
 */
public class IncludeResourceTag extends TagSupport
{
	private static final long serialVersionUID = 1L;
	
	private String path;
	private String type;//script or style
	
	@Override
	public int doStartTag() throws JspException
	{
		try
		{
			String absolutePath = getAbsolutePath(pageContext);
			String text = null;
			if("script".equalsIgnoreCase(type)
			{
				text = "<script type=\"text/javascript\" src=\""+absolutePath+"\"></script>";
			}
			else if if("style".equalsIgnoreCase(type)
			{
				text = "<LINK href=\""+absolutePath+"\" rel=\"stylesheet\" type=\"text/css\">";
			}
			pageContext.getOut().write(text);
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
		return SKIP_BODY;
	}
	
	@Override
	public int doEndTag() throws JspException
	{		
		return EVAL_PAGE;
	}
	
	public String getPath()
	{
		return path;
	}
	public void setPath(String path)
	{
		this.path = path;
	}
	
	public String getType()
	{
		return type;
	}
	public void setType(String type)
	{
		this.type = type;
	}
	
	public static String getAbsolutePath(PageContext pageContext)
	{
		HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
		String contextRoot = request.getContextPath();
		String cleanPath = stripStartingChars(path, '/');		
		return (contextRoot+"/"+path);
	}
	
	public static String stripStartingChars(String str, char c)
	{
		int len = str.length();
		for (int i = 0; i < len; i++)
		{
			if(str.charAt(i) != c)
			{
				return str.substring(i);
			}
		}
		return str;
	}
	
}

Now we need to create the TLD sivalabs.tld and put it in WEB-INF dir.

<?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">
    
    <description>A tag library for SivaLabs CustomTag handlers.</description>
    <tlib-version>1.0</tlib-version>
    <short-name>SivaLabsTagLibrary</short-name>
    <uri>http://sivalabs.blogspot.com/tags</uri>
    
    <tag>
		<description>Outputs the JavaScript include tag</description>
	    <name>includeResource</name>
		<tag-class>com.sivalabs.core.web.tags.IncludeResourceTag</tag-class>
		<body-content>empty</body-content>
		<attribute>
		    <name>path</name>
		    <required>true</required>
		    <rtexprvalue>true</rtexprvalue>
		</attribute>
		<attribute>
		    <name>type</name>
		    <required>true</required>
		    <rtexprvalue>true</rtexprvalue>
		</attribute>
    </tag>

</taglib>

Now in JSPs you can use the custom tag as follows:

<%@taglib uri="http://sivalabs.blogspot.com/tags" prefix="sl"%>

<html>
<head>
	<sl:includeResource type="style" path="resources/css/style.css"/>
	<sl:includeResource type="script" path="resources/js/util.js"/>
</head>
<body>
..
..
</body>
Now You can always use absolute path irrespective of current URL.

Wednesday, March 23, 2011

JSON processing using Jackson Java JSON Processor

JSON(Javascript Object Notation) is becoming more popular data exchange format.
While developing Web applications using Javascript frameworks like YUI, ExtJS, DOJO etc
we can use either XML or JSON to exchange the data between the client and server.
Normally we get the response from the server in terms of java objects. Then in Servlets or Action classes we need to build the JSON from objects and send back to client.
To build the JSON response from Java object we can use Jackson Java JSON Processor which very much easy to use.

Let us see how we can use Jackson Java JSON Processor to convert a java object into JSON and vice versa.

We can download the jackson-all-1.6.4.jar from http://jackson.codehaus.org.

The key class which does the marshalling and unmarshalling is org.codehaus.jackson.map.ObjectMapper.

Let us create a User javabean as follows:
package com.sivalabs.json;
import java.util.Date;

public class User
{
 private String userId;
 private UserName userName;
 private Date dob;
 
 @Override
 public String toString()
 {
  return "User [dob=" + dob + ", userId=" + userId + ", userName="+ userName + "]";
 }
 //setters and getters
 
}

package com.sivalabs.json;
public class UserName
{
 private String firstname;
 private String middlename;
 private String lastname;
 
 @Override
 public String toString()
 {
  return "UserName [firstname=" + firstname + ", lastname=" + lastname+ ", middlename=" + middlename + "]";
 }
 //setters and getters 
}

Now let us create an instance of User and marshall it into JSON:

ObjectMapper mapper = new ObjectMapper();

UserName userName = new UserName();
userName.setFirstname("Katamreddy");
userName.setMiddlename("Siva");
userName.setLastname("PrasadReddy");

User user = new User();
user.setUserId("1");
user.setUserName(userName);
user.setDob(new Date());

Writer strWriter = new StringWriter();
mapper.writeValue(strWriter, user);
String userDataJSON = strWriter.toString();
System.out.println(userDataJSON);


This will print the User data in JSON format as :
{"userId":"1","userName":{"firstname":"Katamreddy","middlename":"Siva","lastname":"PrasadReddy"},"dob":1300878089906}

Now let us unmarshall the following user data in json format into User Object:

{
 "userId":"100",
 "userName":
  {
   "firstname":"K",
   "middlename":"Siva",
   "lastname":"Prasad"
  },
 "dob":1300878089906
}

String userDataJSON = "{\"userId\":\"100\",\"userName\":{\"firstname\":\"K\",\"middlename\":\"Siva\",\"lastname\":\"Prasad\"},\"dob\":1300878089906}";
User userFromJSON = mapper.readValue(userDataJSON, User.class);
System.out.println(userFromJSON);

This will print the User object as :
User [dob=Wed Mar 23 16:31:29 IST 2011, userId=100, userName=UserName [firstname=K, lastname=Prasad, middlename=Siva]]

The Date value is marshalled as Timestamp which is the default behaviour. If you want you can change the DateFormat as follows:

DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
SerializationConfig serConfig = mapper.getSerializationConfig();
serConfig.setDateFormat(dateFormat);
DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
deserializationConfig.setDateFormat(dateFormat);
mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);

Then the User JSON will be :
{"userId":"1","userName":{"firstname":"Katamreddy","middlename":"Siva","lastname":"PrasadReddy"},"dob":"03-23-2011"}

We can also marshall a Java Object as json into a file as:
mapper.writeValue(new File("user.json"), user);

This will create a file user.json as :
{
"userId":"100",
"userName":
{
"firstname":"K",
"middlename":"Siva",
"lastname":"Prasad"
},
"dob":1300878089906
}

We can build the User object from user,json as:
User user = mapper.readValue(new File("user.json"), User.class);

For more information you can visit http://jackson.codehaus.org .