Sunday, 30 June 2013

Spring Data - REST

Gone are the days when people used to take significant amount of time to expose REST service APIs for their domain objects. "SPRING DATA - REST" project is under active development to make your life easy. Its 1.0.0.RC3 version was released on Sep 14, 2012. We can expect the final build to be released soon.

The goal of this project is to expose CRUD operations on JPA entities in the form of REST services.

You can focus on defining your domain classes and SPRING DATA - REST framework will do the job of exposing them in the form of REST services (In simple words you don’t have to write even a single line of code to achieve this.) It is just a matter of configuring your project rightly with the framework.

Here are few simple steps to get started with.

Step 1 :

Add the following maven dependency in your pom.xml :

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-rest-webmvc</artifactId>
  <version>1.0.0.RC3</version>
</dependency>

Use the following repository to resolve this dependency :

<repository>
  <id>spring-milestone</id>
  <name>Spring Maven MILESTONE Repository</name>
  <url>http://repo.springsource.org/libs-milestone</url>
</repository>

Step 2 :

Add RepositoryRestExporterServlet in your web.xml which will act as an exporter for your JPA repositories :

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

<servlet-mapping>
 <servlet-name>exporter</servlet-name>
 <url-pattern>/*</url-pattern>
</servlet-mapping>

Step 3 :

No change is needed in your Spring JPA config file. Here is my config file for your reference :


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

<context:property-placeholder location="classpath*:*.properties" />
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${database.driverClassName}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
</bean>  

<bean id="entityManagerFactory"
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="packagesToScan" value="com.viracct.rest.demo" />
 <property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
 <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
     <property name="showSql" value="${hibernate.showSql}" />
     <property name="generateDdl" value="true" />
        </bean>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
 <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<jpa:repositories base-package="com.viracct.rest.demo.dao" />

</beans>

Here I have defined some simple JPA entities - Company, Department, Employee.

package com.viracct.rest.demo.domain;

@Entity

public class Company {

 @Id

 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String name;
 private String description;
 @OneToMany
 private List<Department> departments;

 public Long getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

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

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Department> getDepartments() {
  return departments;
 }

 public void setDepartments(List<Department> departments) {
  this.departments = departments;
 }

}


@Entity

public class Department {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private String name;
 private String description;
 @OneToMany
 private List<Employee> employees;

 public Long getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

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

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Employee> getEmployees() {
  return employees;
 }

 public void setEmployees(List<Employee> employees) {
  this.employees = employees;
 }

}



@Entity

public class Employee {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;
 private Long code;
 private String name;
 private String designation;

 public Long getId() {
  return id;
 }

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

 public Long getCode() {
  return code;
 }

 public void setCode(Long code) {
  this.code = code;
 }

 public String getName() {
  return name;
 }

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

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

}

Here are the JPA repositories for the entities mentioned above.

package com.viracct.rest.demo.dao;

public interface CompanyRepository extends JpaRepository {
}

public interface DepartmentRepository extends JpaRepository {
}

public interface EmployeeRepository extends JpaRepository {
}

Once you have deployed this application, you can see the service end points for your entities by hitting the following URL:  http://localhost:8080/restdemo and the output will be :

{
  "links" : [ {
    "rel" : "department",
    "href" : "http://localhost:8080/restdemo/department"
  }, {
    "rel" : "company",
    "href" : "http://localhost:8080/restdemo/company"
  }, {
    "rel" : "employee",
    "href" : "http://localhost:8080/restdemo/employee"
  } ],
  "content" : [ ]
}

You can browse employee objects with the following URL : http://localhost:8080/restdemo/employee and the output will be :


{
  "links" : [ ],
  "content" : [ {
    "links" : [ {
      "rel" : "self",
      "href" : "http://localhost:8080/restdemo/employee/1"
    } ],
    "name" : "Anuja Kumar",
    "designation" : "Software Developer",
    "code" : 100051
  } ],
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 1
  }
}

Similarly you can access department object with id=2 with the following URL : http://localhost:8080/restdemo/department/2 and the output will be :

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/restdemo/department/2"
  }, {
    "rel" : "department.Department.employees",
    "href" : "http://localhost:8080/restdemo/department/2/employees"
  } ],
  "description" : "Product Development Team",
  "name" : "Development"
}

Now if you want to access employee with employee-id=1 from department with department-id=2, you can get that using the following URL: http://localhost:8080/restdemo/department/2/employees/1 and the output will be :

{
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8080/restdemo/employee/1"
  }, {
    "rel" : "department.Department.employees",
    "href" : "http://localhost:8080/restdemo/department/2/employees/1"
  } ],
  "name" : "Anuja Kumar",
  "designation" : "Software Developer",
  "code" : 100051
}

No comments:

Post a Comment