Custom Annotation Processing for Web Application

To know about how to declare custom annotations, what are the properties and options please refer to this post, which is very clear and simple.

What I will be discussing here is after you have declared and used your custom annotations, how to process them in run time for any web application.
Our aim is to find all the annotated classes and process their annotations at the time of servlet initialization i.e. in the init() method of the servlet. After getting those annotation attribute values we will be printing them just for this example. Lets build our custom annotation and one class annotated with that.

package com.annotated.classes.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Task {

	String id();

	String name();

	String uri();
}
package com.annotated.classes.example;

@Task(
		id = "Task1", 
		name = "Task1", 
		uri = "#task1"
)
public class Task1 {

}

The first thing we need to learn is how to get the class files from ‘WEB-INF/classes’ folder as well as all the classes from jars residing in ‘WEB-INF/lib’ folder. We are going to use ‘ServletContext’ to get the list of class files. We will be looking for all the class files under a specified package. So lets declare it at the very beginning with some other top level variables.

private String packageName = "com.annotated.classes";
private String packageNamePath = packageName.replace(".", "/");
private String classesPath = "/WEB-INF/classes/" + packageNamePath;
private String jarsPath = "/WEB-INF/lib";

‘WEB-INF/classes’
The ‘getResourcePaths’ method of ‘ServletContext’ gives us a list of resources (.class files and folders) under a specified path. If we encounter a sub folder under the path we need to get resources from that folder also. So its better to have a recursion to traverse the folder structure to get all the .class files.

private Set<String> getClassFiles(String path, ServletContext context, Set<String> finalList) {

	Set<String> resourceSet = context.getResourcePaths(path);
	if (resourceSet != null) {
		for (Iterator<String> iterator = resourceSet.iterator(); iterator.hasNext();) {
			String resourcePath = (String) iterator.next();

			if (resourcePath.endsWith(".class")) {
				finalList.add(resourcePath.substring(resourcePath.indexOf(packageNamePath)));
			} else {
				getClassFiles(resourcePath, context, finalList);
			}
		}
	}
	return finalList;
}

The method will be called like

ServletContext context = servletConfig.getServletContext();
Set<String> classFiles = new HashSet<String>();
classFiles = getClassFiles(classesPath, context, classFiles);

‘WEB-INF/lib’
Here we will be opening each jar we have in our lib folder and scan for the same package declared above and get the list of class files under them.

Set<String> libJars = context.getResourcePaths(jarsPath);
Set<String> allClasses = new HashSet<String>();

if (libJars != null) {
	for (String jar : libJars) {
		JarInputStream jarInputStream = new JarInputStream(context.getResourceAsStream(jar));
		JarEntry jarEntry;

		while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
			if ((jarEntry.getName().startsWith(packageNamePath)) && (jarEntry.getName().endsWith(".class"))) {
				allClasses.add(jarEntry.getName());
			}
		}
	}
}

Now we have all the class files we expect to have annotated with our custom annotation. To find what classes are annotated with our annotation we may use java reflection. But here we will be using Javassist as its much lighter. The tutorial can be found here and download from here.

First we need to add our class paths to the ClassPool object to be able to get the reference of the classes.

ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(CustomAnnotationProcessor.class));
pool.appendClassPath(jarsPath);

The CtClass object from Javassist will give us the reference of the class. It expects the input as the fully qualified class name. We need to do some string manipulation to get the fully qualified class names from the list we got from above. Once we have the CtClass object we can check for its annotations and if present get the instance of the annotation with attribute values.

CtClass cc = pool.get(classFile);
Object[] annotations = cc.getAnnotations();
for (Object annotation : annotations) {
	if (annotation instanceof Task) {
		Task task = (Task) annotation;
		
		System.out.println("Id : " + task.id());
		System.out.println("Name : " + task.name());
		System.out.println("URI : " + task.uri());
	}
}

And with all it together we have

package com.annotated.classes.annotation;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

public class CustomAnnotationProcessor {

	private String packageName = "com.annotated.classes";
	private String packageNamePath = packageName.replace(".", "/");
	private String classesPath = "/WEB-INF/classes/" + packageNamePath;
	private String jarsPath = "/WEB-INF/lib";

	public void processAnnotations(ServletConfig servletConfig) {

		ServletContext context = servletConfig.getServletContext();
		Set<String> classFiles = new HashSet<String>();
		classFiles = getClassFiles(classesPath, context, classFiles);

		Set<String> libJars = context.getResourcePaths(jarsPath);
		Set<String> allClasses = new HashSet<String>();

		if (!classFiles.isEmpty()) {
			allClasses.addAll(classFiles);
		}

		try {
			// Javassist to get classes from class paths
			ClassPool pool = ClassPool.getDefault();
			pool.insertClassPath(new ClassClassPath(AnnotationProcessor.class));
			pool.appendClassPath(jarsPath);

			// Get classes from Jar files
			if (libJars != null) {
				for (String jar : libJars) {
					JarInputStream jarInputStream = new JarInputStream(context.getResourceAsStream(jar));
					JarEntry jarEntry;

					while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
						if ((jarEntry.getName().startsWith(packageNamePath)) && (jarEntry.getName().endsWith(".class"))) {
							allClasses.add(jarEntry.getName());
						}
					}
				}
			}

			// Read Annotations
			for (String classFile : allClasses) {

				classFile = classFile.replace("/", ".").substring(0, classFile.indexOf(".class"));

				CtClass cc = pool.get(classFile);
				Object[] annotations = cc.getAnnotations();
				for (Object annotation : annotations) {
					if (annotation instanceof Task) {
						Task task = (Task) annotation;

						System.out.println("Id : " + task.id());
						System.out.println("View : " + task.viewClass());
						System.out.println("URI : " + task.uri());
					}
				}
			}
			
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private Set<String> getClassFiles(String path, ServletContext context, Set<String> finalList) {

		Set<String> resourceSet = context.getResourcePaths(path);
		if (resourceSet != null) {
			for (Iterator<String> iterator = resourceSet.iterator(); iterator.hasNext();) {
				String resourcePath = (String) iterator.next();

				if (resourcePath.endsWith(".class")) {
					finalList.add(resourcePath.substring(resourcePath.indexOf(packageNamePath)));
				} else {
					getClassFiles(resourcePath, context, finalList);
				}
			}
		}
		return finalList;
	}

}

IceFaces Cancel Button with immediate true

Putting ‘immediate=”true”‘ in a cancel button in an icefaces form will pass the validation process. But to get old form values in place we have to do something in our back end.
After searching a whole lot of pages I found two articles to get the solution.

https://cwiki.apache.org/confluence/display/MYFACES/Clear+Input+Components
https://cwiki.apache.org/confluence/display/MYFACES/How+the+immediate+attribute+works

One way to do this is to re render the view to get old form values. But in my case the composite view has so many flags to set particular rendering of the components. So just to refresh the page was not working for me. What I did is to set the backing bean value to its old values and call a clear() method on all my UI components needed to be reset.

public void cancelCustomer(ActionEvent event) {
	Customer customer = orderEditBackingBean.getSelected().getCustomer();

	orderEditBackingBean.getSelected().setCustomerId(customer.getCustomerId());
	orderEditBackingBean.getSelected().setContactName(customer.getCustomerFirst());
	orderEditBackingBean.getSelected().setCompanyName(customer.getCompanyName());
	orderEditBackingBean.getSelected().setContactPhone(customer.getContactPhone());
	orderEditBackingBean.getSelected().setAddress1(customer.getAddress1());
	orderEditBackingBean.getSelected().setAddress2(customer.getAddress2());
	orderEditBackingBean.getSelected().setCity(customer.getCity());
	orderEditBackingBean.getSelected().setState(customer.getStateCode());
	orderEditBackingBean.getSelected().setZip(customer.getZipCode());
	orderEditBackingBean.getSelected().setCorpNode(customer.getCorpNode());
	
    event.getComponent().getParent().getParent().getParent().getChildren().clear();
    
	orderEditBackingBean.getSelected().setCustomerDisable(true);
	orderEditBackingBean.getSelected().setEditButtonVisible(true);
	orderEditBackingBean.getSelected().setSubmitButtonVisible(false);
}

Pentaho Dashboard – Show Message if No Data Available

I do not know how to achieve this in ‘jFreeChartComponent’ or in the CCC (community chart component). My solutions are built with action sequence and that’s where I needed to have this feature.

The concept is simple. After getting the result set from the database through ‘SQLLookupRule’ component, I am checking if the result set length is greater than zero or not. The ‘JavascriptRule’ component is used to determine the length of the result set. And then using the ‘if’ condition I am generating the chart or just a simple string saying ‘No Result Found’.

So my action sequence output will be

<outputs> 
	<image-tag type="string"/>  
	<output type="string"/>
</outputs>

The ‘JavascriptRule’ component to check the result set is simple

<action-definition>
	<component-name>JavascriptRule</component-name>
	<action-type>JavaScript</action-type>
	<action-inputs>
		<queryResult type="result-set" mapping="query_result"/> 
	</action-inputs>
	<action-outputs>
		<noData type="string"/>
	</action-outputs>
	<component-definition>
		<script><![CDATA[noData = "false";
		if(queryResult.getRowCount() == 0){
			noData = "true";
		}]]></script>
	</component-definition>
</action-definition>

So depending upon the result set name my output variable ‘noData’ will be “true” or “false”. And based on the ‘noData’ value I am generating respective output

<actions> 
	<condition><![CDATA[noData == "false"]]></condition>  
	<action-definition> 
		<component-name>ChartComponent</component-name>
		<action-type>Pie Chart</action-type>
		<action-inputs> 
			<chart-data type="result-set" mapping="query_result"/>  
		</action-inputs>
		<action-outputs> 
			<image-tag type="string"/> 
		</action-outputs>
		<component-definition> 
			<chart-attributes> 
			<chart-type>PieChart</chart-type>  
			<title>chartTitle</title>  
			<title-position>top</title-position>  
			<display-labels>false</display-labels>  
			<url-template>javascript:;</url-template>  
			<paramName>label</paramName>  
			<width>350</width>  
			<height>350</height> 
			</chart-attributes> 
		</component-definition> 
	</action-definition>
</actions>
  
<actions>
	<condition><![CDATA[noData == "true"]]></condition>
	<action-definition>
		<component-name>JavascriptRule</component-name>
		<action-type>JavaScript</action-type>
		<action-outputs>
			<output type="string"/>
		</action-outputs>
		<component-definition>
			<script><![CDATA[output = "No Result Found";]]></script>
		</component-definition>
	</action-definition>
</actions>

Pentaho Dashboard – Export Chart Data

To give user an option to export any chart data in csv format is very easy when you use ‘jFreeChartComponent’ to generate the chart. The ‘caption’ option in the chart configuration is used to put a ‘detail’ link beneath every chart. The ‘detail’ link opens up the options to export the chart data and some others.

I didn’t like the  ‘jFreeChartComponent’ because of many reasons. If I do not use mdx queries, I have to expose my normal sql queries in javascript while using ‘jFreeChartComponent’. Also I am not sure how I can make some reusable components while I use ‘jFreeChartComponent’.

So I was looking for a good solution where I can give my dashboard users option to download the chart data in csv format while I generate those chart using action sequences (xaction chartcomponent). I could have used the new Pentaho CCC (community chart component), but my solution was too complex to use CCC’s auto generated code. I searched for a solution in Pentaho’s forums but there was no solutions for this. I started one thread there asking for a suggestion, but nobody could come up with any solution. So then I started thinking for a solution by myself.

It was not possible that the same action sequence will be able to provide me the chart as well as the option to generate csv file from the data. So I broke down the solution into three different parts.

  1. One action sequence is generating the result set querying the database (chartData.xaction)
  2. One action sequence is using ‘SubActionComponent’ and getting the result set from (1) and then generating the chart based on the data using ‘ChartComponent’ (chart.xaction)
  3. The other action sequence is again using ‘SubActionComponent’ to get the result set from (1) and then  using ‘JFreeReportComponent’ to generate the csv file. (csvChart.xaction)

So the part of my action sequence generating the chart looks like

<action-definition>
	<component-name>SubActionComponent</component-name>
	<action-type>Render current Data</action-type>
	<action-inputs/>
	<action-outputs>
		<query_result type="result-set" mapping="query_result"/>
	</action-outputs>
	<component-definition>
		<solution><![CDATA[app]]></solution>
		<path><![CDATA[dashboards/SingleChart]]></path>
		<action><![CDATA[currentData.xaction]]></action>
	</component-definition>
</action-definition>

<action-definition>
	<component-name>ChartComponent</component-name>
	<action-type>Pie Chart</action-type>
	<action-inputs>
		<chart-data type="result-set" mapping="query_result"/>
	</action-inputs>
	<action-outputs>
		<image-tag type="string"/>
	</action-outputs>
	<component-definition>
		<chart-attributes>
			<chart-type>PieChart</chart-type>
			<title>chartTitle</title>
			<title-position>top</title-position>
			<display-labels>false</display-labels>
			<url-template>javascript:;</url-template>
			<paramName>label</paramName>
			<width>350</width>
			<height>350</height>
		</chart-attributes>
	</component-definition>
</action-definition>

Like the same way the part of the action sequence  generating the csv looks like

<action-definition>
	<component-name>SubActionComponent</component-name>
	<action-type>Render current Data</action-type>
	<action-inputs/>
	<action-outputs>
		<query_result type="result-set" mapping="query_result"/>
	</action-outputs>
	<component-definition>
		<solution><![CDATA[app]]></solution>
		<path><![CDATA[dashboards/SingleChart]]></path>
		<action><![CDATA[currentData.xaction]]></action>
	</component-definition>
</action-definition>

<action-definition>
	<component-name>JFreeReportComponent</component-name>
	<action-type>Pentaho Report</action-type>
	<action-inputs>
		<data type="result-set" mapping="query_results"/>
	</action-inputs>
	<action-resources>
		<report-definition type="resource"/>
	</action-resources>
	<action-outputs>
		<report type="content"/>
	</action-outputs>
	<component-definition>
		<output-type>csv</output-type>
	</component-definition>
</action-definition>

So as the action sequences are ready I have to call them in my template file. I am here using ‘ExecuteXaction’ component to call the csvChart.xaction, but before that rendering the chart from the template file is very straight forward.

components[components.length] = {
	name : "currentChart",
	type : "XactionComponent",
	solution : solution,
	path : path,
	action : "chart.xaction",
	listeners : [],
	parameters : [],
	htmlObject : "renderedChart",
	executeAtStart : true,
	postExecution: function(){
		Dashboards.fireChange(csvListner, "csvListner");
	}
};

and the ‘ExecuteXaction’ is listening the ‘csvListner’ and fires the event as soon as the chart is loaded.

components[components.length] = {
	name : "chartCsv",
	type : "ExecuteXaction",
	solution : solution,
	path : path,
	action : "csvCchart.xaction",
	listeners : [currentCsvListner],
	parameters : [],
	htmlObject : "downLoadData",
	label: "Download Data",
	executeAtStart : false
};

The ‘ExecuteXaction’ renders a button saying ‘Download Data’ and once clicked the csv download option comes and asks user to save the file.

Facebook Canvas App Authentication – Java

Facebook will stop supporting canvas FBML apps very soon. So this article only talks about iFrame apps build in Java and using OAuth 2.0 protocol. The basic flow of authentication procedure can be found at facebook’s developer section.

When user is logged in Facebook and access to your app, it sends a signed request to the canvas page of the app using POST method. So in your servlet you have to handle the request in doPost method. Check for the presence of Oauth token in the signed request. If that is not present ask for it.

The signed request is a base64url encoded Json object. Now I couldn’t find anywhere a mapping class which can be mapped to the Json object after base64url decoded signed request. So I had to write it by myself.

public class FacebookSignedRequest {

	private String algorithm;
	private Long expires;
	private Long issued_at;
	private String oauth_token;
	private Long user_id;
	private FacebookSignedRequestUser user;
	
	public String getAlgorithm() {
		return algorithm;
	}
	
	public void setAlgorithm(String algorithm) {
		this.algorithm = algorithm;
	}
	
	public Long getExpires() {
		return expires;
	}
	
	public void setExpires(Long expires) {
		this.expires = expires;
	}
	
	public Long getIssued_at() {
		return issued_at;
	}
	
	public void setIssued_at(Long issued_at) {
		this.issued_at = issued_at;
	}
	
	public String getOauth_token() {
		return oauth_token;
	}
	
	public void setOauth_token(String oauth_token) {
		this.oauth_token = oauth_token;
	}
	
	public Long getUser_id() {
		return user_id;
	}
	
	public void setUser_id(Long user_id) {
		this.user_id = user_id;
	}

	public FacebookSignedRequestUser getUser() {
		return user;
	}

	public void setUser(FacebookSignedRequestUser user) {
		this.user = user;
	}
	
	public static class FacebookSignedRequestUser {

		private String country;
		private String locale;
		private FacebookSignedRequestUserAge age;
		
		public String getCountry() {
			return country;
		}

		public void setCountry(String country) {
			this.country = country;
		}

		public String getLocale() {
			return locale;
		}

		public void setLocale(String locale) {
			this.locale = locale;
		}

		public FacebookSignedRequestUserAge getAge() {
			return age;
		}

		public void setAge(FacebookSignedRequestUserAge age) {
			this.age = age;
		}

		public static class FacebookSignedRequestUserAge{
			private int min;
			private int max;

			public int getMin() {
				return min;
			}

			public void setMin(int min) {
				this.min = min;
			}

			public int getMax() {
				return max;
			}

			public void setMax(int max) {
				this.max = max;
			}
		}
	}
}

Now I write a Facebook util class which works as a configuration set up for Facebook app

public class FacebookAuthService {

	private static final String apiKey = "APP_KEY";
	private static final String appSecret = "APP_SECRET";
	private static final String appId = "APP_ID";
	
	private static final String redirect_uri = "https://apps.facebook.com/YOUR_APP_PATH";
	
	private static final String[] perms = new String[] {"publish_stream", "email"};
	
	public static String getAPIKey() {
		return apiKey;
	}

	public static String getSecret() {
		return appSecret;
	}

	public static String getLoginRedirectURL() {
		return "https://graph.facebook.com/oauth/authorize?client_id=" + appId
				+ "&display=page&redirect_uri=" + redirect_uri + "&scope="
				+ StringUtils.join(perms);
	}

	public static String getAuthURL(String authCode) {
		return "https://graph.facebook.com/oauth/access_token?client_id="
				+ appId + "&redirect_uri=" + redirect_uri + "&client_secret="
				+ appSecret + "&code=" + authCode;
	}
	
	public static String getAuthURL() {
		return "https://www.facebook.com/dialog/oauth?client_id="
				+ appId + "&redirect_uri=" + redirect_uri + "&scope="
				+ StringUtils.join(perms);
	}
	
	public static FacebookSignedRequest getFacebookSignedRequest(String signedRequest) throws Exception{
		
		String payLoad = signedRequest.split("[.]", 2)[1];
		payLoad = payLoad.replace("-", "+").replace("_", "/").trim();
		
		String jsonString = new String(Base64.decodeBase64(payLoad));
		return new ObjectMapper().readValue(jsonString, FacebookSignedRequest.class);
	}
}

I’ve used Jackson to map Json to Object here. But any other API can be used too.

Now in my entry servlet (my canvas URL) I check for it in the doPost method like

String signedRequest = (String) request.getParameter("signed_request");

FacebookSignedRequest facebookSignedRequest = FacebookAuthService.getFacebookSignedRequest(signedRequest);
PrintWriter writer = response.getWriter();
if (facebookSignedRequest.getOauth_token() == null) {
	response.setContentType("text/html");
	writer.print("<script> top.location.href='"	+ FacebookAuthService.getAuthURL() + "'</script>");
	writer.close();
} else {
	request.setAttribute("accessToken",	facebookSignedRequest.getOauth_token());
	RequestDispatcher requestDispatcher = getServletContext().getRequestDispatcher("/YOUR_NEXT_PATH");
	requestDispatcher.forward(request, response);
}

So, if the Oauth token is not present in the signed request the servlet redirects user to get the app permission. Once user allows the app the servlet gets the Oauth token in the signed request and pass it to the next page of the app.

REST Template Using Apache HttpClient

Calling REST web services using Spring’s RestTemplate has been already covered in the other post. Here is a template which can be used out side of Spring. A generalize REST template using Apache’s HttpClient API.

package com.your.package.name;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;

public class RestClient {
	public static final int HTTP_OK = 200;
	public static final String SERVER_URL = "BASE URL OF THE REST SERVER";

	public static String doGet(final String url) throws HttpException,
			IOException, URISyntaxException {

		final HttpClient httpClient = new DefaultHttpClient();
		HttpConnectionParams
				.setConnectionTimeout(httpClient.getParams(), 10000);
		HttpGet httpget = new HttpGet(SERVER_URL + url);
		HttpResponse response = httpClient.execute(httpget);
		HttpEntity entity = response.getEntity();
		InputStream instream = entity.getContent();
		return read(instream);
	}

	public static String doPost(final String url, final String POSTText)
			throws URISyntaxException, HttpException, IOException {

		final HttpClient httpClient = new DefaultHttpClient();
		HttpConnectionParams
				.setConnectionTimeout(httpClient.getParams(), 10000);

		HttpPost httpPost = new HttpPost(SERVER_URL + url);
		StringEntity entity = new StringEntity(POSTText, "UTF-8");
		BasicHeader basicHeader = new BasicHeader(HTTP.CONTENT_TYPE,
				"application/json");
		httpPost.getParams().setBooleanParameter(
				"http.protocol.expect-continue", false);
		entity.setContentType(basicHeader);
		httpPost.setEntity(entity);
		HttpResponse response = httpClient.execute(httpPost);
		InputStream instream = response.getEntity().getContent();
		return read(instream);
	}

	public static boolean doPut(final String url, final String PUTText)
			throws URISyntaxException, HttpException, IOException {
		final HttpClient httpClient = new DefaultHttpClient();
		HttpConnectionParams
				.setConnectionTimeout(httpClient.getParams(), 10000);

		HttpPut httpPut = new HttpPut(SERVER_URL + url);
		httpPut.addHeader("Accept", "application/json");
		httpPut.addHeader("Content-Type", "application/json");
		StringEntity entity = new StringEntity(PUTText, "UTF-8");
		entity.setContentType("application/json");
		httpPut.setEntity(entity);
		HttpResponse response = httpClient.execute(httpPut);
		int statusCode = response.getStatusLine().getStatusCode();
		return statusCode == HTTP_OK ? true : false;
	}

	public static boolean doDelete(final String url) throws HttpException,
			IOException, URISyntaxException {
		final HttpClient httpClient = new DefaultHttpClient();
		HttpConnectionParams
				.setConnectionTimeout(httpClient.getParams(), 10000);

		HttpDelete httpDelete = new HttpDelete(SERVER_URL + url);
		httpDelete.addHeader("Accept",
				"text/html, image/jpeg, *; q=.2, */*; q=.2");
		HttpResponse response = httpClient.execute(httpDelete);
		int statusCode = response.getStatusLine().getStatusCode();
		return statusCode == HTTP_OK ? true : false;
	}

	private static String read(InputStream in) throws IOException {
		StringBuilder sb = new StringBuilder();
		BufferedReader r = new BufferedReader(new InputStreamReader(in), 1000);
		for (String line = r.readLine(); line != null; line = r.readLine()) {
			sb.append(line);
		}
		in.close();
		return sb.toString();
	}
}

And it can be used like

RestClient.doDelete("/registration/" + userToken);
RestClient.doGet("/me/profile?ct=" + userToken);

Extract Text from HTML using NekoHTML and Dom4j

Consider the link http://www.cdw.com/shop/search/results.aspx?wclss=C3&enkwrd=laptop&searchscope=ALL.
Lets extract the total search result and title of each item to keep the example simple enough. We will be using XPath to find each element in the HTML page.
Here is the code

package com.asc.dyutiman.html;

import java.io.IOException;
import java.util.List;

import org.cyberneko.html.parsers.DOMParser;
import org.dom4j.Node;
import org.dom4j.io.DOMReader;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class Parse {
	
	public static void main(String[] args){
		
		String url = "http://www.cdw.com/shop/search/results.aspx?wclss=C3&enkwrd=laptop&searchscope=ALL";
		try {
			DOMParser parser = new DOMParser();
			parser.parse(url);
			
			Document document = parser.getDocument();
			DOMReader reader = new DOMReader();
			org.dom4j.Document doc = reader.read(document);
			
			Node totalResultNode = doc.selectSingleNode("//SPAN[@id='lblShowingResultsTop']/B[3]");
			
			@SuppressWarnings("unchecked")
			List<Node> itemList =  doc.selectNodes("//DIV[@class = 'searchrow']");

			System.out.println("Showing " + itemList.size() + " out of " + totalResultNode.getText());
			for(Node itemNode : itemList){
				Node itemTitle = itemNode.selectSingleNode("DIV[@class = 'searchrow-description']/A");
				System.out.println(itemTitle.getText());
			}
		} catch (SAXException e) {
			System.out.println(e.getMessage());
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}
}

Remember to use uppercase for any HTML tag.

Simple REST Web Service – Spring

The Service :
Create a project with Maven for Eclipse Dynamic Web Project from here.

Here I have used Spring Annotation up to my knowledge. I believe there are more things which can be annotated.

The Deployment Descriptor (web.xml) is the simplest

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5" id="WebApp_1291891438549">

  	<display-name>Spring REST Example1</display-name>
  	<servlet>
		<servlet-name>person</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>person</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
	
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

So we must have the person-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:oxm="http://www.springframework.org/schema/oxm"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">

	<context:component-scan base-package="com.dyuti.spring.rest" />

	<!-- Format Output -->
	<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
	<bean id="personXmlView"
		class="org.springframework.web.servlet.view.xml.MarshallingView">
		<constructor-arg>
			<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
				<property name="autodetectAnnotations" value="true" />
			</bean>
		</constructor-arg>
	</bean>
	<!--          -->

	<!-- Convert Input -->
	<bean
		class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
	<bean
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="messageConverters">
			<list>
				<ref bean="marshallingHttpMessageConverter" />
			</list>
		</property>
	</bean>

	<bean id="marshallingHttpMessageConverter"
		class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
		<property name="marshaller" ref="jaxb2Marshaller" />
		<property name="unmarshaller" ref="jaxb2Marshaller" />
	</bean>

	<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		<property name="classesToBeBound">
			<list>
				<value>com.dyuti.spring.rest.domain.Person</value>
			</list>
		</property>
	</bean>
	<!--          -->

	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost/person" />
		<property name="username" value="root" />
		<property name="password" value="*****" />
	</bean>

	<bean id="mySessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="myDataSource" />
		<property name="annotatedClasses">
			<list>
				<value>com.dyuti.spring.rest.domain.Person</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<value>hibernate.dialect=org.hibernate.dialect.MySQLDialect</value>
		</property>
	</bean>

	<bean id="personDao" class="com.dyuti.spring.rest.dao.PersonDaoHibImpl">
		<property name="sessionFactory" ref="mySessionFactory" />
	</bean>
</beans>

We use org.springframework.oxm.xstream.XStreamMarshaller for converting Java Object to XML for sending through HTTP, and also converting HTTP XML data to corresponding Java Object.

The simple Person objec

package com.dyuti.spring.rest.domain;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XmlRootElement
@XStreamAlias("person")
@Entity
@Table(name = "person")
public class Person implements Serializable {

	private static final long serialVersionUID = 2675617253130859687L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;
	@Column
	private String name;
	@Column
	private int age;

	// Generate getter & setter here
}

Now the DAO and the Hibernate Implementation

package com.dyuti.spring.rest.dao;

import com.dyuti.spring.rest.domain.Person;

public interface PersonDao {
	
	public boolean save(Person person);
	
	public Person get(int id);
}
package com.dyuti.spring.rest.dao;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.dyuti.spring.rest.domain.Person;

@Repository("personDao")
public class PersonDaoHibImpl extends HibernateDaoSupport implements PersonDao {

	@Override
	public boolean save(Person person) {
		int id = (Integer) getHibernateTemplate().save(person);
		return id > 0 ? true : false;
	}

	@Override
	public Person get(int id) {
		return (Person) getHibernateTemplate().get(Person.class, id);
	}
}

And the service and its implementation

package com.dyuti.spring.rest.service;

import com.dyuti.spring.rest.domain.Person;

public interface PersonService {

	public boolean savePerson(Person p);
	
	public Person getPerson(int id);
}
package com.dyuti.spring.rest.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dyuti.spring.rest.dao.PersonDao;
import com.dyuti.spring.rest.domain.Person;

@Service("personService")
public class PersonServiceImpl implements PersonService {

	@Autowired
	private PersonDao personDao;

	@Override
	public boolean savePerson(Person person) {
		return personDao.save(person);
	}

	@Override
	public Person getPerson(int id) {
		return personDao.get(id);
	}
}

The controller is the entry point and also the provider of the web service.

package com.dyuti.spring.rest.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.dyuti.spring.rest.domain.Person;
import com.dyuti.spring.rest.service.PersonService;

@Controller
public class PersonController {

	@Autowired
	private PersonService personService;

	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public ModelAndView getPerson(@PathVariable int id) {
		Person person = personService.getPerson(id);
		return new ModelAndView("personXmlView", BindingResult.MODEL_KEY_PREFIX
				+ "person", person);
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public ModelAndView addPerson(@RequestBody Person person) {
		boolean result = personService.savePerson(person);
		return new ModelAndView("personXmlView", BindingResult.MODEL_KEY_PREFIX
				+ "person", result);
	}
}

Finally the 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>com.dyuti.spring.rest</groupId>
	<artifactId>SpringREST</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>SpringREST</name>
	<url>http://maven.apache.org</url>

	<build>
		<finalName>SpringREST</finalName>
		<sourceDirectory>${basedir}/src/main/java</sourceDirectory>

		<resources>
			<resource>
				<directory>${basedir}/src/main/resources</directory>
			</resource>
		</resources>

		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<!-- configure the plugin here -->
						</configuration>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.0</version>
				<configuration>
					<webResources>
						<resource>
							<directory>${basedir}/src/main/webapp</directory>
							<filtering>false</filtering>
							<excludes>
								<exclude>WEB-INF/lib/*</exclude>
							</excludes>
						</resource>
					</webResources>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>${commons.beanutils.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>${commons.collections.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>${commons.lang.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>${commons.io.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-digester</groupId>
			<artifactId>commons-digester</artifactId>
			<version>1.6</version>
			<exclusions>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.1</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.1</version>
			<exclusions>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
				<exclusion>
					<groupId>xerces</groupId>
					<artifactId>xerces</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>commons-pool</groupId>
			<artifactId>commons-pool</artifactId>
			<version>1.2</version>
			<exclusions>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
				<exclusion>
					<groupId>xerces</groupId>
					<artifactId>xerces</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate</artifactId>
			<version>${hibernate.version}</version>
			<exclusions>
				<exclusion>
					<artifactId>ehcache</artifactId>
					<groupId>net.sf.ehcache</groupId>
				</exclusion>
				<exclusion>
					<artifactId>commons-collections</artifactId>
					<groupId>commons-collections</groupId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-annotations</artifactId>
			<version>${hibernate.annotations.version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-commons-annotations</artifactId>
			<version>${hibernate.annotations.version}</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.8</version>
		</dependency>

		<dependency>
			<groupId>org.apache.openejb</groupId>
			<artifactId>commons-dbcp-all</artifactId>
			<version>1.3</version>
		</dependency>

		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>${jpa.version}</version>
		</dependency>

		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.0.0.GA</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		

		<dependency>
			<groupId>com.thoughtworks.xstream</groupId>
			<artifactId>xstream</artifactId>
			<version>1.3.1</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<properties>
		<spring.version>3.0.0.RELEASE</spring.version>
		<java.version>1.6</java.version>
		<servlet-api.version>2.5.0</servlet-api.version>
		<hibernate.annotations.version>3.3.0.ga</hibernate.annotations.version>
		<hibernate.version>3.2.6.ga</hibernate.version>
		<jpa.version>1.0</jpa.version>
		<commons.beanutils.version>1.7.0</commons.beanutils.version>
		<commons.collections.version>3.2</commons.collections.version>
		<commons.io.version>1.3.2</commons.io.version>
		<commons.lang.version>2.3</commons.lang.version>
	</properties>
</project>

So, the project is set up and deploy it on Tomcat.

The client :
The RestClient provided by Spring makes life very simple creating REST consumer.
Create another project (not necessary a web project, client can be anything, even if Ajax).

Create the same Person object from above.
Lets create the Spring context file, resides in the same package of the loader class under resource folder.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:oxm="http://www.springframework.org/schema/oxm"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
				http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
				http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">

	<context:component-scan base-package="com.dyuti.spring.rest" />

	<bean id="personSave" class="com.dyuti.spring.rest.controller.SavePerson">
		<property name="restTemplate">
			<ref bean="restTemplate" />
		</property>
	</bean>
	<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"></bean>
</beans>

And the client class

package com.dyuti.spring.rest.controller;

import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.dyuti.spring.rest.domain.Person;

@Component
public class SavePerson {

	private RestTemplate restTemplate;

	private String restURL = "http://localhost:8080/SpringREST/";

	public void sendPerson() {
		Person person = new Person();
		person.setName("client");
		person.setAge(12);
		person.setId(3);

		Person p = restTemplate.getForObject(restURL + "2", Person.class);
		System.out.println(p.getName());

		String result = restTemplate.postForObject(restURL + "add", person,
				String.class);
		System.out.println(result);
	}

	public void setRestTemplate(RestTemplate restTemplate) {
		this.restTemplate = restTemplate;
	}
}

Run the client

package com.dyuti.spring.rest.controller;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class RunRest {

	public static void main(String[] args) {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
				"applicationContext.xml", RunRest.class);
		SavePerson savePerson = applicationContext.getBean("personSave",
				SavePerson.class);
		savePerson.sendPerson();
	}
}

I have used the same pom.xml for this project, which may require less packages.

Create a Project with Maven for Eclipse

Install & configure Maven from http://maven.apache.org/download.html.

Go to eclipse workspace and run the following command

mvn archetype:create -DgroupId=com.mycompany.projectname -DartifactId=projectname -DarchetypeArtifactId=maven-archetype-webapp

-DartifactId is your project name and -DgrouipId is your package.
Change the ‘com.mycompany.app’ and ‘my-app’ as you want them to be.
The command will download necessary poms & jars and create the folder architecture with a very basic pom.xml file.

Now, we will make it an eclipse project so that we can import it from eclipse. Go to the project folder. Run

cd my-app
mvn eclipse:eclipse -Dwtpversion=2.0

This will generate eclipse .classpath & .project file. So open eclipse and just import the project.

To make a web project change jar to war in pom.xml and run

mvn eclipse:clean eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true -Dwtpversion=2.0

Refer this article for more.

Simple JNI Example

Make a native method in java and call it.

static {
	System.loadLibrary("multiply");
}

public native int multiply(int a, int b);

public static void main(String[] args) {

	GetPhotoData getPhotoData = new GetPhotoData();

	int a = 8;
	int b = 6;

	int c = getPhotoData.multiply(a, b);
	System.out.println(c);
}

Compile it with
javac Filename.java

Now run the following command to make the header(.h) file
javah -jni Filename

It will generate a header file with proper name and will have native method signature in it.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_financial_inclusive_jni_GetPhotoData */

#ifndef _Included_com_financial_inclusive_jni_GetPhotoData
#define _Included_com_financial_inclusive_jni_GetPhotoData
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_financial_inclusive_jni_GetPhotoData
 * Method:    multiply
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_financial_inclusive_jni_GetPhotoData_multiply
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

Now as the header file is created and the method signature of the native method to be implemented is there, make a C file which implements the method. Include the header file so it can find it.

#include "com_financial_inclusive_jni_GetPhotoData.h"

JNIEXPORT jint JNICALL Java_com_financial_inclusive_jni_GetPhotoData_multiply
  (JNIEnv *env, jobject thisobject, jint ja, jint jb){
	return ja*jb;
}

I did it on windows. So I had to make a dll file and keep it under C:/WINDOWS/System32 which is added to my %path% system variable.

I’ve used Borland compiler to generate the dll by running

D:\Borland\BCC55\Bin>bcc32 -WD d:\workspace\FinancialIncl\src\multiply.c

When first time compiled it will throw an error and quite.

Here you see that the C method created has two more extra arguments than we passed. The first one is the pointer to JVM environment and the second one is the reference object to the class. In our case we do not use those variables in our C implementation. So the compiler just gives warning about it and exits. We have to suppress these warnings to create the dll.

D:\Borland\BCC55\Bin>bcc32 -WD -w-par d:\workspace\FinancialIncl\src\multiply.c

Here is a nice reference from where I got all the resources.
And for Borland command options, please refer this.