Typesafe Activator

Play with Spring Data Jpa

Play with Spring Data Jpa

typesafehub
Source
January 31, 2014
playframework spring data jpa dependency-injection

This is a Play example that uses Spring Data Jpa (http://www.springsource.org/spring-data/jpa).

How to get "Play with Spring Data Jpa" on your computer

There are several ways to get this template.

Option 1: Choose play-spring-data-jpa in the Typesafe Activator UI.

Already have Typesafe Activator (get it here)? Launch the UI then search for play-spring-data-jpa in the list of templates.

Option 2: Download the play-spring-data-jpa project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for play-spring-data-jpa.

  1. Download the Template Bundle for "Play with Spring Data Jpa"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Typesafe Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\play-spring-data-jpa> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a play-spring-data-jpa project from the command line

If you have Typesafe Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME play-spring-data-jpa on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/typesafehub/play-spring-data-jpa#master.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial

Play with Spring Data Jpa

Spring Data Jpa provides a higher level of abstraction than having to deal with the Jpa api directly. A great deal of boilerplate code can be avoided when using Spring Data Jpa. When you combine Spring Data Jpa with Play you can focus on solving the business problem at hand.

This project uses Java but can work equally as well with Scala.

This tutorial will take about 10 minutes to complete and assumes that you are already familiar with the basics of a Play application.

The Domain Model

Our domain model is simple for the purposes of demonstrating Spring Data. Person describes a Jpa entity with a few properties, namely id, firstname and surname.

The members are declared public as Jpa entities tend to be simple structures. When behaviour is required then it tends to be related to the instance. Class level behaviour is relegated to a repository e.g. finding instances (discussed next).

Play will synthesise getters and setters for public properties so they do not have to be declared. You typically declare getters and setters when you require behaviour beyond getting or setting the property. Getters and setters are required by Jpa for entity classes, so this is a nice saving of code given Play.

Repositories

Repositories represent the operations that are performed on an "aggregate root" object. The aggregate root ensures the consistency of changes being made within the aggregate e.g. if an Order is to be saved then any associated order details are saved along with it. Operations on a repository therefore tend to be atomic in nature and manage their own transactions.

We have created a simple PersonRepository that extends Spring Jpa's CrudRepository; Crud representing common Create Retrieve Update and Delete operations. We use @Named to declare that the repository is available for dependency injection and @Singleton to declare that only one instance of it is generally required.

You can do a great deal with Spring Data Jpa and provide custom behaviour for the repository. The operations on a repository tend to relate strongly to how the logic layer (web controllers) atomically consumes and produces data.

The Application

Application represents a conventional means of making a synchronous, blocking call to a database (JPA is synchronous and blocking). The repository is injected into the controller via constructor injection via the use of @Inject. We use constructor injection in order to promote an immutable programming model. Immutable variables assist toward providing an inherently thread-safe application.

Note that you have not had to provide any code to perform the repository's save or findOne operations. Spring Data did that for you.

As with the repository being used, Application is declared as being injectable as a single instance via @Inject and @Singleton respectively.

Because Spring's dependency injection system is being used we declare Application as a class with instance methods as opposed to static methods. This is so that we can have Play ask our Global object for instances of Application that have been subjected to dependency injection. More on the Global object next.

The Global

Global sets up Spring's dependency injection system and configures Spring Data with Jpa concerns.

An AnnotationConfigApplicationContext is established and started such that it scans the controllers and models packages for @Named classes to become available for dependency injection. In addition a SpringDataJpaConfiguration inner class is instantiated and provides further configuration of Spring Data. In particular an EntityManagerFactory is made available that uses the a Jpa persistence unit named "default". You can see this persistence unit declared in conf/META-INF/persistence.xml.

The getControllerInstance method is called on by Play whenever a controller is required. More specifically Play will call getControllerInstance when it finds an '@' symbol in front of a route declaration. Check out the routes file for the declaration of controllers.Application.index. We pass on the responsibility of locating a controller instance to Spring so that it is subject to dependency injection.

Testing

ApplicationIT provides an integration test for the Application controller. The purpose of the test is to exercise the routing configuration and the logic within the controller's methods. Dependencies of the controller are not intended to be tested here and so the PeopleRepository is mocked. Most importantly no database is required to be established for this test to run, thereby resulting in a simpler and perhaps faster test.

The mocked PeopleRepository is manually injected into the Application controller, and the controller is made available in a stub implementation of the GlobalSettings class. Because the test extends WithApplication, it is focused on testing a Play application. We construct a FakeApplication with the instance of the GlobalSetting stub as part of the test setup. The indexSavesDataAndReturnsId test then performs its specific setup and routes a GET request. Finally expectations are set on the response.

Conclusion

This tutorial has taken you through the requirements of a Play application in order to use Spring Data Jpa. While this project uses Java you can use Scala equally as well. Spring Data also provides support for NoSQL stores and so a similar setup to this project can be used for many types of repository.

Happy Play-ing with Spring Data.

comments powered by Disqus