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.

Web Service for Lucene Search on Tomcat

The SearchUtil class is created to search on Lucene. This also uses a stop words file to eliminate those words and/or numbers. The class returns ids matched to a table for related search results.

public class SearchUtil {

    private String stopWordsFile = "/mnt/lucene/bmindex/stopwords.txt";

    public int[] search(int clientId, int keywordId, String searchStr, int offset, int hitPerPage) throws IOException, ParseException{

        IndexSearcher searcher = getSearcher(clientId);
        File stopWords = new File(stopWordsFile);
        StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT, stopWords);
        QueryParser qp = new QueryParser(Version.LUCENE_CURRENT, "contents", analyzer);
        Query query = qp.parse(searchStr);
        int limit = offset + hitPerPage;

        TopDocs topDocs = null;
        if(keywordId > 0){
            Filter filter = NumericRangeFilter.newIntRange("keyword_id", keywordId, keywordId, true, true);
            topDocs = searcher.search(query, filter, limit);
        }else{
            topDocs = searcher.search(query, limit);
        }
        int lastIndex = limit > topDocs.totalHits ? topDocs.totalHits : limit;
        int startIndex = offset;

        int[] searchedIds = new int[hitPerPage+1];
        searchedIds[0] = topDocs.totalHits;

        for (int i = startIndex; i < lastIndex; i++) {
            Document doc = searcher.doc(topDocs.scoreDocs[i].doc);
            searchedIds[i] = Integer.parseInt(doc.get("id"));
        }
        return searchedIds;
    }

    private IndexSearcher getSearcher(int clientId) throws IOException {
        Directory dir = FSDirectory.open(new File(indexDir(clientId)));
        IndexReader reader = IndexReader.open(dir, true);
        return new IndexSearcher(reader);
    }

    private String indexDir(int clientId){
        return "/mnt/lucene/bmindex/" + "client_index_" + new Integer(clientId).toString();
    }
}

The next class is the web service which takes various search criterion.
@WebService()
public class SearchIndex {

    @WebMethod(operationName = "searchLucene")
    public int[] searchLucene(
                            @WebParam(name="clientId")int clientId,
                            @WebParam(name="keywordId")int keywordId,
                            @WebParam(name="searchStr")String searchStr,
                            @WebParam(name="startLimit")int startLimit,
                            @WebParam(name="hitPerPage")int hitPerPage) throws IOException, ParseException{

        SearchUtil su = new SearchUtil();
        int[] searchIds = su.search(clientId, keywordId, searchStr, startLimit, hitPerPage);

        return searchIds;
    }
}

To enable the web service on Tomcat we have to map it as a Servlet in web.xml file.
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	 version="3.0">

    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>

   <servlet>
        <servlet-name>jax-ws</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        </servlet>
    <servlet-mapping>
        <servlet-name>jax-ws</servlet-name>
        <url-pattern>/SearchIndex</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
</web-app>

There is one more configuration in Tomcat we have to do to make the web service working. Details of that can be found at Running JAX-WS with Tomcat

Follow

Get every new post delivered to your Inbox.