Java Technology - 2018 - Spring Boot

Spring Boot

It is a Spring module which provides RAD (Rapid Application Development) feature to Spring framework.
It is used to create stand alone spring based application that you can just run because it needs very little spring configuration.
Spring Boot does not generate code and there is absolutely no requirement for XML configuration.
It uses convention over configuration software design paradigm that means it decrease the effort of developer.

Advantages of Spring Boot

  • Create stand-alone Spring applications that can be started using java -jar.
  • Embed Tomcat, Jetty or Undertow directly. You don't need to deploy WAR files.
  • It provides opinionated 'starter' POMs to simplify your Maven configuration.
  • It automatically configure Spring whenever possible.
  • It provides production-ready features such as metrics, health checks and externalized configuration.
  • Absolutely no code generation and no requirement for XML configuration.

Prerequisite of Spring Boot

To create a Spring Boot application following are the prerequisites. In this tutorial, we will use Spring Tool Suite IDE.
  • Java 1.8
  • Gradle 2.3+ or Maven 3.0+
  • Spring Framework 5.0.0.BUILD-SNAPSHOT
  • An IDE (Spring Tool Suit) is recommended.


Spring Boot Features

  • Web Development
  • SpringApplication
  • Application events and listeners
  • Admin features
  • Externalized Configuration
  • Properties Files
  • YAML Support
  • Type-safe Configuration
  • Logging
  • Security

Web Development

It is well suited Spring module for web application development. We can easily create a self-contained HTTP server using embedded Tomcat, Jetty or Undertow. We can use the spring-boot- starter-web module to start and running application quickly.

SpringApplication

It is a class which provides the convenient way to bootstrap a spring application which can be started from main method. You can call start your application just by calling a static run() method.
  1. public static void main(String[] args){  
  2.     SpringApplication.run(className.class, args);  
  3. }  

Application Events and Listeners

Spring Boot uses events to handle variety of tasks. It allows us to create factories file that are used to add listeners. we can refer it by using ApplicationListener key.
Always create factories file in META-INF folder like: META-INF/spring.factories

Admin Support

Spring Boot provides the facility to enable admin related features for the application. It is used to access and manage application remotely. We can enable it by simply using spring.application.admin.enabled property.

Externalized Configuration

Spring Boot allows us to externalize our configuration so that we can work with the same application in different environments. Application use YAML files to externalize configuration.

Properties Files

Spring Boot provides rich set of Application Properties. So, we can use that in properties file of our project. Properties file is used to set properties like: server-port = 8082 and many others. It helps to organize application properties.

YAML Support

It provides convenient way for specifying hierarchical configuration. It is a superset of JSON. The SpringApplication class automatically support YAML. It is successful alternative of properties.

Type-safe Configuration

Strong type-safe configuration is provided to govern and validate the configuration of application. Application configuration is always a crucial task which should be type-safe. We can also use annotation provided by this library.

Logging

Spring Boot uses Common logging for all internal logging. Logging dependencies are managed by default. We should not change logging dependencies, if there is no required customization is needed.

Security

Spring Boot applications are spring bases web applications. So, it is secure by default with basic authentication on all HTTP endpoints. A rich set of Endpoints are available for develop a secure Spring Boot application.

Spring Boot Project

There are multiple approaches to create Spring Boot project. We can use any of the following approach to create application.
  • Spring Maven Project
  • Spring Starter Project Wizard
  • Spring Initializr
  • Spring Boot CLI
Here for all the example, we are using STS (Spring Toll Suite) IDE to create project. You can download this IDE from official site of Spring framework.


------------------------------------------------
Create New Maven project:
click on create a simple project. Next


In pom.xml:
Add:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>

Now update maven.
on right click project-properties-project facets-update java to 1.6 and also select dynamic web module.

package com.javatpoint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootExample {
public static void main(String[] args) {
SpringApplication.run(SpringBootExample.class, args);
}

}

package com.javatpoint;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController 
public class WelcomeController {
private WelcomeService service = new WelcomeService();

@RequestMapping("/welcome")
public String welcome(){
return service.retriveWelcomeMessage();
}

class WelcomeService{
public String retriveWelcomeMessage(){
//complex method
return "Good Morning";
}
}


}

run SpringBootExample as Java application (not run on Server)
Everytime you finish running application stop tomcat
go on browser and enter: localhost:8080\welcome to see the output

Add @Autowired and @Component to tell Spring to manage beans - Dependency Injection
package com.javatpoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController 
public class WelcomeController {
@Autowired
private WelcomeService service;
@RequestMapping("/welcome")
public String welcome(){
return service.retriveWelcomeMessage();
}
@Component
class WelcomeService{
public String retriveWelcomeMessage(){
//complex method
return "Good Morning";
}
}

}

Stop tomcat and again run as application

Change WelcomeController to 
package com.javatpoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.service.WelcomeService;

@RestController 
public class WelcomeController {
@Autowired
private WelcomeService service;
@RequestMapping("/welcome")
public String welcome(){
return service.retriveWelcomeMessage();
}

}
Here we import WelcomeService. Just to check whether spring is able to scan component or not.
For this, WelcomeService is defined as follows in new package com.service and WelcomeService need to be public otherwise it is not visible to other class. 

package com.service;

import org.springframework.stereotype.Component;

@Component 
public class WelcomeService{
public String retriveWelcomeMessage(){
//complex method
return "Good Morning Updated.";
}
}

For this, SpringBootExample need to add @ComponentScan("com"). So that Spring will scan all the @components inside the package com. If spring find it will autowired it else it throws exception.

package com.javatpoint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan("com")
@SpringBootApplication
public class SpringBootExample {
public static void main(String[] args) {
SpringApplication.run(SpringBootExample.class, args);
}
}

Some annotation:
@Component, @Repository, @Controller, @RestController @Service

Spring Boot provides a number of “Starters” that let you add jars to your classpath. Our sample application has already used spring-boot-starter-parent in the parent section of the POM. The spring-boot-starter-parent is a special starter that provides useful Maven defaults. It also provides a dependency-managementsection so that you can omit version tags for “blessed” dependencies.
Other “Starters” provide dependencies that you are likely to need when developing a specific type of application. Since we are developing a web application, we add aspring-boot-starter-web dependency.
Here we didn't configure dispatcher servlet which are auto configured in spring boot
apache tomcat is automatically set as server.
Error page is improved.



Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, include the spring-boot-starter-data-jpa dependency in your project.
The starters contain a lot of the dependencies that you need to get a project up and running quickly and with a consistent, supported set of managed transitive dependencies.
The following application starters are provided by Spring Boot under the org.springframework.boot group:

Table 13.1. Spring Boot application starters
NameDescriptionPom
spring-boot-starterCore starter, including auto-configuration support, logging and YAMLPom
spring-boot-starter-activemqStarter for JMS messaging using Apache ActiveMQPom
spring-boot-starter-amqpStarter for using Spring AMQP and Rabbit MQPom
spring-boot-starter-aopStarter for aspect-oriented programming with Spring AOP and AspectJPom
spring-boot-starter-artemisStarter for JMS messaging using Apache ArtemisPom
spring-boot-starter-batchStarter for using Spring BatchPom
spring-boot-starter-cacheStarter for using Spring Framework’s caching supportPom
spring-boot-starter-cloud-connectorsStarter for using Spring Cloud Connectors which simplifies connecting to services in cloud platforms like Cloud Foundry and HerokuPom
spring-boot-starter-data-cassandraStarter for using Cassandra distributed database and Spring Data CassandraPom
spring-boot-starter-data-cassandra-reactiveStarter for using Cassandra distributed database and Spring Data Cassandra ReactivePom
spring-boot-starter-data-couchbaseStarter for using Couchbase document-oriented database and Spring Data CouchbasePom
spring-boot-starter-data-couchbase-reactiveStarter for using Couchbase document-oriented database and Spring Data Couchbase ReactivePom
spring-boot-starter-data-elasticsearchStarter for using Elasticsearch search and analytics engine and Spring Data ElasticsearchPom
spring-boot-starter-data-jpaStarter for using Spring Data JPA with HibernatePom
spring-boot-starter-data-ldapStarter for using Spring Data LDAPPom
spring-boot-starter-data-mongodbStarter for using MongoDB document-oriented database and Spring Data MongoDBPom
spring-boot-starter-data-mongodb-reactiveStarter for using MongoDB document-oriented database and Spring Data MongoDB ReactivePom
spring-boot-starter-data-neo4jStarter for using Neo4j graph database and Spring Data Neo4jPom
spring-boot-starter-data-redisStarter for using Redis key-value data store with Spring Data Redis and the Lettuce clientPom
spring-boot-starter-data-redis-reactiveStarter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce clientPom
spring-boot-starter-data-restStarter for exposing Spring Data repositories over REST using Spring Data RESTPom
spring-boot-starter-data-solrStarter for using the Apache Solr search platform with Spring Data SolrPom
spring-boot-starter-freemarkerStarter for building MVC web applications using FreeMarker viewsPom
spring-boot-starter-groovy-templatesStarter for building MVC web applications using Groovy Templates viewsPom
spring-boot-starter-hateoasStarter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOASPom
spring-boot-starter-integrationStarter for using Spring IntegrationPom
spring-boot-starter-jdbcStarter for using JDBC with the Tomcat JDBC connection poolPom
spring-boot-starter-jerseyStarter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-webPom
spring-boot-starter-jooqStarter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbcPom
spring-boot-starter-jsonStarter for reading and writing jsonPom
spring-boot-starter-jta-atomikosStarter for JTA transactions using AtomikosPom
spring-boot-starter-jta-bitronixStarter for JTA transactions using BitronixPom
spring-boot-starter-jta-narayanaSpring Boot Narayana JTA StarterPom
spring-boot-starter-mailStarter for using Java Mail and Spring Framework’s email sending supportPom
spring-boot-starter-mustacheStarter for building web applications using Mustache viewsPom
spring-boot-starter-quartzSpring Boot Quartz StarterPom
spring-boot-starter-securityStarter for using Spring SecurityPom
spring-boot-starter-testStarter for testing Spring Boot applications with libraries including JUnit, Hamcrest and MockitoPom
spring-boot-starter-thymeleafStarter for building MVC web applications using Thymeleaf viewsPom
spring-boot-starter-validationStarter for using Java Bean Validation with Hibernate ValidatorPom
spring-boot-starter-webStarter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded containerPom
spring-boot-starter-web-servicesStarter for using Spring Web ServicesPom
spring-boot-starter-webfluxStarter for building WebFlux applications using Spring Framework’s Reactive Web supportPom
spring-boot-starter-websocketStarter for building WebSocket applications using Spring Framework’s WebSocket supportPom

In addition to the application starters, the following starters can be used to add production ready features:

Table 13.2. Spring Boot production starters
NameDescriptionPom
spring-boot-starter-actuatorStarter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your applicationPom

Finally, Spring Boot also includes the following starters that can be used if you want to exclude or swap specific technical facets:

Table 13.3. Spring Boot technical starters
NameDescriptionPom
spring-boot-starter-jettyStarter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcatPom
spring-boot-starter-log4j2Starter for using Log4j2 for logging. An alternative to spring-boot-starter-loggingPom
spring-boot-starter-loggingStarter for logging using Logback. Default logging starterPom
spring-boot-starter-reactor-nettyStarter for using Reactor Netty as the embedded reactive HTTP server.Pom
spring-boot-starter-tomcatStarter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-webPom
spring-boot-starter-undertowStarter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcatPom

Spring Boot vs Spring MVC vs Spring - How do they compare?


What’s the problem Spring Framework solves?
Most important feature of Spring Framework is Dependency Injection. At the core of all Spring Modules is Dependency Injection or IOC Inversion of Control.
Why is this important? Because, when DI or IOC is used properly, we can develop loosely coupled applications. And loosely coupled applications can be easily unit tested.
Let’s consider a simple example:

Example without Dependency Injection

Consider the example below: WelcomeController depends on WelcomeService to get the welcome message. What is it doing to get an instance of WelcomeService? WelcomeService service = new WelcomeService();. It’s creating an instance of it. And that means they are tightly coupled. For example : If I create an mock for WelcomeService in a unit test for WelcomeController, How do I make WelcomeController use the mock? Not easy!
@RestController
public class WelcomeController {

    private WelcomeService service = new WelcomeService();

 @RequestMapping("/welcome")
 public String welcome() {
  return service.retrieveWelcomeMessage();
 }
}

Same Example with Dependency Injection

World looks much easier with dependency injection. You let the spring framework do the hard work. We just use two simple annotations: @Component and @Autowired.
  • Using @Component, we tell Spring Framework - Hey there, this is a bean that you need to manage.
  • Using @Autowired, we tell Spring Framework - Hey find the correct match for this specific type and autowire it in.
In the example below, Spring framework would create a bean for WelcomeService and autowire it into WelcomeController.
In a unit test, I can ask the Spring framework to auto-wire the mock of WelcomeService into WelcomeController. (Spring Boot makes things easy to do this with @MockBean. But, that’s a different story altogether!)

@Component
public class WelcomeService {
    //Bla Bla Bla
}

@RestController
public class WelcomeController {

    @Autowired
    private WelcomeService service;

 @RequestMapping("/welcome")
 public String welcome() {
  return service.retrieveWelcomeMessage();
 }
}

What else does Spring Framework solve?

It builds on the core concept of Dependeny Injection with a number of Spring Modules
  • Spring JDBC
  • Spring MVC
  • Spring AOP
  • Spring ORM
  • Spring JMS
  • Spring Test
For example, you need much less code to use a JDBCTemplate or a JMSTemplate compared to traditional JDBC or JMS.

Problem 2 : Good Integration with Other Frameworks.

Great thing about Spring Framework is that it does not try to solve problems which are already solved. All that it does is to provide a great integration with frameworks which provide great solutions.
  • Hibernate for ORM
  • iBatis for Object Mapping
  • JUnit & Mockito for Unit Testing

What is the core problem that Spring MVC Framework solves?

Spring MVC Framework provides decoupled way of developing web applications. With simple concepts like Dispatcher Servlet, ModelAndView and View Resolver, it makes it easy to develop web applications.

Why do we need Spring Boot?

Spring based applications have a lot of configuration.
When we use Spring MVC, we need to configure component scan, dispatcher servlet, a view resolver, web jars(for delivering static content) among other things.
  <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/views/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
  </bean>
  
  <mvc:resources mapping="/webjars/**" location="/webjars/"/>
    
Below code snippet shows typical configuration of a dispatcher servlet in a web application.
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/todo-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
When we use Hibernate/JPA, we would need to configure a datasource, an entity manager factory, a transaction manager among a host of other things.
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${db.driver}" />
        <property name="jdbcUrl" value="${db.url}" />
        <property name="user" value="${db.username}" />
        <property name="password" value="${db.password}" />
    </bean>

    <jdbc:initialize-database data-source="dataSource">
        <jdbc:script location="classpath:config/schema.sql" />
        <jdbc:script location="classpath:config/data.sql" />
    </jdbc:initialize-database>

    <bean
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="persistenceUnitName" value="hsql_pu" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

Problem #1 : Spring Boot Auto Configuration : 

Spring Boot brings in new thought process around this.
It starts with Starter. Once you include Starter in your class path it will auto configure all the jars that you need.

Problem #2 : Spring Boot Starter Projects : Built around well known patterns

Let’s say we want to develop a web application.
First of all we would need to identify the frameworks we want to use, which versions of frameworks to use and how to connect them together.
All web application have similar needs. Listed below are some of the dependencies we use in our Spring MVC Course. These include Spring MVC, Jackson Databind (for data binding), Hibernate-Validator (for server side validation using Java Validation API) and Log4j (for logging). When creating this course, we had to choose the compatible versions of all these frameworks.
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.2.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.0.2.Final</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
    
Here’s what the Spring Boot documentations says about starters.
Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop-shop for all the Spring and related technology that you need, without having to hunt through sample code and copy paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, just include the spring-boot-starter-data-jpa dependency in your project, and you are good to go.
Let’s consider an example starter - Spring Boot Starter Web.
If you want to develop a web application or an application to expose restful services, Spring Boot Start Web is the starter to pick. Lets create a quick project with Spring Boot Starter Web using Spring Initializr.

Dependency for Spring Boot Starter Web

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Dependencies can be classified into:
  • Spring - core, beans, context, aop
  • Web MVC - (Spring MVC)
  • Jackson - for JSON Binding
  • Validation - Hibernate Validator, Validation API
  • Embedded Servlet Container - Tomcat
  • Logging - logback, slf4j
Any typical web application would use all these dependencies. Spring Boot Starter Web comes pre packaged with these. As a developer, I would not need to worry about either these dependencies or their compatible versions.
What else in Starter??

Spring Boot Starter Project Options

As we see from Spring Boot Starter Web, starter projects help us in quickly getting started with developing specific types of applications.
  • spring-boot-starter-web-services - SOAP Web Services
  • spring-boot-starter-web - Web & RESTful applications
  • spring-boot-starter-test - Unit testing and Integration Testing
  • spring-boot-starter-jdbc - Traditional JDBC
  • spring-boot-starter-hateoas - Add HATEOAS features to your services
  • spring-boot-starter-security - Authentication and Authorization using Spring Security
  • spring-boot-starter-data-jpa - Spring Data JPA with Hibernate
  • spring-boot-starter-cache - Enabling Spring Framework’s caching support
  • spring-boot-starter-data-rest - Expose Simple REST Services using Spring Data REST

Other Goals of Spring Boot

There are a few starters for technical stuff as well
  • spring-boot-starter-actuator - To use advanced features like monitoring & tracing to your application out of the box
  • spring-boot-starter-undertow, spring-boot-starter-jetty, spring-boot-starter-tomcat - To pick your specific choice of Embedded Servlet Container
  • spring-boot-starter-logging - For Logging using logback
  • spring-boot-starter-log4j2 - Logging using Log4j2
Spring Boot aims to enable production ready applications in quick time.
  • Actuator : Enables Advanced Monitoring and Tracing of applications.
  • Embedded Server Integrations - Since server is integrated into the application, I would NOT need to have a separate application server installed on the server.
  • Default Error Handling

Spring Boot vs Spring

Spring

  • Spring is just a dependency injection framework. Spring focuses on the "plumbing" of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.
  • First half of the 2000 decade! EJBs
  • EJBs were NOT easy to develop.
  • Write a lot of xml and plumbing code to get EJBs running
  • Impossible to Unit Test
  • Alternative - Writing simple JDBC Code involved a lot of plumbing
  • Spring framework started with aim of making Java EE development simpler.
  • Goals
  • Make applications testable. i.e. easier to write unit tests
  • Reduce plumbing code of JDBC and JMS
  • Simple architecture. Minus EJB.
  • Integrates well with other popular frameworks.

Applications with Spring Framework

  • Over the next few years, a number of applications were developed with Spring Framework
  • Testable but
  • Lot of configuration (XML and Java)
  • Developing Spring Based application need configuration of a lot of beans!
  • Integration with other frameworks need configuration as well!
  • In the last few years, focus is moving from monolith applications to microservices. We need to be able to start project quickly. Minimum or Zero start up time
  • Framework Setup
  • Deployment - Configurability
  • Logging, Transaction Management
  • Monitoring
  • Web Server Configuration

Spring Boot

  • Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
  • We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss.
  • Example Problem Statements
  • You want to add Hibernate to your project. You dont worry about configuring a data source and a session factory. I will do if for you!
  • Goals
    • Provide quick start for projects with Spring.
    • Be opinionated but provide options.
    • Provide a range of non-functional features that are common to large classes of projects (e.g. embedded servers, security, metrics, health checks, externalized configuration).

What Spring Boot is NOT?

  • It’s not an app or a web server
  • Does not implement any specific framework - for example, JPA or JMS
  • Does not generate code

Creating a REST Service with Spring Boot


What is REST?

REST stands for REpresentational State Transfer. REST specifies a set of architectural constraints. Any service which satisfies these constraints is called RESTful Service.
The five important constraints for RESTful Web Service are
  • Client - Server : There should be a service producer and a service consumer.
  • The interface (URL) is uniform and exposing resources.
  • The service is stateless.
  • The service results should be Cacheable. HTTP cache, for example.
  • Service should assume a Layered architecture. Client should not assume direct connection to server - it might be getting info from a middle layer - cache.

Using appropriate Request Methods

Always use HTTP Methods. Best practices with respect to each HTTP method is described below:
  • GET : Should not update anything. Should be idempotent (same result in multiple calls). Possible Return Codes 200 (OK) + 404 (NOT FOUND) +400 (BAD REQUEST)
  • POST : Should create new resource. Ideally return JSON with link to newly created resource. Same return codes as get possible. In addition : Return code 201 (CREATED) is possible.
  • PUT : Update a known resource. ex: update client details. Possible Return Codes : 200(OK)
  • DELETE : Used to delete a resource.

Bootstrapping REST Services with Spring Initializr

Creating a REST service with Spring Initializr is a cake walk. We will use Spring Web MVC as our web framework.
Spring Initializr http://start.spring.io/ is great tool to bootstrap your Spring Boot projects.
  • Launch Spring Initializr and choose the following
    • Choose com.in28minutes.springboot as Group
    • Choose student-services as Artifact
    • Choose following dependencies
      • Web
      • Actuator
      • DevTools
  • Click Generate Project.
  • Import the project into Eclipse. File -> Import -> Existing Maven Project.
  • If you want to understand all the files that are part of this project, you can go here.
Now: Create Course Class.
package com.in28minutes.springboot.model;

import java.util.List;

public class Course {
 private String id;
 private String name;
 private String description;
 private List<String> steps;

 // Needed by Caused by: com.fasterxml.jackson.databind.JsonMappingException:
 // Can not construct instance of com.in28minutes.springboot.model.Course:
 // no suitable constructor found, can not deserialize from Object value
 // (missing default constructor or creator, or perhaps need to add/enable
 // type information?)
 public Course() {

 }

 public Course(String id, String name, String description, List<String> steps) {
  super();
  this.id = id;
  this.name = name;
  this.description = description;
  this.steps = steps;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getDescription() {
  return description;
 }

 public String getName() {
  return name;
 }

 public List<String> getSteps() {
  return steps;
 }

 @Override
 public String toString() {
  return String.format(
    "Course [id=%s, name=%s, description=%s, steps=%s]", id, name,
    description, steps);
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((id == null) ? 0 : id.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Course other = (Course) obj;
  if (id == null) {
   if (other.id != null)
    return false;
  } else if (!id.equals(other.id))
   return false;
  return true;
 }

}
Create Student Class:
package com.in28minutes.springboot.model;

import java.util.List;

public class Student {
 private String id;
 private String name;
 private String description;
 private List<Course> courses;

 public Student(String id, String name, String description,
   List<Course> courses) {
  super();
  this.id = id;
  this.name = name;
  this.description = description;
  this.courses = courses;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public List<Course> getCourses() {
  return courses;
 }

 public void setCourses(List<Course> courses) {
  this.courses = courses;
 }

 @Override
 public String toString() {
  return String.format(
    "Student [id=%s, name=%s, description=%s, courses=%s]", id,
    name, description, courses);
 }
}
Create StudentService Class:
package com.in28minutes.springboot.service;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Component;

import com.in28minutes.springboot.model.Course;
import com.in28minutes.springboot.model.Student;

@Component
public class StudentService {

 private static List<Student> students = new ArrayList<>();

 static {
  //Initialize Data
  Course course1 = new Course("Course1", "Spring", "10 Steps", Arrays
    .asList("Learn Maven", "Import Project", "First Example",
      "Second Example"));
  Course course2 = new Course("Course2", "Spring MVC", "10 Examples",
    Arrays.asList("Learn Maven", "Import Project", "First Example",
      "Second Example"));
  Course course3 = new Course("Course3", "Spring Boot", "6K Students",
    Arrays.asList("Learn Maven", "Learn Spring",
      "Learn Spring MVC", "First Example", "Second Example"));
  Course course4 = new Course("Course4", "Maven",
    "Most popular maven course on internet!", Arrays.asList(
      "Pom.xml", "Build Life Cycle", "Parent POM",
      "Importing into Eclipse"));

  Student ranga = new Student("Student1", "Ranga Karanam",
    "Hiker, Programmer and Architect", new ArrayList<>(Arrays
      .asList(course1, course2, course3, course4)));

  Student satish = new Student("Student2", "Satish T",
    "Hiker, Programmer and Architect", new ArrayList<>(Arrays
      .asList(course1, course2, course3, course4)));

  students.add(ranga);
  students.add(satish);
 }

 public List<Student> retrieveAllStudents() {
  return students;
 }

 public Student retrieveStudent(String studentId) {
  for (Student student : students) {
   if (student.getId().equals(studentId)) {
    return student;
   }
  }
  return null;
 }

 public List<Course> retrieveCourses(String studentId) {
  Student student = retrieveStudent(studentId);

  if (student == null) {
   return null;
  }

  return student.getCourses();
 }

 public Course retrieveCourse(String studentId, String courseId) {
  Student student = retrieveStudent(studentId);

  if (student == null) {
   return null;
  }

  for (Course course : student.getCourses()) {
   if (course.getId().equals(courseId)) {
    return course;
   }
  }

  return null;
 }

 private SecureRandom random = new SecureRandom();

 public Course addCourse(String studentId, Course course) {
  Student student = retrieveStudent(studentId);

  if (student == null) {
   return null;
  }

  String randomId = new BigInteger(130, random).toString(32);
  course.setId(randomId);

  student.getCourses().add(course);

  return course;
 }
}
package com.in28minutes.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StudentServicesApplication {

 public static void main(String[] args) {
  SpringApplication.run(StudentServicesApplication.class, args);
 }
}
Now Create Controller:
package com.in28minutes.springboot.controller;

import java.net.URI;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.in28minutes.springboot.model.Course;
import com.in28minutes.springboot.service.StudentService;

@RestController
public class StudentController {

 @Autowired
 private StudentService studentService;

 @GetMapping("/students/{studentId}/courses")
 public List<Course> retrieveCoursesForStudent(@PathVariable String studentId) {
  return studentService.retrieveCourses(studentId);
 }
 
 @GetMapping("/students/{studentId}/courses/{courseId}")
 public Course retrieveDetailsForCourse(@PathVariable String studentId,
   @PathVariable String courseId) {
  return studentService.retrieveCourse(studentId, courseId);
 }
 
 @PostMapping("/students/{studentId}/courses")
 public ResponseEntity<Void> registerStudentForCourse(
   @PathVariable String studentId, @RequestBody Course newCourse) {

  Course course = studentService.addCourse(studentId, newCourse);

  if (course == null)
   return ResponseEntity.noContent().build();

  URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(
    "/{id}").buildAndExpand(course.getId()).toUri();

  return ResponseEntity.created(location).build();
 }

}
Now run your application as java application. you are done.


Comments

Popular posts from this blog

Jersey JAX RS Jar

Tomcat Installation Steps for Windows & add tomcat to eclipse

REST API