8621. Creating RESTful Web Services with Spring Boot
Spring Boot, RESTful, and Maven


Build RESTful Web Service with Spring Boot and Maven in Java.

1. Setup

1.1 Java Development Environment

Install JDK, Eclipse and Tomcat first.

1.2 Maven

In addition, we will use maven as build tool. So Maven is also required to be installed.

$ brew install maven // Mac OS $ sudo apt-get install maven // Linux 

Check maven version.

$ mvn -version Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2016-02-20T12:39:06-07:00) Maven home: /usr/local/Cellar/maven/3.5.0/libexec Java version: 1.8.0_101, vendor: Oracle Corporation Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre Default locale: en_US, platform encoding: UTF-8 OS name: "mac os x", version: "10.12.6", arch: "x86_64", family: "mac" 

2. SpringBoot Project

2.1 Enabling Maven Index

In Eclipse, top menu Eclipse -> Preferences, and then choose Maven in the left side. Check the box ‘Download repository index updates on startup’. Optionally, check the boxes ‘Download Artifact Sources’ and ‘Download Artifact JavaDoc’. image

2.2 Rebuilding Index

In Eclipse, Window -> Show View -> Other -> Maven -> Maven Repositories, tick ‘Full Index Enabled’ and then ‘Rebuild Index’ for ‘Global Repositories’. image

2.2 Creating Maven Project

1) In Eclipse, File -> New -> ‘Maven Project’, check the box ‘Create a simple project’-> Next, Name: SpringBootTutorial
image
In the new created project, there are two main branches, one is for source code, another is for test. image

2.2 Specifying Java Version

Since, we will use lamda expression, specify java version to java 8 in pom.xml.

<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> 

2.3 Adding Dependency

Add spring boot dependency to pom.xml.

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> 

Starter for using Spring Data JPA with Hibernate.

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> 

Use H2 in-memory database.

<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> 

2.4 Creating Service

1) Create Package
Right click project SpringBootTutorial->src->main->java>New->Package, Package Name: johnny.tutorial.SpringBootTutorial
2) Create Executable Application
RestApplication.java with dummy data.

package johnny.tutorial.SpringBootTutorial; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import johnny.tutorial.SpringBootTutorial.domain.Product; import johnny.tutorial.SpringBootTutorial.repository.ProductRepository; @SpringBootApplication public class RestApplication { public static void main(String[] args) { SpringApplication.run(RestApplication.class, args); } @Bean CommandLineRunner runner(ProductRepository productRepository) { return args -> { Product product1 = new Product("iPhone 7s"); product1.setPrice(700.00); productRepository.save(product1); Product product2 = new Product("iPad 4"); product2.setPrice(500.00); productRepository.save(product2); Product product3 = new Product("iPod"); product3.setPrice(300.00); productRepository.save(product3); }; } } 

Create folder domain and create class Product in domain.
Product.java

package johnny.tutorial.SpringBootTutorial.domain; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Product { @Id @GeneratedValue private Long id; private String name; private double price; @SuppressWarnings("unused") private Product(){} public Product(String name) { this.name = name; } 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 double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Product [name=" + name + ", price=" + price + "]"; } } 

Create folder repository and create interface ProductRepository in repository. ProductRepository.java

package johnny.tutorial.SpringBootTutorial.repository; import org.springframework.data.repository.CrudRepository; import johnny.tutorial.SpringBootTutorial.domain.Product; public interface ProductRepository extends CrudRepository<Product, Long> { } 

Create folder service and create interface ProductService in serice folder, and create ProductService.java

package johnny.tutorial.SpringBootTutorial.service; import johnny.tutorial.SpringBootTutorial.domain.Product; public interface ProductService { Iterable<Product> list(); Product create(Product product); Product read(long id); Product update(long id, Product product); void delete(long id); } 

ProductServiceImpl.java

package johnny.tutorial.SpringBootTutorial.service; import javax.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import johnny.tutorial.SpringBootTutorial.domain.Product; import johnny.tutorial.SpringBootTutorial.repository.ProductRepository; public class ProductServiceImpl implements ProductService { private ProductRepository productRepository; @Autowired public ProductServiceImpl(ProductRepository postRepository){ this.productRepository = productRepository; } @Override public Iterable<Product> list() { return productRepository.findAll(); } @Override public Product read(long id) { return productRepository.findOne(id); } @Override @Transactional public Product create(Product product) { // save the new product return productRepository.save(product); } @Override public void delete(long id) { productRepository.delete(id); } @Override public Product update(long id, Product update) { Product product = productRepository.findOne(id); if( update.getName() != null ) { product.setName(update.getName()); } return productRepository.save(product); } } 

Finally, create controller folder and create ProductController in controller.

package johnny.tutorial.SpringBootTutorial.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import johnny.tutorial.SpringBootTutorial.domain.Product; import johnny.tutorial.SpringBootTutorial.repository.ProductRepository; @RestController @RequestMapping("/products") public class ProductController { ProductRepository productRepository; @Autowired public ProductController(ProductRepository productRepository){ this.productRepository = productRepository; } @RequestMapping("/") public Iterable<Product> list(){ return productRepository.findAll(); } @RequestMapping("/{id}") public Product read(@PathVariable(value="id") long id){ return productRepository.findOne(id); } } 

2.5 Project Structure

This is the final structure of this tutorial project. image

2.6 Running and Testing

run spring boot project with maven

$ mvn spring-boot:run 

Use Postman to access http://localhost:8080/ for testing.
1) Get Product List
URL: http://localhost:8080/products/ image
2) Get Product by ID
URL: http://localhost:8080/product/1 image

3. Supporting XML

3.1 Adding Dependency to pom.xml

<dependencies> ... <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency> </dependencies> 

3.2 Running and Testing

restart spring boot.

$ mvn spring-boot:run 

In Postman, add Accept = “application/xml” to Header.
URL: http://localhost:8080/products/1 image

4. Enabling Autoload

Add dependency of Spring Dev-Tool in pom.xml

<dependencies> ... <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> 

change the name and price of product1. image
Don’t restart maven. Just send request again. The new product is returned. image

5. Debugging

1) In Eclipse, set breakpoint inside the method(eg. StringController.java->reverse()) you want to debug.
2) Right click on the RestApplication.java, choose “Debug As” -> “Java Application”.
3) In postman, access the url to trigger method being called. You should see breakpoint is activated.

6. Source Files

7. Reference