spring

Spring Data Rest Example

In the previous few examples we demonstrated how the different spring data modules are configured and their support for the NoSql databases. In this example, I will demonstrate how we can expose our CRUD Repository as a REST Web-Service over the HTTP.

We will be using MySQL as the database for this project . However, the application which we shall build here will be largely independent of the underlying Database technology used. This is because of the abstraction layer added by the Spring Data Module.
 
 
 
 

 
So let’s get started with the project setup:

We will create a new Maven project with archetype as maven-archetype-webapp. Update the pom.xml with the below file :

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>SpringDataRestExample1</groupId>
  <artifactId>SpringDataRestExample1</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringDataRestExample</name>
  <url>http://maven.apache.org</url>
  <dependencies>

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>1.9.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-rest-webmvc</artifactId>
			<version>2.3.2.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.36</version>
		</dependency>


		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.3.6.Final</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>4.3.6.Final</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>3.3</version>
				<configuration>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
					
				</configuration>
				
			</plugin>
			   <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
		</plugins>
		<finalName>SpringDataRestExample</finalName>
	</build>
</project>

This will add the required dependencies for the archives we will need for setting up this project. Let’s start with the implementation now.

We start by creating the entities that will be persisted to the MySql server.

Person.java

package com.jcg.examples.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

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

		private static final long serialVersionUID = -5378396373373165919L;
		
		@Id
		@GeneratedValue(strategy=GenerationType.IDENTITY)
		private Long pId;
		
		@Column
		private String personName;
		
		@Column
		private double personAge;

		public Long getpId()
		{
				return pId;
		}

		public void setpId(Long pId)
		{
				this.pId = pId;
		}

		public String getPersonName()
		{
				return personName;
		}

		public void setPersonName(String personName)
		{
				this.personName = personName;
		}

		public double getPersonAge()
		{
				return personAge;
		}

		public void setPersonAge(double personAge)
		{
				this.personAge = personAge;
		}

		@Override
		public String toString()
		{
				return "Person [pId=" + pId + ", personName=" + personName + ", personAge=" + personAge + "]";
		}
}

We are using annotations to map the entity properties to the database table columns. Here is a brief description of the annotations we have used for mapping:

@Id is used to mark the primary key of the entity. @Column is used to map the properties of the entity to those of the table columns. In case, the name of the column happens to be different from the name of the property we can use the name attribute of the @Column annotation and pass the name of the table column.

Next we create a repository to persist the entity defined above to the database.

PersonRepo.java

package com.jcg.examples.repo;

import java.util.List;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.data.rest.core.annotation.RestResource;

import com.jcg.examples.entity.Person;

@RepositoryRestResource
public interface PersonRepo extends CrudRepository<Person, Long>
{
		@RestResource(path="byName") 
		public List findByPersonName(@Param("name") String personName);
}


Spring Data Module provides us with a number of inbuilt method for manipulating the Data. We need not write the queries for basic data manipulation and reading. It is achieved by extending the CrudRepository interface and declaring the proper Generics as per the Entity, which in our case is the <Person, Long>.

Also, we have a created a custom a method that searches based on the name property of the Person.

Now, we have annotated the repository with the @RepositoryRestResource annotation. This marks the resource to be exported as a REST resource which is available over the HTTP. We may also choose to hide some methods by adding the annotation : @RestResource(exported = false) . The same annotation can be used to annotate an entity property so that it is not transmitted over the network.

Now we create the spring-config.xml and place it in the WEB-INF folder. This file contains the configuration of the database and other required beans. Line 13 causes the spring container to scan the repo package for the classes annotated with the @RepositoryRestResource to be exported.We can also use the path attribute of the @RestResource to modify the path of the method.

spring-config.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:jpa="http://www.springframework.org/schema/data/jpa"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="com.jcg.examples.repo" />
    
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/test"/>
        <property name="username" value="root"/>
        <property name="password" value="toor"/>
    </bean>

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true"/>
        <property name="generateDdl" value="true"/>
        <property name="database" value="MYSQL"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="packagesToScan" value="com.jcg.examples.entity"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>
    
    <jpa:repositories base-package="com.jcg.examples.repo" />

</beans>

Next is the most important web.xml. We configure the ContextLoaderListener to load the spring-config.xml file and bind the Applicationcontext lifecycle to that of the ServletContext.This initializes the beans we have defined in the xml

The RepositoryRestDispatcherServlet is used to expose the REST Resources over the network. The non-zero value of load-on-startup marks the servlet to be eagerly loaded during the web-container initialization.

web.xml

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

	<display-name>Archetype Created Web Application</display-name>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring-config.xml</param-value>
	</context-param>

	<servlet>
		<servlet-name>rest</servlet-name>
		<servlet-class>org.springframework.data.rest.webmvc.RepositoryRestDispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>rest</servlet-name>
		<url-pattern>/api/*</url-pattern>
	</servlet-mapping>

</web-app>

Deploy the above application to the Web-Server/Application Server you have configured and the REST service is ready to be consumed.

Here is the sample output when different HTTP methods are used. For the sake of this project I have used curl, a command line tool, to test our REST Web-Service.

Command executed for GET:

curl http://localhost:8080/SpringDataRestExample/api/persons

Fig 1 : CURL
Fig 1 : CURL

Command executed for POST :

curl -i -X POST -H "Content-Type:application/json" -d "{ \"personName\" : \"Krishna\" , \"personAge\" : \"120\" }" http://localhost:8080/SpringDataRestExample/api/persons

Fig 2 : POST
Fig 2 : POST

In the windows console, single quote is not recognized as such we are forced to use the double quotes and escape sequence for passing the values.

Command executed for Search :

curl http://localhost:8080/SpringDataRestExample/api/persons/search/byName?name=Krishna

Fig 3 : Search
Fig 3 : Search

We search using the query method findByPersonName we wrote in PersonRepo class. Had we not changed the path of the method, it would be accessed using the actual method name.

Command executed for Delete :

curl -X DELETE http://localhost:8080/SpringDataRestExample/api/persons/3

Fig 4 : Delete
Fig 4 : Delete

As you can see, this command deletes an entity with the id = 3.

Download the Source Code

Thus we demonstrated how the Spring Data REST repository is configured and we can use it for CRUD operation. However, the reader should note that this style of architecture is more suited for smaller to medium scale applications. In large scale applications omitting the service layer, altogether, may not be advisable.

Download
You can download the source code of this example here: SpringDataRestExample.zip

Chandan Singh

Chandan holds a degree in Computer Engineering and is a passionate software programmer. He has good experience in Java/J2EE Web-Application development for Banking and E-Commerce Domains.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Krishna
Krishna
5 years ago

I want to return pId also with personAge and personName in same object, But not like http://localhost:8080/SpringDataRestExample/api/persons/3. How to do that

Back to top button