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

Hibernate One-to-Many and Many-to-One Mapping using Annotation

person
id
name
age
sex
location

client
id
name

person_client
id
person_id
client_id

Person.java

package com.dyutiman.beans;

@Entity
@Table(name = "person")
public class Person {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	@OneToMany(mappedBy = "person")
	private List<PersonClient> personClients;

	@Column
	private String name;

	@Column
	private int age;

	@Column
	private String sex;

	@Column
	private String location;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public List<PersonClient> getPersonClients() {
		return personClients;
	}

	public void setPersonClients(List<PersonClient> personClients) {
		this.personClients = personClients;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

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

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}
}

Client.java

package com.dyutiman.beans;

@Entity
@Table(name = "client")
public class Client {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;

	@OneToMany(mappedBy = "client")
	private List<PersonClient> pc;

	@Column
	private String name;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public List<PersonClient> getPc() {
		return pc;
	}

	public void setPc(List<PersonClient> pc) {
		this.pc = pc;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

PersonClient.java

package com.dyutiman.beans;

@Entity
@Table(name = "person_client")
public class PersonClient {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@ManyToOne
	@JoinColumn(name = "person_id")
	private Person person;

	@ManyToOne
	@JoinColumn(name = "client_id")
	private Client client;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public Client getClient() {
		return client;
	}

	public void setClient(Client client) {
		this.client = client;
	}
}

Test

public void testLoad() {
	long id = 1;
	Client c = cd.load(id);

	List<PersonClient> pcList = c.getPc();
	for (PersonClient pc : pcList) {
		System.out.println(pc.getPerson().getName());
	}
}

public void testLoad() {
	long id = 1;
	Person p = pd.load(id);

	List<PersonClient> pcList = p.getPersonClients();
	for (PersonClient pc : pcList) {
		System.out.println(pc.getClient().getName());
	}
}

Delete Long List of Files in Linux Fedora

simple :)

find -name 'indexC*' | xargs rm

MySQL Group By Seven Days

If we have a daily expense table like

+------+------------+
| cost | date       |
+------+------------+
|   44 | 2010-07-30 |
|   39 | 2010-07-31 |
|   18 | 2010-08-01 |
|   71 | 2010-08-02 |
|   69 | 2010-08-03 |
|   62 | 2010-08-04 |
|   89 | 2010-08-05 |
|   72 | 2010-08-06 |
|   46 | 2010-08-07 |
|   23 | 2010-08-08 |
+------+------------+

its very easy to show monthly aggregation. Just a group by clause on date column based on month will do the job

SELECT	SUM(cost) AS total, MONTHNAME(date) AS month 
FROM daily_expense 
GROUP BY month 
ORDER BY MONTH(date);
+-------+-----------+
| total | month		|
+-------+-----------+
|    83 | July      |
|  1641 | August    |
|   554 | September |
+-------+-----------+

Now what we do when its been asked to show weekly aggregation. Using MySQL WEEK function returns the number of the week number of the date. By default the start of the week is Sunday or Monday based on the Server System Variables. Otherwise it can be set while using the function itself. So the query

SELECT	SUM(cost) AS total, CONCAT(date, ' - ', date + INTERVAL 6 DAY) AS week
FROM daily_expense
GROUP BY WEEK(date)
ORDER BY WEEK(date)

gives something like

+-------+-------------------------+
| total | week                    |
+-------+-------------------------+
|    83 | 2010-07-31 - 2010-08-06 |
|   427 | 2010-08-07 - 2010-08-13 |
|   345 | 2010-08-14 - 2010-08-20 |
|   389 | 2010-08-21 - 2010-08-27 |
|   318 | 2010-08-28 - 2010-09-03 |
|   404 | 2010-09-04 - 2010-09-10 |
|   272 | 2010-09-11 - 2010-09-17 |
|    40 | 2010-09-13 - 2010-09-19 |
+-------+-------------------------+

Till now its fairly straightforward and simple. Unfortunately it does not remain so when the same weekly aggregation has to be done but on different start day of the week, other than Sunday or Monday. Is there any option in MySQL to specify different start day of a week? I couldn’t find it, but if anybody knows anything like this please let me know by putting a comment here.
But I couldn’t wait till someone finds a easier way & let me know how. I have my own solution.

The thought
To get any aggregated data from a table we have to use the Group By clause on that field. In our case the field is the day name of a day of a week, like Wednesday, lets say in our case. My plan is to do some kind of operation on all the day up to next Wednesday. This function will change those next days into something similar to Wednesday. Similarly, another function will change last weekdays (like Tuesday, Monday) up to last Wednesday into something similar and unique to the last Wednesday.

Now, what is uniqueness of Wednesday which can be treated logically !! The first thing came to my mind is the day number of the week. MySQL WEEKDAY function gives a number for each day corresponding to the position of the day in a week. Like 2 is for Wednesday. If we use some function to make all other days as 2, we will ed up having all the day in a year as 2.
So, what is the uniqueness of each Wednesday from the other!, across the time! Here MySQL have another function named TO_DAYS. This function gives a unique number for each day since year 0. Now, my plan is to create some operations which for each day gives the same number equals to its previous Wednesday. So from one Wednesday to the next the number remains same and I can apply Group By clause over them to get an weekly aggregation.

The execution
I have an array of weekdays where Monday is 0 & Sunday is 6, same as the WEEKDAY function in MySQL.

$weekArr = array(
			'Monday' => 0,
			'Tuesday' => 1,
			'Wednesday' => 2,
			'Thursday' => 3,
			'Friday' => 4,
			'Saturday' => 5,
			'Sunday' => 6);

So given the weekday, which should be considered as the start day of a week, I can get a number (2 for Wednesday). All the date following it till Sunday has the weekday greater than current Wednesday. So I subtract the day difference between the day and the current Wednesday from the TO_DAYS of the day to make it same as the TO_DAYS of the current Wednesday. I do something like

$startWeekDay = $weekArr['Wednesday']; //2
TO_DAYS(date) - (WEEKDAY(date) - ".$startWeekDay.")

And for all the preceding days up to previous Wednesday, I subtract the day difference between the day and its previous Wednesday. Now the previous Wednesday has exact 7 days different from the current Wednesday. Like

TO_DAYS(date) - (7 - (".$startWeekDay." - WEEKDAY(date)))

And the whole query becomes

SELECT	SUM(cost) AS total, 
		CONCAT(IF(date - INTERVAL 6 day < '".$startDay."', 
				'".$startDay."', 
				IF(WEEKDAY(date - INTERVAL 6 DAY) = ".$startWeekDay.", 
					date - INTERVAL 6 DAY, 
					date - INTERVAL ((WEEKDAY(date) - ".$startWeekDay.")) DAY)),
			' - ', date) AS week, 
			IF((WEEKDAY(date) - ".$startWeekDay.") >= 0, 
				TO_DAYS(date) - (WEEKDAY(date) - ".$startWeekDay."), 
				TO_DAYS(date) - (7 - (".$startWeekDay." - WEEKDAY(date)))) AS sortDay 
FROM	daily_expense
WHERE	date BETWEEN '".$startDay."' AND '".$endDay."' 
GROUP BY sortDay;

which gives

+-------+-------------------------+---------+
| total | week                    | sortDay |
+-------+-------------------------+---------+
|   158 | 2010-08-01 - 2010-08-03 |  734346 |
|   378 | 2010-08-04 - 2010-08-10 |  734353 |
|   365 | 2010-08-11 - 2010-08-17 |  734360 |
|   393 | 2010-08-18 - 2010-08-24 |  734367 |
|   347 | 2010-08-25 - 2010-08-31 |  734374 |
+-------+-------------------------+---------+

Now a date range can be put to limit the results like, BETWEEN ‘2010-08-01’ AND ‘2010-08-31’.

I believe this can be extended or modified to use any interval of aggregation (thats may be the next part), just have to find a logical equation for each step of the interval.