This tutorial provides the detailed instruction on how to use Spring Data REST project in your Spring MVC applications to export your JPA entities. The greatest advantage of using the Spring Data REST is that, it easily exports the entities and made available through the HTTP protocol.
Using Spring Data REST repository exporter project, you can now export these managed entities via a REST web service to easily interact with the data. The exporter mechanism will transparently expose a resource per repository, map CRUD operations onto HTTP methods for that resource, and provide facility to execute the query methods exposed on the repository interface.
But before getting started with Spring Data Exporter , it is important to have a understanding on the REST concept. Also, it is worthy to know that this tutorial will try to simplify the concept of REST by considering the Spring Boot for implementing a standalone spring mvc application.
1. REST
REST stands for Representational State Transfer (REST) is an architectural style. It is a generalization of the principles behind the HTTP protocol, from which it derives the following core concepts:
- Resources: Systems expose resources to other systems: an Employee, an Address, and so on.
- Identifiers: These resources can be addressed through an identifier. In the HTTP world, these identifiers are URIs
- Verbs: Each resource can be accessed and manipulated though a well-defined set of verbs. The most common verbs used in the HTTP are GET, POST, DELETE, HEAD and OPTIONS.
- Representations: A client never interacts with the resource directly but rather through representations of it. As you will be seeing inside this tutorial, the JSON should be used for representing the resources.
2. Persistence Entities
We are using the Employee and Address persistence entity for this tutorials. Lets look at the implementation of these entities and how it is modeled in the database schema. Note that this example uses Java Persistence API (JPA) for the entity exporter. We can use any other persistence provider supported by Spring Data Rest for exporting the entities. Only change will be the persistence repository.
Employee.java
package net.javabeat.springdata.jpa.data; import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; @Entity public class Employee { @Id private Integer employeeId; @Basic(optional = false) private String employeeName; @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "Address") private Address address; public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Integer getEmployeeId() { return employeeId; } public void setEmployeeId(Integer employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public boolean equals(Object obj){ if(obj instanceof Employee){ Employee emp = (Employee)obj; if(this.employeeId == emp.employeeId){ return true; } } return false; } public int hashCode(){ return this.employeeId; } }
Address.java
package net.javabeat.springdata.jpa.data; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToOne; @Entity(name = "address") public class Address { @Id private Integer addressId; private String addressCountry; private String addressCity; @OneToOne(cascade = CascadeType.ALL, mappedBy = "address") private Employee employee; public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public int getAddressId() { return addressId; } public void setAddressId(int addressId) { this.addressId = addressId; } public String getAddressCountry() { return addressCountry; } public void setAddressCountry(String addressCountry) { this.addressCountry = addressCountry; } public String getAddressCity() { return addressCity; } public void setAddressCity(String addressCity) { this.addressCity = addressCity; } }
For your convenience, we have provided the database schema design which will help you for writing the example. Also you can download the example source code at the bottom of this tutorial.
3. JPA Context Configurations
Here is the persistence context used for this tutorial. This configuration file provides configuration details for the MYSQL database driver and the above mentioned persistence entities.
persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="SpringData" transaction-type="RESOURCE_LOCAL"> <class>net.javabeat.springdata.jpa.data.Employee</class> <class>net.javabeat.springdata.jpa.data.Address</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JavaBeat" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.password" value="root" /> <property name="eclipselink.logging.level" value="OFF" /> </properties> </persistence-unit> </persistence>
4. Spring Application Context Configurations
Here is the spring context configuration for this example. For more details about the configurations, please read Spring Data – JPA tutorial.
SpringContext.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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xmlns:jpa="http://www.springframework.org/schema/data/jpa" 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.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!-- For consider the using of annotations foe defining Spring Bean --> <context:annotation-config /> <!-- For defining Spring Bean --> <context:component-scan base-package="net.javabeat.springdata.beans" /> <!-- For bootstrapping the Spring Repository --> <jpa:repositories base-package="net.javabeat.springdata.repo" /> <!-- Necessary to get the entity manager injected into the factory bean --> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <!-- Define EclipseLink JPA Vendor Adapter --> <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> <property name="databasePlatform" value="org.eclipse.persistence.platform.database.MySQLPlatform" /> <property name="generateDdl" value="false" /> <property name="showSql" value="true" /> </bean> <!-- Entity Manager Factory --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <property name="persistenceUnitName" value="SpringData"></property> <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> </bean> <!-- Transaction Manager --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!-- Enable Transactional Manner --> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
5. Spring REST Repositories
For exposing your repositories as a REST, you have to define the repositories using the @RepositoryRestResource annotation.
EmployeeRepository.java
package net.javabeat.springdata.repo; import net.javabeat.springdata.jpa.data.Employee; import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(collectionResourceRel = "employee", path = "employee") public interface EmployeeRepository extends CrudRepository<Employee, Integer>{}
AddressRepository.java
package net.javabeat.springdata.repo; import net.javabeat.springdata.jpa.data.Address; import org.springframework.data.repository.CrudRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(collectionResourceRel = "address", path = "address") public interface AddressRepository extends CrudRepository<Address,Integer>{}
6. Maven Dependencies For Spring Data Rest
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.javabeat.springdata</groupId> <artifactId>SpringData-JPA</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>Spring Data</name> <!-- Inherit defaults from Spring Boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.0.2.RELEASE</version> </parent> <dependencies> <!-- Dependencies for Eclipse JPA Persistence API --> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.5.0-RC1</version> <exclusions> <exclusion> <groupId>org.eclipse.persistence</groupId> <artifactId>commonj.sdo</artifactId> </exclusion> </exclusions> </dependency> <!-- Dependency for MySql Java connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Spring Data Dependency --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> </dependency> <!-- Dependency for REST Exporter --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-rest-webmvc</artifactId> </dependency> <!-- Required Spring Boot Web Application Dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Required Spring Boot JPA Dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> </project>
7. Spring Data REST Exporter Example Application
This example application is executed using the Spring Boot application. If you have the Tomcat runtime in your machine, this below example will embed the tomcat and spring mvc application.
Executable.java
package net.javabeat.springdata.executable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.ImportResource; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; @Configuration @EnableJpaRepositories @Import(RepositoryRestMvcConfiguration.class) @ImportResource("classpath:SpringContext.xml") @EnableAutoConfiguration public class Executable { public static void main(String[] args) { SpringApplication.run(Executable.class, args); } }
8. Running Application
You can now access the Spring Data Rest through browser which will be exposed as the REST services.
9. Summary
Spring Data provides the Spring Developer that ability to create a REST web services against already user defined CRUD repositories. This service is limited to the CRUD repositories but in the next coming releases other types of repositories should be supported.