Home » Java » Enterprise Java » Spring Data REST in Action

About Gregor Riegler

Gregor Riegler
Gregor is a passionate software engineer and RESTafarian who loves to continuously improve. He is interested in modern web development, oo-design and extreme programming. He is also serious about clean code and TDD.

Spring Data REST in Action

What is spring-data-rest?

spring-data-rest, a recent addition to the spring-data project, is a framework that helps you expose your entities directly as RESTful webservice endpoints. Unlike rails, grails or roo it does not generate any code achieving this goal. spring data-rest supports JPA, MongoDB, JSR-303 validation, HAL and many more. It is really innovative and lets you setup your RESTful webservice within minutes. In this example i’ll give you a short overview of what spring-data-rest is capable of.

Initial Configuration

I’m gonna use the new Servlet 3 Java Web Configuration instead of an ancient web.xml. Nothing really special here.

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{AppConfiguration.class};

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfiguration.class};

    protected String[] getServletMappings() {
        return new String[]{"/"};

WebAppInitializer.java on github

I am initializing hibernate as my database abstraction layer in the AppConfiguration class. I’m using an embedded database (hsql), since i want to keep this showcase simple stupid. Still, nothing special here.

public class AppConfiguration {

    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder.setType(EmbeddedDatabaseType.HSQL).build();

    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

        return factory;

    public PlatformTransactionManager transactionManager() {
        return new JpaTransactionManager();

AppConfiguration.java on github

Now to the application servlet configuration: WebConfiguration

public class WebConfiguration extends RepositoryRestMvcConfiguration {

WebConfiguration.java on github

Oh, well thats a bit short isnt it? Not a single line of code required for a complete setup. This is a really nice application of the convention over configuration paradigm. We can now start creating spring-data-jpa repositories as they will be exposed as RESTful resources automatically. And we can still add custom configuration to the WebConfiguration class if needed.

The Initialization was really short and easy. We didn’t have to code anything special. The only thing we did was setting up a database connection and hibernate, which is obviously inevitable. Now, that we have setup our “REST Servlet” and persistence, lets move on to the application itself, starting with the model.

The Model

I’ll keep it really simple creating only two related entities.

public class Book {

    private String isbn;

    private String title;

    private String language;

    private List<Author> authors;


Book.java on github

public class Author {

    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer id;

    private String name;

    @ManyToMany(mappedBy = "authors")
    private List<Book> books;


Author.java on github

To finally make the entities persistent and exposed as a RESTful webservice, we need spring-data repositories. A repository is basically a DAO. It offers CRUD functionality for our entities. spring-data takes away most of your programming effort creating such repositories. We just have to define an empty interface, spring-data does everything else out of the box. Still, it is easily customizable thanks to its design by convention over configuration!

The Actual Repositories

@RestResource(path = "books", rel = "books")
public interface BookRepository extends PagingAndSortingRepository<Book, Long> {

BookRepository.java on github

@RestResource(path = "authors", rel = "authors")
public interface AuthorRepository extends PagingAndSortingRepository<Author, Integer> {

AuthorRepository.java on github

Again, there is nearly no code needed. Even the @RestResource annotation could be left out. But if i did, the path and rel would be named after the entity, which i dont want. A REST resource that contains multiple children should be named plural though.

Accessing The Result

Our RESTful webservice is now ready for deployment. Once run, it lists all available resources on the root, so you can navigate from there.

GET http://localhost:8080/

  "links" : [ {
    "rel" : "books",
    "href" : "http://localhost:8080/books"
  }, {
    "rel" : "authors",
    "href" : "http://localhost:8080/authors"
  } ],
  "content" : [ ]

Fine! Now lets create an author and a book.

POST http://localhost:8080/authors

{"name":"Uncle Bob"}


201 Created
Location: http://localhost:8080/authors/1

PUT http://localhost:8080/books/0132350882

  "title": "Clean Code",
  "authors": [
          "rel": "authors",
          "href": "http://localhost:8080/authors/1"


201 Created

Noticed how i used PUT to create the book? This is because its id is the actual isbn. I have to tell the server which isbn to use since he cant guess it. I used POST for the author as his id is just an incremental number that is generated automatically. Also, i used a link to connect both, the book (/books/0132350882) and the author (/authors/1). This is basically what hypermedia is all about: Links are used for navigation and relations between entities.

Now, lets see if the book was created accordingly.

GET http://localhost:8080/books

  "links" : [ ],
  "content" : [ {
    "links" : [ {
      "rel" : "books.Book.authors",
      "href" : "http://localhost:8080/books/0132350882/authors"
    }, {
      "rel" : "self",
      "href" : "http://localhost:8080/books/0132350882"
    } ],
    "title" : "Clean Code"
  } ],
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 1


Here is an Integration Test, following these steps automatically. It is also available in the example on github.

public class BookApiIT {

    private final RestTemplate restTemplate = new RestTemplate();

    private final String authorsUrl = "http://localhost:8080/authors";
    private final String booksUrl = "http://localhost:8080/books";

    public void testCreateBookWithAuthor() throws Exception {
        final URI authorUri = restTemplate.postForLocation(authorsUrl, sampleAuthor()); // create Author

        final URI bookUri = new URI(booksUrl + "/" + sampleBookIsbn);
        restTemplate.put(bookUri, sampleBook(authorUri.toString())); // create Book linked to Author

        Resource<Book> book = getBook(bookUri);

        final URI authorsOfBookUri = new URI(book.getLink("books.Book.authors").getHref());
        Resource<List<Resource<Author>>> authors = getAuthors(authorsOfBookUri);
        assertFalse(authors.getContent().isEmpty()); // check if /books/0132350882/authors contains an author

    private String sampleAuthor() {
        return "{\"name\":\"Robert C. Martin\"}";

    private final String sampleBookIsbn = "0132350882";

    private String sampleBook(String authorUrl) {
        return "{\"title\":\"Clean Code\",\"authors\":[{\"rel\":\"authors\",\"href\":\"" + authorUrl + "\"}]}";

    private Resource<Book> getBook(URI uri) {
        return restTemplate.exchange(uri, HttpMethod.GET, null, new ParameterizedTypeReference<Resource<Book>>() {

    private Resource<List<Resource<Author>>> getAuthors(URI uri) {
        return restTemplate.exchange(uri, HttpMethod.GET, null, new ParameterizedTypeReference<Resource<List<Resource<Author>>>>() {

BookApiIT.java on github


We have created a complete RESTful webservice without much coding effort. We just defined our entities and database connection. spring-data-rest stated that everything else is just boilerplate, and i agree.

To consume the webservices manually, consider the rest-shell. It is a command-shell making the navigation in your webservice as easy and fun as it could be. Here is a screenshot:
The complete example is available on my github


Reference: Spring Data REST in Action from our JCG partner Gregor Riegler at the Be a better Developer blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!


1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design


and many more ....


Receive Java & Developer job alerts in your Area from our partners over at ZipRecruiter



  1. Your maven project doesn’t build. mvn package produces errors.

    • Thank you! i just found out that some really nice guy called Jay Sissom already fixed that.
      Thank you Jay, your pull request was merged!

      It should now build

      • Maven still cannot build. I am getting the following errors:
        Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1.1:war (default-war) on project message-converter: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]

        • web.xml was also missing for message-converter. i added it. you should now be able to package.

          but please, if you want to build the spring-data-rest package, just build the submodule not the main module. otherwise you are building both.

          greetings, gregor

          • Thanks. Builds fine. However when starting jetty (Jetty6 since we are using Java 6), the server starts up but it doesn’t seem to work well. In all, it would be great to have some steps as to how to get your code up and running soup to nuts.

  2. How i can fix if i use Turkish char set like; Ş, ı, ö, ğ ?

    • Hi Edirne,
      Im not familiar how spring-data-rest deals with unicode in particular, but what i do know is that there are several Points you need to check in order to get your characters to work.

      1.) Does your database support unicode characters? Did you use the right collation? Can you store a Ş in your database without spring-data?

      Often unicode problems are not caused by the framework but the database itself. So check that first!

      2.) Are the characters broken in Java?

      Debug a Request, follow the parsed body and check if they are already broken within java. If not, it might be an issue with the jdbc driver or something more database related.

      If it is already broken in Java you might check if you are using the right content-type in your HTTP Requests. Make sure that u are using an utf-8 content type like so:
      content=”application/json; charset=utf-8″

      3.) If all those points dont help, maybe your REST Client is causing broken characters. Some REST Clients are badly written and transfer iso-8859-1 Strings regardless of the charset that you are using.
      Thus, your characters break right in your REST Client.

      Make sure you try another rest client. curl should work without a problem.

  3. I’m attempting to startup your project and so far been unsuccessful.

    Do I need to download both of your projects? The REST project seems to complain about a parent pom.xml… I am unfamiliar with Maven and would really appreciate some assistance because your project is so far the simplest implementation I’ve found of a REST Data project..

    My own needs will require a MySQL instead of HSQL implementation as well, but I imagine it shouldn’t be as hard to figure out as Maven has been.

    • Hi Erik,

      Unfortunately, the examples are both inside a single multi-module-maven-project. Thus, i suggest you download the whole trunk. Maybe it’d be better if i separate those examples. I’ll do this as soon as possible.

      Greetings, Gregor

      • Perhaps if you just explain what projects you’re leveraging I can try to whip up a gradle file.

        I see Hibernate, Spring-Data, but unsure what else. Trying to get this awesome code to run in a standalone manner via a Gradle build is my current goal.

      • After much research and toil, I got your project to compile in a standalone version. If you message me a good email I can zip it up to you.

        The only thing I need now, is to learn how to customize this example. I’m running Tomcat and want this service to deploy in a folder .. not root.

        I tried changing just WebAppInitializer.java , under the getServletMappings.. but it did not work.

  4. This is supposed to be deployed to a server, not run standalone.. correct? You kind of gloss over that in this part:

    “Our RESTful webservice is now ready for deployment. Once run, it lists all available resources on the root, so you can navigate from there.”

    I popped this into TomCat on my gradle based build of your project and it’s throwing errors.

  5. In attempting to backtrack from my gradle build (it’s not deploying to TOMCAT properly), I thought I’d try building just your whole maven project..

    however your pom.xml has no build goals. I’m brand new to most of these tools and it would help if your POM had a goal to clarify what it’s building either a .war or .jar (.war in this case right?)

    [ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]

  6. Nice article. i can build and deploy successfully.

    Could you please tell me where this data persist

  7. thanks Gregor for writing up this tutorial, it has been very helpful to get started with Spring data rest.
    I have noticed one issue here: ID for book is String (isbn) yet, the BookRepository is declared as Long. Anyway, that was a easy fix. The part that I am having trouble with is adding book with author href. I am getting the following error:

    message: “Could not read JSON: (was java.lang.NullPointerException) (through reference chain: com.khan.sdr2.model.Book[“authors”]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.khan.sdr2.model.Book[“authors”])”

    any idea ?

  8. Hi, How to include validation for the fields using spring data rest. I have tried many ways all in vain. Any tutorials to do that?

  9. Hi is it possible to create a new author with his books in only ONE POST?

  10. How do I can configure the methods save, update and delete to only ROLE_ADMIN can access them? My repository its like:

    public interface OrganizationRepository extends CrudRepository {


  11. Is it possible to add a new book and an author in a single post request? i am having a projection used to display data from multiple interrelated entities but so far finding it hard to save to different entities with single post.

Leave a Reply

Your email address will not be published. Required fields are marked *


Want to take your Java skills to the next level?

Grab our programming books for FREE!

Here are some of the eBooks you will get:

  • Spring Interview QnA
  • Multithreading & Concurrency QnA
  • JPA Minibook
  • JVM Troubleshooting Guide
  • Advanced Java
  • Java Interview QnA
  • Java Design Patterns