1. What You Will Learn
-
How to use repositories for data access
-
How to expose a REST API on top of those repositories
-
How to use an embedded database for development
-
How to use a production ready database in production
-
How to gain access to the command line arguments and run specific code once
-
How to control log levels
2. Exercises
2.1. Add an Embedded Database
Review the following file: hello-spring-boot-rest/pom.xml
. By adding the H2
dependency, we have added embedded database support for the hello-spring-boot-rest
application. This helps us get started quickly in development, as we don’t have to provision a database.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
2.2. Persistence With Spring Data JPA
In the same pom.xml
file, you’ll notice the spring-boot-starter-data-jpa
dependency, which provides Spring Data JPA support for the hello-spring-boot-rest
application.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Implementing a data access layer of an application has been cumbersome for quite a while. Too much boilerplate code has to be written to execute simple queries as well as perform pagination, and auditing. Spring Data JPA aims to significantly reduce the effort required to implement data access. As a developer you write your repository interfaces, including custom finder methods, and Spring provides the implementation automatically.
To learn more on Spring Data JPA see http://docs.spring.io/spring-data/jpa/docs/1.11.1.RELEASE/reference/html/.
-
Review the following file:
hello-spring-boot-rest/src/main/java/io/pivotal/hello/Greeting.java
. This is a typical JPA domain entity. This class represents one row in ourgreeting
table.package io.pivotal.hello; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Greeting { @Id private Long id; private String text; public Greeting() { } public Greeting(Long id, String text) { this.id = id; this.text = text; } public Long getId() { return id; } public String getText() { return text; } @Override public String toString() { return "Greeting [id=" + id + ", text=" + text + "]"; } }
-
Review the file
GreetingRepository.java
. This repository interface provides CRUD operations against thegreeting
table. All without the developer having to write an implementation!package io.pivotal.hello; import org.springframework.data.jpa.repository.JpaRepository; public interface GreetingRepository extends JpaRepository<Greeting, Long> { }
-
Review the file:
hello-spring-boot-rest/src/main/resources/application.yml
. Thespring.jpa.hibernate.ddl-auto
setting controls how/if DDL changes are made. In this case, our application will update the schema on startup if necessary. Read more on database initialization here.logging: level: io: pivotal: DEBUG spring: jpa: hibernate: ddl-auto: update
2.3. Add a Restful API with Spring Data Rest
Note that the project’s pom.xml
file also includes the spring-boot-starter-data-rest
dependency, which adds REST support for our JPA repositories in the hello-spring-boot-rest
application.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
The goal of the Spring Data REST project is to provide a solid foundation on which to expose CRUD operations to your repositories using plain HTTP REST semantics. Read more on Spring Data REST here.
For the GreetingRepository
, Spring Data REST exposes a collection resource at /greetings
. The path is derived from the uncapitalized, pluralized, simple class name of the domain class being managed. It also exposes an item resource for each of the items managed by the repository under the URI template /greetings/{id}
.
We will explore the REST API, once we populate the database.
2.4. How to Run Code on Startup
In many cases, you need to run some code on startup. Spring Boot allows you capture the command line arguments and run code just as if you had implemented public static void main(String[] args)
by implementing a CommandLineRunner
bean.
CommandLineRunner
is a core feature to Spring Boot so there are no dependencies that need to be explicitly added.
-
Review the following file:
hello-spring-boot-rest/src/main/java/io/pivotal/hello/HelloSpringBootApplication.java
.
package io.pivotal.hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class HelloSpringBootApplication {
private final Logger logger = LoggerFactory.getLogger(HelloSpringBootApplication.class);
public static void main(String[] args) {
SpringApplication.run(HelloSpringBootApplication.class, args);
}
@Bean
CommandLineRunner loadDatabase(GreetingRepository repository) {
return args -> {
logger.debug("loading database..");
repository.save(new Greeting(1L, "Hello"));
repository.save(new Greeting(2L, "Hola"));
repository.save(new Greeting(3L, "Ohai"));
logger.debug("record count: {}", repository.count());
repository.findAll().forEach(x -> logger.debug(x.toString()));
};
}
}
In this case, we are using a CommandLineRunner
to populate the database with our GreetingRepository
.
2.5. Turn Up Logging
To view the debug statements in the class we can turn up logging.
-
Review the following file:
hello-spring-boot-rest/src/main/resources/application.yml
.
logging:
level:
io:
pivotal: DEBUG
Log levels can be ERROR
, WARN
, INFO
, DEBUG
or TRACE
.
Simply specify the package/class in the logging.level
key and set the desired level.
In this case, we have turned on DEBUG
logging for everything in the io.pivotal
package.
2.6. Run hello-spring-boot-rest
-
Open a terminal window.
$ cd hello-spring-boot-rest $ mvn spring-boot:run
-
View the logs in the terminal output. See the database being populated.
2015-10-06 13:42:27.350 DEBUG 65573 --- [lication.main()] i.p.hello.HelloSpringBootApplication : loading database.. 2015-10-06 13:42:27.527 DEBUG 65573 --- [lication.main()] i.p.hello.HelloSpringBootApplication : record count: 3 2015-10-06 13:42:27.564 DEBUG 65573 --- [lication.main()] i.p.hello.HelloSpringBootApplication : Greeting [id=1, text=Hello] 2015-10-06 13:42:27.564 DEBUG 65573 --- [lication.main()] i.p.hello.HelloSpringBootApplication : Greeting [id=2, text=Hola] 2015-10-06 13:42:27.564 DEBUG 65573 --- [lication.main()] i.p.hello.HelloSpringBootApplication : Greeting [id=3, text=Ohai]
-
Browse to http://localhost:8080/greetings
Notice that not just data is returned but links on how to navigate the API. This is provided by Spring HATEOAS as opposed to establishing a contract up front or use of documentation. Read more on HATEOAS.
-
Experiment with paging and sorting
-
Sort by text in ascending order: http://localhost:8080/greetings?sort=text,asc
-
Sort by text in descending order: http://localhost:8080/greetings?sort=text,desc
-
Get page 0, size 1: http://localhost:8080/greetings?size=1&page=0
-
Get page 1, size 1: http://localhost:8080/greetings?size=1&page=1
-
-
Stop the
hello-spring-boot-rest
application.
Congratulations! You’ve completed this lab. In the next lab we’re going to discuss how to deploy this application to cloud foundry.