SB Notes
SB Notes
================================================================
Creating Project
Spring Initializr
Download & Install STS IDE
Spring Boot Example
Spring Boot CLI
SB Example-STS
================================================================
Project Components
SB Annotations
SB Dependency Management
SB Application Properties
SB Starters
SB Starter Parent
SB Starter Web
SB Starter Data JPA
SB Starter Actuator
SB Starter Test
SB DevToolsMulti Module Project
SB Packaging
SB Auto-configuration
================================================================
Tool Suite
Hello World Example
Project Deployment Using Tomcat
================================================================
Spring Boot AOP
Spring Boot AOP
AOP Before Advice
AOP After Advice
AOP Around Advice
After Returning Advice
After Throwing Advice
================================================================
Spring Boot Database
Spring Boot JPA
Spring Boot JDBC
SB JDBC Example
SB H2 Database
SB CRUD Operations
================================================================
Spring Boot View
SB Thymeleaf View
================================================================
SB Caching
Spring Boot Caching
SB Cache Provider
Spring Boot EhCaching
================================================================
Spring Boot Misc
-------------------------------------------------------------------------------------------------------------------------------
Run SB Application
SB Change Port
SB REST Example
================================================================
Spring Boot - RESTful
-------------------------------------------------------------------------------------------------------------------------------
-
Introduction to RESTful Web Services With Spring Boot
Initializing a RESTful Web Services
Spring Boot Auto Configuration and Dispatcher Servlet
Enhancing the Hello World Service with a Path Variable
Implementing the POST Method to create User Resource
Implementing Exception Handling- 404 Resource Not Found
Implementing Generic Exception Handling for all Resources
Implementing DELETE Method to Delete a User Resource
Implementing Validations for RESTful Services
Implementing HATEOAS for RESTful Services
Internationalization of RESTful Services
Content Negotiation Implementing Support for XML
Configuring Auto Generation of Swagger Documentation
Introduction to Swagger Documentation Format
Enhancing Swagger Documentation with Custom Annotations
Monitoring APIs with Spring Boot Actuator
Implementing Static Filtering for RESTful Services
Implementing Dynamic Filtering for RESTful Services
Versioning RESTful Web Services-Basic Approach With URIs
Implementing Basic Authentication with Spring Security
Connecting RESTful Services to JPA
Updating GET Methods on User Resource to Use JPA
Updating POST and DELETE methods on UserResource to use JPA
Creating Post Entity and Many to One Relationship with User Entity
Implementing a GET service to retrieve all Posts of a User
Implementing POST Service to Create a Post for a User
Richardson Maturity ModelRESTful Web
================================================================
===============================================================
Dependency Injection
IOC container
Dependency Injection
Constructor Injection
setter injection
Autowiring
Factory method
===============================================================
Spring MVC
MVC Introduction
Multiple View Page
Multiple Controller
Model Interface
RequestParam Annotation
===============================================================
MVC Applications
MVC CRUD Example
MVC Pagination Example
File Upload Example
===============================================================
Spring MVC Validation
Spring MVC ValidationRegular Expression ValidationNumber ValidationCustom Validation
===============================================================
Spring boot
CRUD Example
File Upload Example
Login & Logout Example
Search Field Example
1) in hotel management project how you implement user registration using java spring boot
spring security hibernate jpa
2) in hotel management project how you implement user login using java spring boot spring
security hibernate jpa react
)Search & Booking Search hotels based on location, dates, and preferences -
View hotel details and room availability - Book rooms and manage bookings
5) Admin Panel - Manage users, hotels, bookings, and other administrative tasks
7)OTP User Validation- Developed OTP validation in Spring Boot using third party API services
8) Booking Confirmation - Generated booking confirmation tickets in PDF format
using iTextPDF library
12)User Reviews and Ratings - Developed module for users to leave reviews and
ratings for hotels
14) API Testing and Documentation- Thoroughly tested APIs using Postman -
Prepared comprehensive API documentation for frontend integration
1 )Spring Boot is a project that is built on the top of the Spring Framework. It provides an easier
and faster way to set up, configure, and run both simple and web-based applications.
2)It is a Spring module that provides the RAD (Rapid Application Development) feature to the
Spring Framework. It is used to create a stand-alone Spring-based application that you can just
run because it needs minimal Spring configuration.
3)In short, Spring Boot is the combination of Spring Framework and Embedded Servers.
4)In Spring Boot, there is no requirement for XML configuration (deployment descriptor). It uses
convention over configuration software design paradigm that means it decreases the effort of
the developer.
We can use Spring STS IDE or Spring Initializr to develop Spring Boot Java applications.
*********************************************************************************
Why should we use Spring Boot Framework?
*********************************************************************************
We should use Spring Boot Framework because:
1)The dependency injection approach is used in Spring Boot.
2)It contains powerful database transaction management capabilities.
3)It simplifies integration with other Java frameworks like JPA/Hibernate ORM, Struts, etc.
4)It reduces the cost and development time of the application.
*********************************************************************************
Along with the Spring Boot Framework, many other Spring sister projects help to build
applications addressing modern business needs. There are the following Spring sister projects
are as follows:
*********************************************************************************
Spring Data: It simplifies data access from the relational and NoSQL databases.
Spring Batch: It provides powerful batch processing.
Spring Security: It is a security framework that provides robust security to applications.
Spring Social: It supports integration with social networking like LinkedIn.
Spring Integration: It is an implementation of Enterprise Integration Patterns. It facilitates
integration with other enterprise applications using lightweight messaging and declarative
adapters.
********************************************************************************
4)It provides production-ready features such as metrics, health checks, and externalized
configuration.
6)It offers a CLI tool for developing and testing the Spring Boot application.
8)It also minimizes writing multiple boilerplate codes (the code that has to be included in many
places with little or no alteration), XML configuration, and annotations.
*******************************************************************************
Limitations of Spring Boot
*****************************************************************************
Spring Boot can use dependencies that are not going to be used in the application. These
dependencies increase the size of the application.
******************************************************************************
Goals of Spring Boot
****************************************************************************
1)The main goal of Spring Boot is to reduce development, unit test, and integration test time.
6)By providing or avoiding the above points, Spring Boot Framework reduces Development
time, Developer Effort, and increases productivity.
*******************************************************************************
Prerequisite of Spring Boot
******************************************************************************
To create a Spring Boot application, following are the prerequisites. In this tutorial, we will use
Spring Tool Suite (STS) IDE.
Java 1.8
Maven 3.0+
Spring Framework [Link]-SNAPSHOT
An IDE (Spring Tool Suite) 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
================================================================
Spring Boot Version
================================================================
Supports Java 8 or above versions
Supports Apache Tomcat 8 or above versions
Supports Thymeleaf 3
Supports Hibernate 5.2
The latest version of Spring Boot is 2.2.1. This release of Spring Boot includes 110 fixes,
dependency upgrades, and improvements.
In the Spring Boot v2.2.1, the annotation @ConfigurationProperties scanning is now disabled by
default. We need to be explicitly opted into by adding the @ConfigurationPropertiesScan
annotation.
New Features
Support constructor binding for property nested inside a JavaBean
Add config property for [Link] in WebFlux
Make test slices' type exclude filters public
Support amqps:// URIs in [Link]
Dependency upgrades
Some dependencies have been upgraded in Spring Boot v2.2.1 are as follows:
Mongodb 3.11.2
Spring Security [Link]
Slf4j 1.7.29
Spring Hateoas [Link]
Hibernate Validator [Link]
Hibernate [Link]
Jetty 9.4.22.v20191022
Spring Framework 5.2.1
Spring AMQP 2.2.1
H2 1.4.200
Spring Security 5.2
Spring Batch 4.2
Some important and widely used third-party dependencies are upgraded in this release are as
follows:
Micrometer 1.3.1
Flyway 6.0.7
Elasticsearch 6.8.4
JUnit 5.5
Jackson 2.10
Performance Improvements
In Spring Boot 2.2.1 the following performance has been improved:
Lazy Initialization
================================================================
Spring vs Spring Boot vs Spring MVC
================================================================
Spring:
------------------------------------------------------------------------------------------------------------
Spring Framework is the most popular application development framework of Java. The main
feature of the Spring Framework is dependency Injection or Inversion of Control (IoC). With the
help of Spring Framework, we can develop a loosely coupled application. It is better to use if
application type or characteristics are purely defined.
The developer writes a lot of code (boilerplate code) to do the minimal task.
It aims to shorten the code length and provide the easiest way to develop Web Applications.
The primary feature of Spring Boot is Autoconfiguration. It automatically configures the classes
based on the requirement.
Spring Boot offers embedded server such as Jetty and Tomcat, etc.
It offers several plugins for working with an embedded and in-memory database such as H2.
Spring Boot comes with the concept of starter in [Link] file that internally takes care of
downloading the dependencies JARs based on Spring Boot Requirement.
spring MVC
-----------------------------------------------------------------
Spring MVC is a model view controller-based web framework under the Spring framework.
================================================================
Spring Boot Architecture
===============================================================
Spring Boot follows a layered architecture in which each layer communicates with the layer
directly below or above (hierarchical structure) it.
Before understanding the Spring Boot Architecture, we must know the different layers and
classes present in it. There are four layers in Spring Boot are as follows:
1)Presentation Layer: The presentation layer handles the HTTP requests, translates the JSON
parameter to object, and authenticates the request and transfer it to the business layer. In short,
it consists of views i.e., frontend part.
2)Business Layer: The business layer handles all the business logic. It consists of service
classes and uses services provided by data access layers. It also performs authorization and
validation.
3)Persistence Layer: The persistence layer contains all the storage logic and translates
business objects from and to database rows.
4)Database Layer: In the database layer, CRUD (create, retrieve, update, delete) operations are
performed.
================================================================
Creating Project
Spring Initializr
================================================================
Spring Initializr is a web-based tool provided by the Pivotal Web Service. With the help of Spring
Initializr, we can easily generate the structure of the Spring Boot Project. It offers extensible API
for creating JVM-based projects.
initializr-bom: In this module, BOM stands for Bill Of Materials. In Spring Boot, BOM is a special
kind of POM that is used to control the versions of a project's dependencies. It provides a
central place to define and update those versions. It provides flexibility to add a dependency in
our module without worrying about the versions.
Outside the software world, the BOM is a list of parts, items, assemblies, and other materials
required to create products. It explains what, how, and where to collect required materials.
initializr-generator-spring:
initializr-generator-test: It provides a test infrastructure for project generation.
initializr-metadata: It provides metadata infrastructure for various aspects of the projects.
initializr-service-example: It provides custom instances.
initializr-version-resolver: It is an optional module to extract version numbers from an arbitrary
POM.
initializr-web: It provides web endpoints for third party clients.
----------------------------------------------------------------------------------------------------------------------
Supported Interface
--------------------------------------------------------------------------------------------------------------------------
It supports IDE STS, IntelliJ IDEA Ultimate, NetBeans, Eclipse. You can download the plugin
from [Link] If you are using VSCode, download the
plugin from [Link]
Use Custom Web UI [Link] or [Link]
It also supports the command-line with the Spring Boot CLI or cURL or HTTPie.
The following image shows the Spring Initializr UI:
------------------------------------------------------------------------------------------------------------------------------
Spring Initializer
-------------------------------------------------------------------------------------------------------------------------------
Generating a Project
-------------------------------------------------------------------------------------------------------------------------------
-
Before creating a project, we must be friendly with UI. Spring Initializr UI has the following
labels:
Project: It defines the kind of project. We can create either Maven Project or Gradle Project. We
will create a Maven Project throughout the tutorial.
Language: Spring Initializr provides the choice among three languages Java, Kotlin, and
Groovy. Java is by default selected.
Spring Boot: We can select the Spring Boot version. The latest version is 2.2.2.
Project Metadata: It contains information related to the project, such as Group, Artifact, etc.
Group denotes the package name; Artifact denotes the Application name. The default Group
name is [Link], and the default Artifact name is demo.
Dependencies: Dependencies are the collection of artifacts that we can add to our project.
There is another Options section that contains the following fields:
Step 2: Provide the Group and Artifact name. We have provided Group name [Link]
and Artifact spring-boot-example.
It takes some time to import the project. When the project imports successfully, we can see the
project directory in the Package Explorer. The following image shows the project directory:
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
[Link]
================================================================
Spring Boot CLI
================================================================
SB Example-STS
================================================================
Project Components
SB Annotations
-------------------------------------------------------------------------------------------------------------------------------
--
Spring Boot Annotations is a form of metadata that provides data about a program. In other
words, annotations are used to provide supplemental information about a program.
Example
@Component
public class Customer
{
private Person person;
@Autowired
public Customer(Person person)
{
[Link]=person;
}
}
---------------------------------------------------------------------------------------------------------------------------
@Configuration: It is a class-level annotation. The class annotated with @Configuration used by
Spring Containers as a source of bean definitions.
Example
@Configuration
public class Vehicle
{
@BeanVehicle engine()
{
return new Vehicle();
}
}
---------------------------------------------------------------------------------------------------------------------------
@ComponentScan: It is used when we want to scan a package for beans. It is used with the
annotation @Configuration. We can also specify the base packages to scan for Spring
Components.
Example
@ComponentScan(basePackages = "[Link]")
@Configuration
public class ScanComponent
{
// ...
}
---------------------------------------------------------------------------------------------------------------------------
@Bean: It is a method-level annotation. It is an alternative of XML <bean> tag. It tells the
method to produce a bean to be managed by Spring Container.
Example
@Bean
public BeanExample beanExample()
{
return new BeanExample ();
}
Spring Framework Stereotype Annotations
---------------------------------------------------------------------------------------------------------------------------
@Component: It is a class-level annotation. It is used to mark a Java class as a bean. A Java
class annotated with @Component is found during the classpath. The Spring Framework pick it
up and configure it in the application context as a Spring Bean.
Example
@Component
public class Student
{
.......
}
---------------------------------------------------------------------------------------------------------------------------
@Controller: The @Controller is a class-level annotation. It is a specialization of @Component.
It marks a class as a web request handler. It is often used to serve web pages. By default, it
returns a string that indicates which route to redirect. It is mostly used with @RequestMapping
annotation.
Example
@Controller
@RequestMapping("books")
public class BooksController
{
@RequestMapping(value = "/{name}", method = [Link])
public Employee getBooksByName()
{
return booksTemplate;
}
}
---------------------------------------------------------------------------------------------------------------------------
@Service: It is also used at class level. It tells the Spring that class contains the business logic.
Example
package [Link];
@Service
public class TestService
{
public void service1()
{
//business code
}
}
---------------------------------------------------------------------------------------------------------------------------
@Repository: It is a class-level annotation. The repository is a DAOs (Data Access Object) that
access the database directly. The repository does all the operations related to the database.
package [Link];
@Repository
public class TestRepository
{
public void delete()
{
//persistence code
}
}
Spring Boot Annotations
ADVERTISEMENT
---------------------------------------------------------------------------------------------------------------------------
@EnableAutoConfiguration: It auto-configures the bean that is present in the classpath and
configures it to run the methods. The use of this annotation is reduced in Spring Boot 1.2.0
release because developers provided an alternative of the annotation, i.e.
@SpringBootApplication.
@SpringBootApplication: It is a combination of three annotations @EnableAutoConfiguration,
@ComponentScan, and @Configuration.
---------------------------------------------------------------------------------------------------------------------------
Spring MVC and REST Annotations
---------------------------------------------------------------------------------------------------------------------------
@RequestMapping: It is used to map the web requests. It has many optional elements like
consumes, header, method, name, params, path, produces, and value. We use it with the class
as well as the method.
Example
@Controller
public class BooksController
{
@RequestMapping("/computer-science/books")
public String getAllBooks(Model model)
{
//application code
return "bookList";
}
---------------------------------------------------------------------------------------------------------------------------
@GetMapping: It maps the HTTP GET requests on the specific handler method. It is used to
create a web service endpoint that fetches It is used instead of using:
@RequestMapping(method = [Link])
---------------------------------------------------------------------------------------------------------------------------
@PostMapping: It maps the HTTP POST requests on the specific handler method. It is used to
create a web service endpoint that creates It is used instead of using:
@RequestMapping(method = [Link])
---------------------------------------------------------------------------------------------------------------------------
@PutMapping: It maps the HTTP PUT requests on the specific handler method. It is used to
create a web service endpoint that creates or updates It is used instead of using:
@RequestMapping(method = [Link])
---------------------------------------------------------------------------------------------------------------------------
@DeleteMapping: It maps the HTTP DELETE requests on the specific handler method. It is
used to create a web service endpoint that deletes a resource. It is used instead of using:
@RequestMapping(method = [Link])
---------------------------------------------------------------------------------------------------------------------------
@PatchMapping: It maps the HTTP PATCH requests on the specific handler method. It is used
instead of using: @RequestMapping(method = [Link])
---------------------------------------------------------------------------------------------------------------------------
@RequestBody: It is used to bind HTTP request with an object in a method parameter.
Internally it uses HTTP MessageConverters to convert the body of the request. When we
annotate a method parameter with @RequestBody, the Spring framework binds the incoming
HTTP request body to that parameter.
---------------------------------------------------------------------------------------------------------------------------
@ResponseBody: It binds the method return value to the response body. It tells the Spring Boot
Framework to serialize a return an object into JSON and XML format.
---------------------------------------------------------------------------------------------------------------------------
@PathVariable: It is used to extract the values from the URI. It is most suitable for the RESTful
web service, where the URL contains a path variable. We can define multiple @PathVariable in
a method.
---------------------------------------------------------------------------------------------------------------------------
@RequestParam: It is used to extract the query parameters form the URL. It is also known as a
query parameter. It is most suitable for web applications. It can specify default values if the
query parameter is not present in the URL.
---------------------------------------------------------------------------------------------------------------------------
@RequestHeader: It is used to get the details about the HTTP request headers. We use this
annotation as a method parameter. The optional elements of the annotation are name, required,
value, defaultValue. For each detail in the header, we should specify separate annotations. We
can use it multiple time in a method
---------------------------------------------------------------------------------------------------------------------------
@RestController: It can be considered as a combination of @Controller and @ResponseBody
annotations. The @RestController annotation is itself annotated with the @ResponseBody
annotation. It eliminates the need for annotating each method with @ResponseBody.
----------------------------------------------------------------------------------------------------------------------------
@RequestAttribute: It binds a method parameter to request attribute. It provides convenient
access to the request attributes from a controller method. With the help of @RequestAttribute
annotation, we can access objects that are populated on the server-side.
----------------------------------------------------------------------------------------------------------------------
SB Dependency Management
----------------------------------------------------------------------------------------------------------------------------
Spring Boot manages dependencies and configuration automatically. Each release of Spring
Boot provides a list of dependencies that it supports. The list of dependencies is available as a
part of the Bills of Materials (spring-boot-dependencies) that can be used with Maven. So, we
need not to specify the version of the dependencies in our configuration. Spring Boot manages
itself. Spring Boot upgrades all dependencies automatically in a consistent way when we update
the Spring Boot version.
It provides the centralization of dependency information by specifying the Spring Boot version in
one place. It helps when we switch from one version to another.
It avoids mismatch of different versions of Spring Boot libraries.
We only need to write a library name with specifying the version. It is helpful in multi-module
projects.
<parent>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>[Link]-SNAPSHOT</version> <!-- lookup parent from repository -->
<relativePath/>
</parent>
Note: In the above dependency, we have specified only the Spring Boot version. If we want to
add additional starters, simply remove the <version> tag. Similarly, we can also override the
individual dependency by overriding a property in our project.
For example, if we want to add another dependency with the same artifact that we have injected
already, inject that dependency again inside the <properties> tag to override the previous one.
<properties>
<[Link]>1.8</[Link]>
</properties>
Adding Spring Boot Maven Plugin
We can also add Maven plugin in our [Link] file. It wraps the project into an executable jar
file.
<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
============================================================
SB Application Properties
============================================================
Spring Boot Framework comes with a built-in mechanism for application configuration using a
file called [Link]. It is located inside the src/main/resources
Spring Boot provides various properties that can be configured in the [Link] file.
The properties have default values. We can set a property(s) for the Spring Boot application.
Spring Boot also allows us to define our own property if required.
Example of [Link]
#configuring application name
[Link] = demoApplication
#configuring port
[Link] = 8081
In the above example, we have configured the application name and port. The port 8081
denotes that the application runs on port 8081.
Spring Boot provides another file to configure the properties is called yml file. The Yaml file
works because the Snake YAML jar is present in the classpath. Instead of using the
[Link] file, we can also use the [Link] file, but the Yml file should be
present in the classpath.
Example of [Link]
spring:
application:
name: demoApplication
server:
port: 8081
In the above example, we have configured the application name and port. The port 8081
denotes that the application runs on port 8081.
Core Properties
Cache Properties
Mail Properties
JSON Properties
Data Properties
Transaction Properties
Data Migration Properties
Integration Properties
Web Properties
Templating Properties
Server Properties
Security Properties
RSocket Properties
Actuator Properties
DevTools Properties
Testing Properties
-------------------------------------------------------------------------------------------------------------------------------
--
SB Starters
===============================================================
Spring Boot provides a number of starters that allow us to add jars in the classpath. Spring Boot
built-in starters make development easier and rapid. Spring Boot Starters are the dependency
descriptors.
In the Spring Boot Framework, all the starters follow a similar naming pattern:
spring-boot-starter-*, where * denotes a particular type of application. For example, if we want to
use Spring and JPA for database access, we need to include the spring-boot-starter-data-jpa
dependency in our [Link] file of the project.
----------------------------------------------------------------------------------------------------
Third-Party Starters
-------------------------------------------------------------------------------------
We can also include third party starters in our project. But we do not use spring-boot-starter for
including third party dependency. The spring-boot-starter is reserved for official Spring Boot
artifacts. The third-party starter starts with the name of the project. For example, the third-party
project name is abc, then the dependency name will be abc-spring-boot-starter.
The Spring Boot Framework provides the following application starters under the
[Link] group.
6)spring-boot-starter-data-redis It is used for Redis key-value data store with Spring Data
Redis and the Jedis client.
12)spring-boot-starter-jdbc It is used for JDBC with the Tomcat JDBC connection pool.
spring-boot-starter-data-neo4j It is used for the Neo4j graph database and Spring Data
Neo4j.
SB Starter Parent
====================================================================
Spring Boot Starter Parent
The spring-boot-starter-parent is a project starter. It provides default configurations for our
applications. It is used internally by all dependencies. All Spring Boot projects use
spring-boot-starter-parent as a parent in [Link] file.
<parent>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>[Link]</version>
</parent>
Parent Poms allow us to manage the following things for multiple child projects and modules:
ADVERTISEMENT
Configuration: It allows us to maintain consistency of Java Version and other related properties.
Dependency Management: It controls the versions of dependencies to avoid conflict.
Source encoding
Default Java Version
Resource filtering
It also controls the default plugin configuration.
The spring-boot-starter-parent inherits dependency management from
spring-boot-dependencies. We only need to specify the Spring Boot version number. If there is a
requirement of the additional starter, we can safely omit the version number.
<properties>
<[Link]>1.8</[Link]>
<[Link]>@</[Link]>
<[Link]>UTF-8</[Link]>
<[Link]>UTF-8</[Link]>
<[Link]>${[Link]}</[Link]>
<[Link]>${[Link]}</[Link]>
</properties>
The properties section defines the application default values. The default Java version is 1.8.
We can also override Java version by specifying a property <[Link]>1.8</[Link]> in
the project pom. The parent pom also contains the few other settings related to encoding and
source. The Spring Boot framework uses these defaults in case, if we have not defined in the
[Link] file.
Plugin Management
The spring-boot-starter-parent specifies the default configuration for a host of plugins including
maven-failsafe-plugin, maven-jar-plugin and maven-surefire-plugin.
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>${start-class}</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>[Link]</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*[Link]</include>
<include>**/*[Link]</include>
</includes>
<excludes>
<exclude>**/Abstract*.java</exclude>
</excludes>
</configuration>
</plugin>
Spring Boot Dependencies
<properties>
<[Link]>5.13.4</[Link]>
...
<[Link]>[Link].21</[Link]>
<[Link]>3.1.1</[Link]>
...
<[Link]>1.4.192</[Link]>
<[Link]>1.3</[Link]>
<[Link]>3.6.4</[Link]>
<[Link]>[Link]</[Link]>
<[Link]>[Link]</[Link]>
<[Link]>2.4.7</[Link]>
<[Link]>2.3.13</[Link]>
<[Link]>[Link]</[Link]>
<[Link]>2.3.3</[Link]>
<[Link]>2.21</[Link]>
<[Link]>4.1.2</[Link]>
<[Link]>4.5.2</[Link]>
<[Link]>4.4.5</[Link]>
<[Link]>[Link]</[Link]>
<[Link]>2.8.1</[Link]>
....
<[Link]>2.23.1</[Link]>
<[Link]>2.0.3</[Link]>
<[Link]>9.3.11.v20160721</[Link]>
<[Link]>2.2.0.v201112011158</[Link]>
<[Link]>[Link]</[Link]>
<[Link]>8.5.4</[Link]>
<[Link]>[Link]</[Link]>
<[Link]>1.7</[Link]>
<[Link]>2.0</[Link]>
<[Link]>9f96c74</[Link]>
<[Link]>0.32</[Link]>
<[Link]>1.6.3</[Link]>
<[Link]>1.4.01</[Link]>
</properties>
<prerequisites>
<maven>3.2.1</maven>
</prerequisites>
Spring Boot Starter without Parent
In some cases, we need not to inherit spring-boot-starter-parent in the [Link] file. To handle
such use cases, Spring Boot provides the flexibility to still use the dependency management
without inheriting the spring-boot-starter-parent.
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>[Link]</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>[Link]</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
In the above code, we can see that we have used <scope> tag for this. It is useful when we
want to use different version for a certain dependency.
=============================================================
SB Starter Web
==============================================================
There are two important features of spring-boot-starter-web:
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>[Link]</version>
</dependency>
Starter of Spring web uses Spring MVC, REST and Tomcat as a default embedded server. The
single spring-boot-starter-web dependency transitively pulls in all dependencies related to web
development. It also reduces the build dependency count. The spring-boot-starter-web
transitively depends on the following:
[Link]:spring-boot-starter
[Link]:spring-boot-starter-tomcat
[Link]:spring-boot-starter-validation
[Link]:jackson-databind
[Link]:spring-web
[Link]:spring-webmvc
By default, the spring-boot-starter-web contains the following tomcat server dependency
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>[Link]</version>
<scope>compile</scope>
</dependency>
The spring-boot-starter-web auto-configures the following things that are required for the web
development:
Dispatcher Servlet
Error Page
Web JARs for managing the static dependencies
Embedded servlet container
Spring Boot Embedded Web Server
Each Spring Boot application includes an embedded server. Embedded server is embedded as
a part of deployable application. The advantage of embedded server is, we do not require
pre-installed server in the environment. With Spring Boot, default embedded server is Tomcat.
Spring Boot also supports another two embedded servers:
Jetty Server
Undertow Server
Using another embedded web server
For servlet stack applications, the spring-boot-starter-web includes Tomcat by including
spring-boot-starter-tomcat, but we can use spring-boot-starter-jetty or
spring-boot-starter-undertow instead.
Jetty Server
The Spring Boot also supports an embedded server called Jetty Server. It is an HTTP server
and Servlet container that has the capability of serving static and dynamic content. It is used
when machine to machine communication is required.
If we want to add the Jetty server in the application, we need to add the spring-boot-starter-jetty
dependency in our [Link] file.
ADVERTISEMENT
Remember: While using Jetty server in the application, make sure that the default Tomcat server
is excluded from the spring-boot-starter-web. It avoids the conflict between servers.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
We can also customize the behavior of the Jetty server by using the [Link] file.
Undertow Server
Spring Boot provides another server called Undertow. It is also an embedded web server like
Jetty. It is written in Java and manage and sponsored by JBoss. The main advantages of
Undertow server are:
Supports HTTP/2
HTTP upgrade support
Websocket Support
Provides support for Servlet 4.0
Flexible
Embeddable
Remember: While using Undertow server in the application, make sure that the default Tomcat
server is excluded from the spring-boot-starter-web. It avoids the conflict between servers.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
We can also customize the behavior of the Undertow server by using the [Link]
file.
core
el
logging
websocket
The starter-tomcat has the following dependencies:
<dependency>
<groupId>[Link]</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.23</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>tomcat-embed-el</artifactId>
<version>8.5.23</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>8.5.23</version>
<scope>compile</scope>
</dependency>
We can also use spring-mvc without using the embedded Tomcat server. If we want to do so, we
need to exclude the Tomcat server by using the <exclusion> tag, as shown in the following
code.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
===========================================================
SB Starter Data JPA
=============================================================
Spring Data is a high-level Spring Source project. Its purpose is to unify and easy access to the
different kinds of persistence stores, both relational database systems, and NoSQL data stores.
When we implement a new application, we should focus on the business logic instead of
technical complexity and boilerplate code. That's why the Java Persistent API (JPA)
specification and Spring Data JPA are extremely popular.
Spring Data JPA adds a layer on the top of JPA. It means, Spring Data JPA uses all features
defined by JPA specification, especially the entity, association mappings, and JPA's query
capabilities. Spring Data JPA adds its own features such as the no-code implementation of the
repository pattern and the creation of database queries from the method name.
Spring internally generates a JPQL (Java Persistence Query Language) query based on the
method name. The query is derived from the method signature. It sets the bind parameter value,
execute the query, and returns the result.
CrudRepository: It offers standard create, read, update, and delete It contains method like
findOne(), findAll(), save(), delete(), etc.
PagingAndSortingRepository: It extends the CrudRepository and adds the findAll methods. It
allows us to sort and retrieve the data in a paginated way.
JpaRepository: It is a JPA specific repository It is defined in Spring Data Jpa. It extends the both
repository CrudRepository and PagingAndSortingRepository. It adds the JPA-specific methods,
like flush() to trigger a flush on the persistence context.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>[Link]</version>
</dependency>
Spring Boot Starter Data JPA
Spring Boot provides spring-boot-starter-data-jpa dependency to connect Spring application
with relational database efficiently. The spring-boot-starter-data-jpa internally uses the
spring-boot-jpa dependency (since Spring Boot version 1.5.3).
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>[Link]</version>
</dependency>
The databases are designed with tables/relations. Earlier approaches (JDBC) involved writing
SQL queries. In the JPA, we will store the data from objects into table and vice-versa. However,
JPA evolved as a result of a different thought process.
Before JPA, ORM was the term more commonly used to refer to these frameworks. It is the
reason Hibernate is called the ORM framework.
Entity Manager: Once we define the mapping, it handles all the interactions with the database.
JPQL (Java Persistence Query Language): It provides a way to write queries to execute
searches against entities. It is different from the SQL queries. JPQL queries already understand
the mapping that is defined between entities. We can add additional conditions if required.
Criteria API: It defines a Java-based API to execute searches against the database.
Hibernate vs. JPA
Hibernate is the implementation of JPA. It is the most popular ORM framework, while JPA is an
API that defines the specification. Hibernate understands the mapping that we add between
objects and tables. It ensures that data is retrieved/ stored from the database based on the
mapping. It also provides additional features on the top of the JPA.
Step 4: Add the dependencies: Spring Web, Spring Data JPA, and H2 Database.
ADVERTISEMENT
Step 5: Click on the Generate button. When we click on the Generate button, it wraps the
project in Jar file and downloads it to the local system.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-jpa-example -> Finish
Step 9: Create a Controller class with the name ControllerDemo in the package
[Link].
[Link]
package [Link];
import [Link];
import [Link];
@Controller
public class ControllerDemo
{
@RequestMapping("/")
public String home()
{
return "[Link]";
}
}
Step 10: Create another package with the name [Link] in the folder
src/main/java.
Step 11: Create a class with the name User in the package [Link].
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
@Entity
@Table(name="userdata")
public class User
{
@Id
private int id;
private String username;
public int getId()
{
return id;
}
public void setId(int id)
{
[Link] = id;
}
public String getUname()
{
return username;
}
public void setUname(String username)
{
[Link] = username;
}
@Override
public String toString()
{
return "User [id=" + id + ", uname=" + username + "]";
}
}
Now we need to Configure the H2 database.
Step 12: Open the [Link] file and configure the following things: port, enable the
H2 console, datasource, and URL.
[Link]
[Link]=8085
[Link]=true
[Link]=h2
[Link]=jdbc:h2:mem:javatpoint
Step 13: Create a SQL file in the folder src/main/resources.
Right-click on the folder src/main/resources -> New -> File -> Provide the File name -> Finish
We have provided the file name [Link] and insert the following data into it.
[Link]
Step 15: Create a JSP file with the name that we have returned in the ControllerDemo. In the
[Link], we have returned [Link].
[Link]
Step 18: Click on the Connect button. It shows the structure of the table userdata that we have
defined in the [Link].
Endpoints
Metrics
Audit
Endpoint: The actuator endpoints allows us to monitor and interact with the application. Spring
Boot provides a number of built-in endpoints. We can also create our own endpoint. We can
enable and disable each endpoint individually. Most of the application choose HTTP, where the
Id of the endpoint, along with the prefix of /actuator, is mapped to a URL.
For example, the /health endpoint provides the basic health information of an application. The
actuator, by default, mapped it to /actuator/health.
Metrics: Spring Boot Actuator provides dimensional metrics by integrating with the micrometer.
The micrometer is integrated into Spring Boot. It is the instrumentation library powering the
delivery of application metrics from Spring. It provides vendor-neutral interfaces for timers,
gauges, counters, distribution summaries, and long task timers with a dimensional data model.
Audit: Spring Boot provides a flexible audit framework that publishes events to an
AuditEventRepository. It automatically publishes the authentication events if spring-security is in
execution.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>[Link]</version>
</dependency>
Spring Boot Actuator Endpoints
The actuator endpoints allow us to monitor and interact with our Spring Boot application. Spring
Boot includes number of built-in endpoints and we can also add custom endpoints in Spring
Boot application.
Id Usage Default
actuator It provides a hypermedia-based discovery page for the other endpoints. It
requires Spring HATEOAS to be on the classpath. True
auditevents It exposes audit events information for the current application. True
autoconfig It is used to display an auto-configuration report showing all auto-configuration
candidates and the reason why they 'were' or 'were not' applied. True
beans It is used to display a complete list of all the Spring beans in your application. True
configprops It is used to display a collated list of all @ConfigurationProperties. True
dump It is used to perform a thread dump. True
env It is used to expose properties from Spring's ConfigurableEnvironment. True
flyway It is used to show any Flyway database migrations that have been applied. True
health It is used to show application health information. False
info It is used to display arbitrary application info. False
loggers It is used to show and modify the configuration of loggers in the application.
True
liquibase It is used to show any Liquibase database migrations that have been applied.
True
metricsIt is used to show metrics information for the current application. True
mappings It is used to display a collated list of all @RequestMapping paths. True
shutdown It is used to allow the application to be gracefully shutdown. True
trace It is used to display trace information. True
For Spring MVC, the following additional endpoints are used.
Id Description Default
docs It is used to display documentation, including example requests and responses for the
Actuator's endpoints. False
heapdump It is used to return a GZip compressed hprof heap dump file. True
jolokia It is used to expose JMX beans over HTTP (when Jolokia is on the classpath). True
logfile It is used to return the contents of the logfile. True
prometheus It is used to expose metrics in a format that can be scraped by a prometheus
server. It requires a dependency on micrometer-registry- prometheus. True
Spring Boot actuator properties
Spring Boot enables security for all actuator endpoints. It uses form-based authentication that
provides user Id as the user and a randomly generated password. We can also access
actuator-restricted endpoints by customizing basicauth security to the endpoints. We need to
override this configuration by [Link] property. For example:
[Link]=true
[Link]=ADMIN
[Link]=true
[Link]=admin
[Link]=admin
Spring Boot Actuator Example
Let's understand the concept of the actuator through an example.
Step 4: Add the following dependencies: Spring Web, Spring Boot Starter Actuator, and Spring
Data Rest HAL Browser.
Step 5: Click on the Generate button. When we click on the Generate button, it wraps all the
specifications related to the project into a Jar file and downloads it to our local system
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-actuator-example -> Finish
It takes some time to import. After importing the project, we can see the project directory in the
package explorer section.
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class DemoRestController
{
@GetMapping("/hello")
public String hello()
{
return "Hello User!";
}
}
Step 9: Open the [Link] file and disable the security feature of the actuator by
adding the following statement.
[Link]
[Link]=false
Step 10: Run the [Link] file.
Step 11: Open the browser and invoke the URL [Link] It returns the
following page:
{"_links":{"self":{"href":"[Link]
calhost:8080/actuator/health","templated":false},"health-path":{"href":"[Link]
tor/health/{*path}","templated":true},"info":{"href":"[Link]
false}}}
The application runs on port 8080 by default. Once the actuator has started, we can see the list
of all the endpoints exposed over HTTP.
There are several different types of tests that we can write to help test and automate the health
of an application. Before starting any testing, we need to integrate the testing framework.
With Spring Boot, we need to add starter to our project, for testing we only need to add the
spring-boot-starter-test dependency.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>[Link]</version>
<scope>test</scope>
</dependency>
It pulls all the dependencies related to test. After adding it, we can build up a simple unit test.
We can either create the Spring Boot project through IDE or generate it using Spring Initializr.
Note: If you are adding test dependency manually, add it to the bottom of the [Link] file.
In the above dependency, one thing to be noticed that it includes the scope of test
<scope>test</scope>. It means when the application is bundled and packaged for deployment,
any dependency that is declared with the test scopes is ignored. The test scope dependencies
are only available when running in the development and Maven test modes.
When we create a simple Spring Boot application, by default, it contains the test dependency in
the [Link] file and [Link] file under in the folder src/test/java.
Step 2: Provide the Group name and Artifact Id. We have provided Group name [Link]
and Artifact spring-boot-test-example.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-test-example -> Finish
After importing the project, we can see the following project directory in the Package Explorer
section of the STS.
[Link]
package [Link];
import [Link];
import [Link];
@SpringBootTest
class SpringBootTestExampleApplicationTests
{
@Test
void contextLoads()
{
}
}
The above code implements two annotation by default: @SpringBootTest, and @Test.
@SpringBootTest: It applies on a Test Class that runs Spring Boot based tests. It provides the
following features over and above the regular Spring TestContext Framework:
It uses SpringBootContextLoader as the default ContextLoader if no specific
@ContextConfiguration(loader=...) is defined.
It automatically searches for a @SpringBootConfiguration when nested @Configuartion is not
used, and no explicit classes are specified.
It provides support for different WebEnvironment modes.
It registers a TestRestTemplate or WebTestClient bean for use in web tests that are using the
webserver.
It allows application arguments to be defined using the args attribute.
Step 7: Open the [Link] file and run it as Junit Test.
================================================================
SB DevTools
================================================================
Spring Boot DevTools
Spring Boot 1.3 provides another module called Spring Boot DevTools. DevTools stands for
Developer Tool. The aim of the module is to try and improve the development time while
working with the Spring Boot application. Spring Boot DevTools pick up the changes and restart
the application.
We can implement the DevTools in our project by adding the following dependency in the
[Link] file.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime<scope >
</dependency>
Spring Boot DevTools Features
Spring Boot DevTools provides the following features:
Property Defaults
Automatic Restart
LiveReload
Remote Debug Tunneling
Remote Update and Restart
Property Defaults: Spring Boot provides templating technology Thymeleaf that contains the
property [Link]. It disables the caching and allows us to update pages without
the need of restarting the application. But setting up these properties during the development
always creates some problems.
ADVERTISEMENT
When we use the spring-boot-devtools module, we are not required to set properties. During the
development caching for Thymeleaf, Freemarker, Groovy Templates are automatically disabled.
The classes that do not change (third-Jars) are loaded in the base ClassLoader.
The classes that we are actively developing are loaded in the restart ClassLoader.
When the application restarts, the restart ClassLoader is thrown away, and a new one is
populated. Therefore, the base ClassLoader is always available and populated.
Remember:
The DevTools always monitors the classpath resources.
There is only a way to trigger a restart is to update the classpath.
DevTools required a separate application classloader to work properly. By default, Maven fork
the application process.
Auto-restart works well with LiveReload.
DevTools depends on the application context's shutdown hook to close it during the restart.
LiveReload: The Spring Boot DevTools module includes an embedded server called
LiveReload. It allows the application to automictically trigger a browser refresh whenever we
make changes in the resources. It is also known as auto-refresh.
It provides browser extensions for Chrome, Firefox, and Safari. By default, LiveReload is
enabled. The LiveReload works on the following path:
/META-INF/maven
/META-INF/resources
/resources
/static
/public
/templates
We can also disable auto-reload in browser by excluding the above paths. For example:
[Link]-paths=/path-to-folder
If we want to exclude additional path and want to keep defaults then use the property
[Link]-exclude. For example:
[Link]-exclude=styles/**
Remember
We can run one LiveReload server at a time.
Before starting the application, ensure that no other LiveReload server is running.
If we start multiple applications from IDE, it supports only the first LiveReload.
Remote Debug Tunneling: Spring Boot can tunnel JDWP (Java Debug Wire Protocol) over
HTTP directly to the application. It can even work application deployment to Internet Cloud
providers that only expose port 80 and 443.
Remote Update and Restart: There is another trick that DevTools offers is: it supports remote
application updates and restarts. It monitors local classpath for file changes and pushes them to
a remote server, which is then restarted. We can also use this feature in combination with
LiveReload.
We can implement the trigger file in our application by adding the property
[Link]-file. The file can be internal or external. For example:
[Link]-file=c:/[Link]/[Link]
Spring Boot DevTools Example
Step 1: Create a Maven project using Spring Initializr [Link]
Step 2: Provide the Group name and Artifact Id. We have provided Group name [Link]
and Artifact Id spring-boot-devtools-example.
Step 4: Click on the Generate button. It downloads the Jar file of the project.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-devtools-example -> Finish
When the project imports successfully, we can see the following directory in the Package
Explorer section of the STS.
Spring Boot DevTools
Step 7: Open the [Link] and run it as Java Application.
After that, make any changes (edit or remove some file or code) in the application, and save
that changes. As soon as we save the changes, the server restarts and pick up the changes.
← prevnext →
==============================================================
Multi Module Project
================================================================
SB Packaging
================================================================
Spring Boot Packaging
In the J2EE application, modules are packed as JAR, WAR, and EAR. It is the compressed file
formats that is used in the J2EE. J2EE defines three types of archives:
WAR
JAR
EAR
Spring Boot Packaging
WAR
WAR stands for Web Archive. WAR file represents the web application. Web module contains
servlet classes, JSP files, HTML files, JavaScripts, etc. are packaged as a JAR file with .war
extension. It contains a special directory called WEB-INF.
WAR is a module that loads into a web container of the Java Application Server. The Java
Application Server has two containers: Web Container and EJB Container.
The Web Container hosts the web applications based on Servlet API and JSP. The web
container requires the web module to be packaged as a WAR file. It is a WAR file special JAR
file that contains a [Link] file in the WEB-INF folder.
An EJB Container hosts Enterprise Java beans based on EJB API. It requires EJB modules to
be packaged as a JAR file. It contains an [Link] file in the META-INF folder.
The advantage of the WAR file is that it can be deployed easily on the client machine in a Web
server environment. To execute a WAR file, a Web server or Web container is required. For
example, Tomcat, Weblogic, and Websphere.
JAR
JAR stands for Java Archive. An EJB (Enterprise Java Beans) module that contains bean files
(class files), a manifest, and EJB deployment descriptor (XML file) are packaged as JAR files
with the extension .jar. It is used by software developers to distribute Java classes and various
metadata.
In other words, A file that encapsulates one or more Java classes, a manifest, and descriptor is
called JAR file. It is the lowest level of the archive. It is used in J2EE for packaging EJB and
client-side Java Applications. It makes the deployment easy.
EAR
EAR stands for Enterprise Archive. EAR file represents the enterprise application. The above
two files are packaged as a JAR file with the .ear extension. It is deployed into the Application
Server. It can contain multiple EJB modules (JAR) and Web modules (WAR). It is a special JAR
that contains an [Link] file in the META-INF folder.
================================================================
SB Auto-configuration
================================================================
Spring Boot auto-configuration automatically configures the Spring application based on the jar
dependencies that we have added.
For example, if the H2 database Jar is present in the classpath and we have not configured any
beans related to the database manually, the Spring Boot's auto-configuration feature
automatically configures it in the project.
@SpringBootApplication=@ComponentScan+@EnableAutoConfiguration+@Configuration
ADVERTISEMENT
Similarly, when we add the spring-boot-starter-data-jpa dependency, we see that Spring Boot
Auto-configuration, auto-configures a datasource and an Entity Manager.
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
[Link]
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/[Link]</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>
Similarly, when we use Hibernate/ JPA, we need to configure datasource, a transaction
manager, an entity manager factory among a host of other things.
Configuring datasource
ADVERTISEMENT
<bean
class="[Link]"
id="entityManagerFactory">
<property name="persistenceUnitName" value="hsql_pu" />
<property name="dataSource" ref="dataSource" />
</bean>
Configuring transaction manager
import [Link].*;
import [Link].*;
import [Link].*;
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(exclude={[Link]})
public class MyConfiguration
{
}
We can use the attribute excludeName of the annotation @EnableAutoConfiguration and
specify the qualified name of the class, if the class is not on the class path. We can exclude any
number of auto-configuration classes by using the property [Link].
Step 5: Click on the Generate button. When we click on the Generate button, it wraps the
project in Jar file and downloads it to the local system.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-autoconfiguration-example -> Finish
Step 8: Create a package with the name [Link] in the folder src/main/java.
Step 9: Create a Controller class with the name ControllerDemo in the package
[Link].
[Link]
package [Link];
import [Link];
import [Link];
@Controller
public class ControllerDemo
{
@RequestMapping("/")
public String home()
{
return "[Link]";
}
}
Step 10: Create another package with the name [Link] in the folder
src/main/java.
ADVERTISEMENT
ADVERTISEMENT
Step 11: Create a class with the name User in the package [Link].
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
@Entity
@Table(name="userdata")
public class User
{
@Id
private int id;
private String username;
public int getId()
{
return id;
}
public void setId(int id)
{
[Link] = id;
}
public String getUname()
{
return username;
}
public void setUname(String username)
{
[Link] = username;
}
@Override
public String toString()
{
return "User [id=" + id + ", uname=" + username + "]";
}
}
Now we need to Configure the H2 database.
Step 12: Open the [Link] file and configure the following things: port, enable the
H2 console, datasource, and URL.
[Link]
[Link]=8085
[Link]=true
[Link]=h2
[Link]=jdbc:h2:mem:javatpoint
Step 13: Create a SQL file in the folder src/main/resources.
Right-click on the folder src/main/resources -> New -> File -> Provide the File name -> Finish
ADVERTISEMENT
ADVERTISEMENT
We have provided the file name [Link] and insert the following data into it.
[Link]
Step 15: Create a JSP file with the name that we have returned in the ControllerDemo. In the
[Link], we have returned [Link].
[Link]
ADVERTISEMENT
Step 18: Click on the Connect button. It shows the structure of the table userdata that we have
defined in the [Link] file.
ADVERTISEMENT
We can debug logging by adding a property in the [Link] file. Let's implement
the debug logging in the above example. Open the [Link] file and add the
following property:
[Link]: DEBUG
Now restart the application. We see that an auto-configuration report printed in the log. The
report includes all the classes that are auto-configured. It is divided into two parts: positive
matches annegative matches, as shown in the following figure.
Positive matches
We can also debug auto-configuration by using Actuator in the project. We will also add in HAL
Browser to make things easy. It shows the details of all the beans that are auto-configured, and
those are not.
Step 4: Add the dependencies: Spring Web and Spring Boot Actuator.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Step 5: Click on the Generate button. It binds all the specification related to project into a jar file
and downloads it in our local system.
File -> Import -> Existing Maven Project -> Next -> Browse -> Select the Project folder -> Finish
After importing the project, we can see the following directory structure in the Package Explorer
section of the IDE.
In the Controller, we have defined a method named hello() that returns a string.
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class DemoRestController
{
@GetMapping("/hello")
public String hello()
{
return "Hello User, have a nice day.";
}
}
Step 9: Run the [Link] file.
Step 10: Open the browser and invoke the URL [Link] It returns a string
that we have specified in the controller.
{"_links":{"self":{"href":"[Link]
calhost:8080/actuator/health","templated":false},"health-path":{"href":"[Link]
tor/health/{*path}","templated":true},"info":{"href":"[Link]
false}}}
Step 11: Open the [Link] file and add the HAL Browser dependency.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
Step 12: Again, run the [Link] file.
To access the HAL browser, type [Link] in the browser and hit the enter key.
Type /actuator in the Explorer's text box and click on the Go button.
================================================================
Tool Suite
Hello World Example
================================================================
In the section, we will create a Maven project for Hello Word Example. We need the following
tools and technologies to develop the same.
ADVERTISEMENT
ADVERTISEMENT
Step 5: Click on the Generate button. When we click on the Generate button, it wraps all the
specifications into a jar file and downloads it to our local system.
File -> Import -> Existing Maven Project -> Next -> Browse -> Select the Project Folder -> Finish
When the project imports successfully, it shows the following project directory in the Package
Explorer section of the IDE.
ADVERTISEMENT
ADVERTISEMENT
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class HelloWorldController
{
@RequestMapping("/")
public String hello()
{
return "Hello javaTpoint";
}
}
Step 11: Run the [Link] file.
[Link]
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootHelloWorldExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
When the application runs successfully, it shows a massage in the console, as shown in the
following figure.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Step 5: Click on the Generate button. It wraps all the specification related to the project and
download the jar file in our local system.
ADVERTISEMENT
File -> Import -> Existing Maven Project -> Next -> Browse -> Select the Project Folder -> Finish
After importing the project, we can see the following directory structure in the Package Explorer
section of the IDE.
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class DemoRestController
{
@GetMapping("/hello")
public String hello()
{
return "Hello User, have a nice day.";
}
}
Step 9: Run the [Link] file as Java Application.
ADVERTISEMENT
ADVERTISEMENT
Step 10: Open the browser and invoke the URL [Link]
ADVERTISEMENT
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return [Link]([Link]);
}
ADVERTISEMENT
ADVERTISEMENT
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootWarDeploymentExampleApplication extends SpringBootServletInitializer
{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return [Link]([Link]);
}
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Step 13: Open the [Link] file and marked the servlet container (Tomcat) as provided.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
Step 14: We need to deploy WAR file so change the package type to WAR in [Link] file.
<packaging>war</packaging>
Step 15: Modify the final WAR file name by using the <finalName> tag to avoid including the
version numbers. We have created a WAR file with the name web-services.
<finalName>web-services</finalName>
[Link]
ADVERTISEMENT
ADVERTISEMENT
Step 17: Write clean install in the Goals label and check the Skip Tests. Click on the Apply and
Run button, respectively.
C:\Users\Anubhav\Documents\[Link]\spring-boot-war-deployment-exa
mple\target
Spring Boot Project Deployment Using Tomcat
Deploy the WAR file to Tomcat
To deploy the WAR file, follow the steps below:
ADVERTISEMENT
Step 19: Download and install the Apache Tomcat Server, if not installed.
Step 20: Copy the WAR file ([Link]) and paste it inside the webapps folder of the
Tomcat. In our case, the location of the webapps folder is:
================================================================
Spring Boot AOP
================================================================
ADVERTISEMENT
ADVERTISEMENT
Web Layer: It exposes the services using the REST or web application.
Business Layer: It implements the business logic of an application.
Data Layer: It implements the persistence logic of the application.
The responsibility of each layer is different, but there are a few common aspects that apply to all
layers are Logging, Security, validation, caching, etc. These common aspects are called
cross-cutting concerns.
If we implement these concerns in each layer separately, the code becomes more difficult to
maintain. To overcome this problem, Aspect-Oriented Programming (AOP) provides a solution
to implement cross-cutting concerns.
AOP
AOP (Aspect-Oriented Programming) is a programming pattern that increases modularity by
allowing the separation of the cross-cutting concern. These cross-cutting concerns are different
from the main business logic. We can add additional behavior to existing code without
modification of the code itself.
Using AOP, we define common functionality in one place. We are free to define how and where
this functionality is applied without modifying the class to which we are applying the new feature.
The cross-cutting concern can now be modularized into special classes, called aspect.
First, the logic for each concern is now in one place instead of scattered all over the codebase.
Second, the business modules only contain code for their primary concern. The secondary
concern has been moved to the aspect.
The aspects have the responsibility that is to be implemented, called advice. We can implement
an aspect's functionality into a program at one or more join points.
Benefits of AOP
It is implemented in pure Java.
There is no requirement for a special compilation process.
It supports only method execution Join points.
Only run time weaving is available.
Two types of AOP proxy is available: JDK dynamic proxy and CGLIB proxy.
Cross-cutting concern
The cross-cutting concern is a concern that we want to implement in multiple places in an
application. It affects the entire application.
AOP Terminology
Aspect: An aspect is a module that encapsulates advice and pointcuts and provides
cross-cutting An application can have any number of aspects. We can implement an aspect
using regular class annotated with @Aspect annotation.
Pointcut: A pointcut is an expression that selects one or more join points where advice is
executed. We can define pointcuts using expressions or patterns. It uses different kinds of
expressions that matched with the join points. In Spring Framework, AspectJ pointcut
expression language is used.
Join point: A join point is a point in the application where we apply an AOP aspect. Or it is a
specific execution instance of an advice. In AOP, join point can be a method execution,
exception handling, changing object variable value, etc.
Advice: The advice is an action that we take either before or after the method execution. The
action is a piece of code that invokes during the program execution. There are five types of
advices in the Spring AOP framework: before, after, after-returning, after-throwing, and around
advice. Advices are taken for a particular join point. We will discuss these advices further in this
section.
Target object: An object on which advices are applied, is called the target object. Target objects
are always a proxied It means a subclass is created at run time in which the target method is
overridden, and advices are included based on their configuration.
Weaving: It is a process of linking aspects with other application types. We can perform weaving
at run time, load time, and compile time.
Proxy: It is an object that is created after applying advice to a target object is called proxy. The
Spring AOP implements the JDK dynamic proxy to create the proxy classes with target classes
and advice invocations. These are called AOP proxy classes.
AOP OOP
Aspect: A code unit that encapsulates pointcuts, advices, and attributes. Class: A code unit
that encapsulates methods and attributes.
Pointcut: It defines the set of entry points in which advice is executed. Method signature: It
defines the entry points for the execution of method bodies.
Advice: It is an implementation of cross-cutting concerns. Method bodies: It is an
implementation of the business logic concerns.
Waver: It constructs code (source or object) with advice. Compiler: It converts source code to
object code.
Spring Boot AOP
Spring AOP vs. AspectJ
The differences between AOP and OOP are as follows:
Before Advice
After Advice
Around Advice
After Throwing
After Returning
Before Advice: An advice that executes before a join point, is called before advice. We use
@Before annotation to mark an advice as Before advice.
After Advice: An advice that executes after a join point, is called after advice. We use @After
annotation to mark an advice as After advice.
ADVERTISEMENT
Around Advice: An advice that executes before and after of a join point, is called around advice.
After Throwing Advice: An advice that executes when a join point throws an exception.
After Returning Advice: An advice that executes when a method executes successfully.
ADVERTISEMENT
Before implementing the AOP in an application, we are required to add Spring AOP
dependency in the [Link] file.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>[Link]</version>
</dependency>
In the next section, we will implement the different advices in the application.=
================================================================
AOP Before Advice
AOP After Advice
AOP Around Advice
After Returning Advice
After Throwing Advice
================================================================
Spring Boot Database
Spring Boot JPA
================================================================
What is JPA?
Spring Boot JPA is a Java specification for managing relational data in Java applications. It
allows us to access and persist data between Java object/ class and relational database. JPA
follows Object-Relation Mapping (ORM). It is a set of interfaces. It also provides a runtime
EntityManager API for processing queries and transactions on the objects against the database.
It uses a platform-independent object-oriented query language JPQL (Java Persistent Query
Language).
ADVERTISEMENT
JPA avoids writing DDL in a database-specific dialect of SQL. Instead of this, it allows mapping
in XML or using Java annotations.
JPA allows us to avoid writing DML in the database-specific dialect of SQL.
JPA allows us to save and load Java objects and graphs without any DML language at all.
When we need to perform queries JPQL, it allows us to express the queries in terms of Java
entities rather than the (native) SQL table and columns.
JPA Features
There are following features of JPA:
The following figure describes the class-level architecture of JPA that describes the core classes
and interfaces of JPA that is defined in the javax persistence package. The JPA architecture
contains the following units:
In the following figure, the ORM layer is an adapter layer. It adapts the language of object
graphs to the language of SQL and relation tables.
JPA Versions
Earlier versions of EJB defines the persistence layer combined with the business logic layer
using [Link] Interface. EJB specification includes the definition of JPA.
While introducing EJB 3.0, the persistence layer was separated and specified as JPA 1.0 (Java
Persistence API). The specifications of this API were released along with the specifications of
JAVA EE5 on May 11, 2006, using JSR 220.
In 2019, JPA renamed to Jakarta Persistence. The latest version of JPA is 2.2. It supports the
following features:
The following table describes the differences between JPA and Hibernate.
JPA Hibernate
JPA is a Java specification for mapping relation data in Java application. Hibernate is an ORM
framework that deals with data persistence.
JPA does not provide any implementation classes. It provides implementation classes.
It uses platform-independent query language called JPQL (Java Persistence Query Language).
It uses its own query language called HQL (Hibernate Query Language).
It is defined in [Link] package. It is defined in [Link] package.
It is implemented in various ORM tools like Hibernate, EclipseLink, etc. Hibernate is the
provider of JPA.
JPA uses EntityManager for handling the persistence of data. In Hibernate uses Session
for handling the persistence of data.
Spring Boot Starter Data JPA
Spring Boot provides starter dependency spring-boot-starter-data-jpa to connect Spring Boot
application with relational database efficiently. The spring-boot-starter-data-jpa internally uses
the spring-boot-jpa dependency.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>[Link]</version>
</dependency>
Spring Boot JPA Example
Let's create a Spring Boot application that uses JPA to connect to the database. In the following
example, we have used in-memory database Apache Derby.
ADVERTISEMENT
ADVERTISEMENT
In Spring Boot, we can easily integrate Apache Derby database just by adding Derby
dependency in [Link] file.
<dependency>
<groupId>[Link]</groupId>
<artifactId>derby</artifactId>
<scope>runtime</scope>
</dependency>
Step 1: Open Spring Initializr [Link]
Step 5: Add the dependencies: Spring Web, Spring Data JPA, and Apache Derby Database.
ADVERTISEMENT
Step 6: Click on the Generate button. When we click on the Generate button, it wraps the
project in a Jar file and downloads it to the local system.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder apache-derby-example
-> Finish
Step 9: Create a package with the name [Link] in the folder src/main/java.
Step 10: Create a class with the name UserRecord in the package [Link] and do
the following:
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
@Entity
public class UserRecord
{
@Id
private int id;
private String name;
private String email;
//default conatructor
public UserRecord()
{
}
public int getId()
{
return id;
}
public void setId(int id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
[Link] = email;
}
}
Step 11: Create a package with the name [Link] in the folder src/main/java.
Step 12: Create a Controller class with the name UserController in the package
[Link] and do the following:
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserController
{
@Autowired
private UserService userService;
@RequestMapping("/")
public List<UserRecord> getAllUser()
{
return [Link]();
}
@RequestMapping(value="/add-user", method=[Link])
public void addUser(@RequestBody UserRecord userRecord)
{
[Link](userRecord);
}
}
Step 13: Create a package with the name [Link] in the folder src/main/java.
Step 14: Create a Service class with the name UserService in the package
[Link] and do the following:
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Service
public class UserService
{
@Autowired
private UserRepository userRepository;
public List<UserRecord> getAllUsers()
{
List<UserRecord>userRecords = new ArrayList<>();
[Link]().forEach(userRecords::add);
return userRecords;
}
public void addUser(UserRecord userRecord)
{
[Link](userRecord);
}
}
Step 15: Create a package with the name [Link] in the folder src/main/java.
Step 16: Create a repository interface with the name UserRepository in the package
[Link] and extends CrudRepository.
[Link]
package [Link];
import [Link];
import [Link];
public interface UserRepository extends CrudRepository<UserRecord, String>
{
}
Step 17: Now, open the [Link] file. It created by default when
we set-up an application.
[Link]
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class ApacheDerbyExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Now, we have set-up all the necessary classes and packages according to the requirements.
Notice that we have not provided any connection URL for the database. After completing all the
above steps, the project directory looks like the following:
Step 18: Open the [Link] file and run it as Java Application.
Step 19: Open the browser and invoke the URL [Link] It returns an empty list
because we have not added any user in the List.
To add a user to the database, we will send a POST request by using the Postman.
Step 21: Open the browser and invoke the URL [Link] It returns the user that we
have inserted in the database.
In Spring Boot JDBC, the database related beans such as DataSource, JdbcTemplate, and
NamedParameterJdbcTemplate auto-configures and created during the startup. We can
autowire these classes if we want to use it. For example:
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
In [Link] file, we configure DataSource and connection pooling. Spring Boot
chooses tomcat pooling by default.
In the first figure, there are three clients connected with different connections, and a connection
is available. In the second figure, Client 3 has disconnected, and that connection is available.
When a client completes his work, it releases the connection, and that connection is available
for other clients.
HikariCP
The default connection pool in Spring Boot 2 is HikariCP. It provides enterprise-ready features
and better performance. HikariCP is a JDBC DataSource implementation that provides a
connection pooling mechanism.
If the HikariCP is present on the classpath, the Spring Boot automatically configures it.
If the HikariCP is not found on the classpath, Spring Boot looks for the Tomcat JDBC
Connection Pool. If it is on the classpath Spring Boot, pick it up.
If both the above options are not available, Spring Boot chooses Apache Commons DBCP2 as
the JDBC connection pool.
We can also configure a connection pool manually, if we do not want to use the default
connection pool. Suppose, we want to use Tomcat JDBC connection pool instead of HikariCP.
We will exclude HikariCP dependency and add the tomcat-jdbc dependency in the [Link] file,
as shown below.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</ artifactId >
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>HikariCP</ artifactId >
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>9.0.10</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.9</version>
<socpe>runtime</scoope>
</dependency>
The above approach allows us to use Tomcat connection pool without having to write a
@Configuration class and programmatically define a DataSource bean.
On the other hand, we can also skip the connection pool scanning algorithm that Spring Boot
uses. We can explicitly specify a connection pooling datasource by adding the property
[Link] in the [Link] file.
[Link]=[Link]
We have set up the Tomcat connection pool. Now, we will add some properties in
[Link] that optimize its performance and suiting some specific requirements.
[Link]-size=20
[Link]-wait=25000
[Link]-active=70
[Link]-idle=20
[Link]-idle=9
[Link]-auto-commit=true
If we want to connect to MySQL database, we need to include the JDBC driver in the
application's classpath:
[Link]=jdbc:mysql://[Link]:3306/test
[Link]=javatpoint
[Link]=password
Use the following properties if you are using Oracle database:
[Link]=jdbc:oracle:thin:@localhost:1521:orcl
[Link]=system
[Link]=Password123
Note: Spring Boot 2 uses HikariCP as the database connection pool, by default. If the HikariCP
is not present in the classpath, Spring Boot choose tomcat pooling by default.
Why should we use Spring Boot JDBC?
The functionality of Spring JDBC and Spring Boot JDBC is the same except the
implementations. There are following advantages of Spring Boot JBDC over Spring JDBC:
The CRUD operation can be defined as user interface conventions that allow view, search, and
modify information through computer-based forms and reports. CRUD is data-oriented and the
standardized use of HTTP action verbs. HTTP has a few important verbs.
ADVERTISEMENT
Suppose, if we want to create a new record, we should use HTTP action verb POST. To update
a record, we should use the PUT verb. Similarly, if we want to delete a record, we should use
the DELETE verb. Through CRUD operations, users and administrators have the right to
retrieve, create, edit, and delete records online.
We have many options for executing CRUD operations. One of the most efficient choices is to
create a set of stored procedures in SQL to execute operations.
The CRUD operations refer to all major functions that are implemented in relational database
applications. Each letter of the CRUD can map to a SQL statement and HTTP methods.
Syntax
ADVERTISEMENT
For example:
Step 5: Add the dependencies Spring Web, Spring Data JPA, and H2 Database.
ADVERTISEMENT
Step 6: Click on the Generate button. When we click on the Generate button, it wraps the
specifications in a Jar file and downloads it to the local system.
ADVERTISEMENT
ADVERTISEMENT
Step 8: Import the project folder into STS.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-crud-operation -> Finish
Step 10: Create a model class in the package [Link]. We have created a model
class with the name Books. In the Books class, we have done the following:
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
//mark class as an Entity
@Entity
//defining class name as Table name
@Table
public class Books
{
//Defining book id as primary key
@Id
@Column
private int bookid;
@Column
private String bookname;
@Column
private String author;
@Column
private int price;
public int getBookid()
{
return bookid;
}
public void setBookid(int bookid)
{
[Link] = bookid;
}
public String getBookname()
{
return bookname;
}
public void setBookname(String bookname)
{
[Link] = bookname;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
[Link] = author;
}
public int getPrice()
{
return price;
}
public void setPrice(int price)
{
[Link] = price;
}
}
ADVERTISEMENT
ADVERTISEMENT
Step 11: Create a package with the name [Link] in the folder src/main/java.
Step 12: Create a Controller class in the package [Link]. We have created a
controller class with the name BooksController. In the BooksController class, we have done the
following:
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
//mark class as Controller
@RestController
public class BooksController
{
//autowire the BooksService class
@Autowired
BooksService booksService;
//creating a get mapping that retrieves all the books detail from the database
@GetMapping("/book")
private List<Books> getAllBooks()
{
return [Link]();
}
//creating a get mapping that retrieves the detail of a specific book
@GetMapping("/book/{bookid}")
private Books getBooks(@PathVariable("bookid") int bookid)
{
return [Link](bookid);
}
//creating a delete mapping that deletes a specified book
@DeleteMapping("/book/{bookid}")
private void deleteBook(@PathVariable("bookid") int bookid)
{
[Link](bookid);
}
//creating post mapping that post the book detail in the database
@PostMapping("/books")
private int saveBook(@RequestBody Books books)
{
[Link](books);
return [Link]();
}
//creating put mapping that updates the book detail
@PutMapping("/books")
private Books update(@RequestBody Books books)
{
[Link](books);
return books;
}
}
Step 13: Create a package with the name [Link] in the folder src/main/java.
Step 14: Create a Service class. We have created a service class with the name BooksService
in the package [Link].
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
//defining the business logic
@Service
public class BooksService
{
@Autowired
BooksRepository booksRepository;
//getting all books record by using the method findaAll() of CrudRepository
public List<Books> getAllBooks()
{
List<Books> books = new ArrayList<Books>();
[Link]().forEach(books1 -> [Link](books1));
return books;
}
//getting a specific record by using the method findById() of CrudRepository
public Books getBooksById(int id)
{
return [Link](id).get();
}
//saving a specific record by using the method save() of CrudRepository
public void saveOrUpdate(Books books)
{
[Link](books);
}
//deleting a specific record by using the method deleteById() of CrudRepository
public void delete(int id)
{
[Link](id);
}
//updating a record
public void update(Books books, int bookid)
{
[Link](books);
}
}
Step 15: Create a package with the name [Link] in the folder src/main/java.
ADVERTISEMENT
ADVERTISEMENT
Step 16: Create a Repository interface. We have created a repository interface with the name
BooksRepository in the package [Link]. It extends the Crud Repository
interface.
[Link]
package [Link];
import [Link];
import [Link];
//repository that extends CrudRepository
public interface BooksRepository extends CrudRepository<Books, Integer>
{
}
Now we will configure the datasource URL, driver class name, username, and password, in the
[Link] file.
Step 17: Open the [Link] file and configure the following properties.
[Link]
[Link]=jdbc:h2:mem:books_data
[Link]=[Link]
[Link]=sa
[Link]=
[Link]-platform=[Link].H2Dialect
#enabling the H2 console
[Link]=true
Note: Do not forget to enable the H2 console.
After creating all the classes and packages, the project directory looks like the following.
ADVERTISEMENT
ADVERTISEMENT
[Link]
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootCrudOperationApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Note: In the next steps we will use rest client Postman. So, ensure that the Postman application
is already installed in your system.
Step 19: Open the Postman and do the following:
{
"bookid": "0982",
"bookname": "Programming with Java",
"author": "E. Balagurusamy",
"price": "350"
}
{
"bookid": "6321",
"bookname": "Data Structures and Algorithms in Java",
"author": "Robert Lafore",
"price": "590"
}
{
"bookid": "5433",
"bookname": "Effective Java",
"author": "Joshua Bloch",
"price": "670"
}
Let's access the H2 console to see the data.
Step 20: Open the browser and invoke the URL [Link] Click on the
Connect button, as shown below.
Select the DELETE method and invoke the URL [Link] Again,
execute the Select query in the H2 console. We see that the book whose id is 5433 has been
deleted from the database.
================================================================
Spring Boot View
SB Thymeleaf View
================================================================
What is Thymeleaf?
The Thymeleaf is an open-source Java library that is licensed under the Apache License 2.0. It
is a HTML5/XHTML/XML template engine. It is a server-side Java template engine for both web
(servlet-based) and non-web (offline) environments. It is perfect for modern-day HTML5 JVM
web development. It provides full integration with Spring Framework.
It applies a set of transformations to template files in order to display data or text produced by
the application. It is appropriate for serving XHTML/HTML5 in web applications.
The goal of Thymeleaf is to provide a stylish and well-formed way of creating templates. It is
based on XML tags and attributes. These XML tags define the execution of predefined logic on
the DOM (Document Object Model) instead of explicitly writing that logic as code inside the
template. It is a substitute for JSP.
The architecture of Thymeleaf allows the fast processing of templates that depends on the
caching of parsed files. It uses the least possible amount of I/O operations during execution.
Thymeleaf supports variable expressions (${...}) like Spring EL and executes on model
attributes, asterisk expressions (*{...}) execute on the form backing bean, hash expressions
(#{...}) are for internationalization, and link expressions (@{...}) rewrite URLs.
XML
Valid XML
XHTML
Valid XHTML
HTML5
Legacy HTML5
Except for the Legacy HTML5 mode, all the above modes refer to well-defined XML files. It
allows us to process HTML5 files with features such as standalone tags, tag attributes without
value, or not written between quotes.
To process files in this specific mode, Thymeleaf performs a transformation that converts files
into a well-formed XML file (valid HTML5 file).
ADVERTISEMENT
Note: In Thymeleaf, validation is available only for XHTML and XML template.
Thymeleaf also allows us to define our own mode by specifying both a way to parse templates
in this mode. In this way, whatever that can be modeled as a DOM tree could effectively be
processed as a template by Thymeleaf.
An object that applies logic to a DOM node is called processor. A set of processors, along with
some extra artifacts, is called the dialect. The dialect that contains the Thymeleaf's core library
is called the Standard Dialect.
If we want to define our own processing logic while taking advantage of the library's advanced
features, we can define our own dialects. In a template engine, we can configure several
dialects at a time.
For example, use Spring Expression Language instead of Thymeleaf's standard ONGL
(Object-Graph Navigation Language).
The Standard Dialect can process template in any mode. But it is perfect for web-oriented
template modes (HTML5 and XHTML). It supports and validates the following XHTML
specifications:
For example, when a JSP file uses tag library, it includes a fragment of code not displayable by
a browser like:
It allows a designer and developer to work on the same template file that reduces the efforts
required to transform a static prototype into a working template file. It is known as Natural
Templating.
Thymeleaf Features
It works on both web and non-web environments.
Java template engine for HTML5/ XML/ XHTML.
Its high-performance parsed template cache reduces I/O to the minimum.
It can be used as a template engine framework if required.
It supports several template modes: XML, XHTML, and HTML5.
It allows developers to extend and create custom dialect.
It is based on modular features sets called dialects.
It supports internationalization.
Thymeleaf Implementation
ADVERTISEMENT
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Spring Boot Thymeleaf Example
Let's create a Spring Boot application and implement Thymeleaf template.
Step 6: Click on the Generate button. When we click on the Generate button, it wraps the
specifications in a Jar file and downloads it to the local system.
Spring Boot thymeleaf view
Step 7: Extract the Jar file and paste it into the STS workspace.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-thymeleaf-view-example -> Finish
Step 9: Create a model class in the package [Link]. We have created a model class
with the name User.
ADVERTISEMENT
ADVERTISEMENT
In this class, we have defined two variables name and email and generate Getters and Setters.
[Link]
package [Link];
public class User
{
String name;
String email;
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
[Link] = email;
}
}
Step 10: Create a controller class. We have created a controller class with the name
DemoController.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class DemoController
{
@RequestMapping("/")
public String index()
{
return"index";
}
@RequestMapping(value="/save", method=[Link])
public ModelAndView save(@ModelAttribute User user)
{
ModelAndView modelAndView = new ModelAndView();
[Link]("user-data");
[Link]("user", user);
return modelAndView;
}
}
In the next step, we will create the Thymeleaf templates.
Step 11: Inside the templates (src/main/resources/templates) folder of the project create a
Thymeleaf template with the name user-data.
ADVERTISEMENT
ADVERTISEMENT
Right-click on the templates folder -> New -> Other -> HTML File -> Next -> Provide the File
name -> Finish
<html xmlns:th="[Link]
<table>
<tr>
<td><h4>User Name: </h4></td>
<td><h4 th:text="${[Link]}"></h4></td>
</tr>
<tr>
<td><h4>Email ID: </h4></td>
<td><h4 th:text="${[Link]}"></h4></td>
</tr>
</table>
</html>
Step 12: Similarly, create an HTML file in the folder templates. We have created an HTML file
with the name index.
[Link]
<html lang="en">
<head>
<title>Index Page</title>
</head>
<body>
<form action="save" method="post">
<table>
<tr>
<td><label for="user-name">User Name</label></td>
<td><input type="text" name="name"></input></td>
</tr>
<tr>
<td><label for="email">Email</label></td>
<td><input type="text" name="email"></input></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Submit"></input></td>
</tr>
</table>
</form>
</body>
</html>
Step 13: Open the [Link] file and add the following properties in it.
[Link]
[Link]=false
[Link]: .html
After creating all the files, folders, and packages, the project directory looks like the following:
[Link]
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootThymeleafViewExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Step 15: Now, open the browser and invoke the URL [Link] It shows the output,
as shown below.
================================================================
SB Caching
================================================================
Spring Boot Caching
================================================================
Spring Framework provides caching in a Spring Application, transparently. In Spring, the cache
abstraction is a mechanism that allows consistent use of various caching methods with minimal
impact on the code.
Cache Abstraction
The cache abstraction mechanism applies to Java methods. The main objective of using cache
abstraction is to reduce the number of executions based on the information present in the
cache. It applies to expensive methods such as CPU or IO bound.
Every time, when a method invokes, the abstraction applies a cache behavior to the method. It
checks whether the method has already been executed for the given argument or not.
ADVERTISEMENT
If yes, the cached result is returned without executing the actual method.
If no, first, the method executes, and the result is cached and returned to the user.
Note: This approach works only for the methods that are guaranteed to return the same result
for a given input. It does not matter how many times the method executes.
The developers take care of two things while working with cache abstractions.
Play
Next
Mute
Current TimeÂ
0:00
/
DurationÂ
18:10
Loaded: 0.37%
Â
Fullscreen
Play Video
In-memory Caching
Database Caching
Web server Caching
CDN Caching
In-memory Caching
In-memory caching increases the performance of the application. It is the area that is frequently
used. Memcached and Redis are examples of in-memory caching. It stores key-value between
application and database. Redis is an in-memory, distributed, and advanced caching tool that
allows backup and restore facility. We can manage cache in distributed clusters, also.
Database Caching
Database caching is a mechanism that generates web pages on-demand (dynamically) by
fetching the data from the database. It is used in a multi-tier environment that involved clients,
web-application server, and database. It improves scalability and performance by distributing a
query workload. The most popular database caching is the first level cache of Hibernate.
CDN Caching
The CDN stands for Content Delivery Network. It is a component used in modern web
applications. It improves the delivery of the content by replicating commonly requested files
(such as HTML Pages, stylesheet, JavaScript, images, videos, etc.) across a globally distributed
set of caching servers.
It is the reason CDN becomes more popular. The CDN reduces the load on an application origin
and improves the user experience. It delivers a local copy of the content from a nearby cache
edge (a cache server that is closer to the end-user), or a Point of Presence (PoP).
Example
@SpringBootApplication
@EnableCaching
public class SpringBootCachingApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
@CacheConfig
It is a class-level annotation that provides a common cache-related setting. It tells the Spring
where to store cache for the class. When we annotate a class with the annotation, it provides a
set of default settings for any cache operation defined in that class. Using the annotation, we
need not to declare things multiple times.
Example
@CacheConfig(cacheNames={"employee"})
public class UserService
{
//some code
}
@Caching
It is used when we need both annotations @CachePut or @CacheEvict at the same time on the
same method. In other words, it is used when we want to use multiple annotations of the same
type.
ADVERTISEMENT
But Java does not allow multiple annotations of the same type to be declared for a given
method. To avoid this problem, we use @Caching annotation.
Example
In the following example, we have used the annotation @Caching and grouped all the
@CacheEvict annotations.
We can also specify the key attribute of the annotation that uniquely identifies each entry in the
cache. If we do not specify the key, Spring uses the default mechanism to create the key.
Example
In the following example, we have cached the return value of the method studentInfo() in
cacheStudentInfo, and id is the unique key that identifies each entry in the cache.
@Cacheable(value="cacheStudentInfo", key="#id")
public List studentInfo()
{
//some code
return studentDetails;
}
We can also apply a condition in the annotation by using the condition attribute. When we apply
the condition in the annotation, it is called conditional caching.
For example, the following method will be cached if the argument name has a length shorter
than 20.
@Cacheable(value="student", condition="#[Link]<20")
public Student findStudent(String name)
{
//some code
}
@CacheEvict
It is a method level annotation. It is used when we want to remove stale or unused data from the
cache. It requires one or multiple caches that are affected by the action. We can also specify a
key or condition into it. If we want wide cache eviction, the @CacheEvict annotation provides a
parameter called allEntries. It evicts all entries rather than one entry based on the key.
One important point about @CacheEvict annotation is that it can be used with void methods
because the method acts as a trigger. It avoids return values. On the other hand, the annotation
@Cacheable requires a return value that adds/updates data in the cache. We can use
@CacheEvict annotation in the following ways:
@CacheEvict(allEntries=true)
Evict an entry by key:
@CacheEvict(key="#student.stud_name")
Example
The following annotated method evicts all the data from the cache student_data.
ADVERTISEMENT
A point to be noticed that the annotations @Cacheable and @CachePut are not the same
because they have different behavior. There is a slight difference between @Cacheable and
@CachePut annotation is that the @Cacheable annotation skips the method execution while
the @CachePut annotation runs the method and put the result into the cache.
Example
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Spring Boot Cache Example
Let's create a Spring Boot application and implement cache mechanism into it.
Step 5: Add the dependencies Spring Web and Spring Cache Abstraction.
Step 6: Click on the Generate button. When we click on the Generate button, it wraps the
specifications in a Jar file and downloads it to the local system.
Step 7: Extract the Jar file and paste it into the STS workspace.
File -> Import -> Existing Maven Projects -> Browse -> Select the folder
spring-boot-cache-example -> Finish
Let's open the [Link] file and see which dependencies we have added into it.
[Link]
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
@SpringBootApplication
//enabling caching
@EnableCaching
public class SpringBootCacheExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Step 10: Create a package in the folder src/main/java with the name [Link].
Step 11: In the model package, create a class with the name Customer and define the following:
package [Link];
public class Customer
{
private int accountno;
private String customername;
private String accounttype;
private double balance;
public Customer(int accountno, String customername, String accounttype, double balance)
{
[Link] = accountno;
[Link] = customername;
[Link] = accounttype;
[Link] = balance;
}
public int getAccountno()
{
return accountno;
}
public void setAccountno(int accountno)
{
[Link] = accountno;
}
public String getCustomername()
{
return customername;
}
public void setCustomername(String customername)
{
[Link] = customername;
}
public String getAccounttype()
{
return accounttype;
}
public void setAccounttype(String accounttype)
{
[Link] = accounttype;
}
public double getBalance()
{
return balance;
}
public void setBalance(double balance)
{
[Link] = balance;
}
}
Step 11: Create a package in the folder src/main/java with the name [Link].
Step 12: In the Controller package, create a controller class with the name CustomerController
and do the following:
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class CustomerController
{
@RequestMapping("/customerinfo")
//defines a cache for method's return value
@Cacheable(value="customerInfo")
public List customerInformation()
{
[Link]("customer information from cache");
//adding customer detail in the List
List detail=[Link](new Customer(5126890,"Charlie Puth","Current A/c", 450000.00),
new Customer(7620015,"Andrew Flintoff","Saving A/c", 210089.00)
);
return detail;
}
}
Now run the application.
Step 13: Open the [Link] file and run it as Java Application.
Step 14: Open the Postman and send a GET request with the URL
[Link] It returns the customer details, as shown below.
In Spring Boot, the cache abstraction does not provide the actual space for the cache. It
depends on the abstraction that occurred by the [Link] or
[Link] interfaces.
Caching Auto-configuration
The Spring Boot Framework simplifies the implementation of caching by auto-configuration
support. It searches for the libraries and configuration-files in the classpath and initializes the
required dependency beans at the time of application startup. The auto-configuration of caching
includes the following steps:
ADVERTISEMENT
Next
Mute
Current TimeÂ
0:00
/
DurationÂ
18:10
Loaded: 0.37%
Â
Fullscreen
Play Video
@SpringBootApplication
@EnableCaching
public class Employee
{
@Bean
public CacheManager cacheManager()
{
//some code
}
}
Add EhCache dependency in the [Link] file. It adds the required libraries in the classpath.
<dependency>
<groupId>[Link]</groupId>
<artifactId>ehcache</artifactId>
</dependency>
At the end, configure the file for cache provider. Here, we are using the EhCache so need to
configure [Link] file at the root of the classpath.
When we do not define a bean of type CacheManager or CacheResolver, the Spring Boot
Framework tries to detect the following cache provider:
Generic
JCache
EhCache
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Simple
If the Spring Boot finds the more than one cache provider in the classpath, in such cases, we
must specify the cache provider explicitly in the [Link] file.
[Link]=[Link]
[Link]=classpath:config/[Link]
We can set up a particular cache provider by using the property [Link]. It is used in
a certain environment if we want to disable caching.
[Link]=none
The Spring Boot Framework provides a starter dependency that adds basic cache dependency
in the application. The starter cache dependency, by default, provides the
spring-context-support dependency.
In the follwoig example, we have set up a flag that passes the null values to the primary map.
@Bean
public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer()
{
return new CacheManagerCustomizer<ConcurrentMapCacheManager>()
{
@Override
public void customize(ConcurrentMapCacheManager cacheManager)
{
[Link](false);
}
};
}
The above bean expects a auto-configured ConcurrentMapCacheManager. If the
ConcurrentMapCacheManager is not auto-configures, the customizer will not invoke in any way.
We can have any number of customizer and arrange them in order by using the annotation
@Order or @Ordered.
Generic Caching
If the spring-context-support defines at least one [Link] bean, it
uses the Generic cache. The CacheManager bundled all the beans and configured them.
JCache
JCache is a self-starting process that is provided by the [Link]. It is
present on the classpath JSR 107. The spring-boot-starter-cache provides the
JCacheCacheManager. We can add any other cache library as well.
Note: Spring Boot prefers the JSR support if a cache library provides both native
implementation and JSR support.
EhCache 2.x
EHCache is Java-based, open-source, and widely used cache. In order to use EhCache we
should use the following dependency.
<dependency>
<groupId>[Link]</groupId>
<artifactId>ehcache</artifactId>
</dependency>
There are two ways to configure EhCache:
First, by configuring Java POJO file where all configuration parameters are configured through
EhCache API.
Second, by configuring the XML file where we configure EhCache according to the provided
schema definition.
EhCache used a file called [Link]. If the application found the file on the classpath, the
EhCacheCacheManager provided by the spring-boot-starter-cache. We can configure the XML
file by using the following property:
[Link]=classpath:config/[Link]
Hazelcast
When we enable the caching in an application, Spring Boot wraps the HazelcastInstance
automatically in the CacheManager. It distributes the data equally among the nodes. We can
configure Hazelcast by using the following property.
[Link]=classpath:config/[Link]
If the property is not set, Spring Boot tries to find the [Link] (Hazelcast configuration) file
on the classpath.
Infinispan
Infinispan is an embedded Java library. It is used as a cache or a data grid. It stores data in the
key-value form. It can be easily integrated with JCache, JPA Quarkus, Spring, etc.
It does not have a default file location, so we should specify it explicitly. If the infinispan is not
specified explicitly, it uses default bootstrap.
[Link]=[Link]
Couchbase
The CouchebaseCacheManager is automatically configured when we implement
couchbase-spring-cache, and Couchbase is configured. All the operations related to the cache
perform in the Bucket. It allows us to create additional caches (if required) by setting up the
property [Link]-name.
The customizer allows us to create additional Buckets, in which we can create another cache.
Suppose that we need three caches named cacheA, cacheB, and cacheC. The cacheA and
cacheB are on the main Bucket (i.e., auto-configured Bucket). The cacheC is on another Bucket
that is to live for a few seconds, say 4 seconds. Hence, we can create cacheA and cacheB by
specifying the property, as follows:
[Link]-names=cacheA, cacheB
Redis
The RedisCacheManager is autoconfigured when we configure Redis. It also allows us to create
additional cache by using the property [Link]-names. The default configuration can
be achieved by using the property [Link].*.
We can take full control over the default configuration by using the RedisCacheConfiguration
bean.
[Link]-names=cacheA, cacheB
[Link]-to-live=100000
The above properties configure two caches named cacheA and cacheB, that lives for 10
minutes.
Caffeine
The caffeine is a Java based caching library. It also provides an in-memory cache. The
spring-boot-starter-cache dependency automatically configures the CaffeineCacheManger, if it
founds the Caffeine in the classpath. If we want to use Caffeine in an application, we need to
add the following dependency:
<dependency>
<groupId>[Link]</groupId>
<artifactId>caffeine</artifactId>
<version>2.7.0</version>
</dependency>
The caffeine cache allows us to define size and time to live of the cache by using the property
[Link]. For example:
[Link]-names=cacheA,cacheB
[Link]=maximumSize=500,expireAfterAccess=600s
The above configuration creates two caches named cache1 and cache2. The maximum size of
the cache is 500 and the maximum time to live cache is 6 seconds.
Simple
It is the default implementation. If no cache provider is specified. It configures a
ConcurrentHashMap as a cache store if the Spring Boot does not find any cache provider in the
classpath.
For example, if we want two caches, set their name by using the following property:
[Link]-names=cache1,cache2
None
When we enable the cache by using the annotation @EnableCaching, the application expects a
suitable configuration. It is used when we want to disable the cache in a certain environment.
We use the property [Link] to disable the cache.
[Link]=none
===============================================================
Spring Boot EhCaching
===============================================================
EhCache
EhCache is an open-source, Java-based cache used to boost performance. The current version
of Ehcache is 3. It provides the implementation of the JSR-107 cache manager. We can use it
directly.
Features of EhCache
ADVERTISEMENT
ADVERTISEMENT
It is fast, lightweight, Scalable, and Flexible.
It allows us to perform Serializable and Object
It offers cache eviction policies such as LRU, LFU, FIFO,
It stores the cache in memory and disk (SSD).
It depends on SLF4J for logging.
It has a full implementation of JSR-107 and Jcache
It supports distributed caching via JGroups or JMS and RMI.
It uses fluent query language for distributed search.
EhCache Usage Patterns
The cache uses several access patterns. There are following patterns used by EhCache:
Cache-aside
Cache-as-SoR (system-of-record)
Read-through
Write-through
Write-behind
Cache-aside
In the cache-aside pattern, first, the application consults with the cache. If the data is found, it
returns the data directly. In the opposite scenario, it fetches the data from the SoR, stores it into
the cache, and then return.
Cache-as-SoR
The cache-as-SoR pattern represents SoR reading and writing operations to the cache. It
reduces the responsibility of the application. It uses the combination of read and write pattern
that includes read-through, write-through, and write-behind. It reduces the difficulty of the
application. It allows the cache to solve the thundering-herd problem
ADVERTISEMENT
Read-through
The read-through pattern also copies the cache-aside pattern while reading data from the
cache. The difference between the read-through and cache-aside is that read-through pattern
implements the CacheEntryFactory interface. It guides the cache how to read an object from the
cache. It is better to wrap the EhCache instance with the instance of SelfPopulatingCache while
using the read-through pattern.
Write-through
The write-through pattern also copies the cache-aside pattern while writing data in the cache.
The difference between write-through and cache-aside pattern is that write-through pattern
implements the CacheWriter interface. It configures the cache for both write-through and
write-behind pattern. It writes data to the SoR in the same thread of execution.
Write-behind
The write-behind pattern is different form the other three patterns. It modifies the cache entries
after a configurable delay. The delay may in seconds, minutes, a day, a week, or for a long time.
Simultaneously, it also queues the data to write at a later time in the same thread of execution.
The data write using write-behind pattern happens outside of the scope of the transaction. It
means that it creates a new transaction to commit the data in the SoR that is distinct from the
main transaction.
The tiers are organized in order. The bottom-most tier is known as authority tier, and the other
tier is known as the caching tier. It is also known as nearer or near cache. The caching tier can
have more than one storage area. The hottest data kept in the caching tier because it is faster
than the authority tier. Other data is kept in the authority tier that is slower but richer in
comparison to the caching tier.
ADVERTISEMENT
ADVERTISEMENT
On-Heap Store
Off-Heap Store
Disk Store
Clustered Store
On-Heap Store
It stores cache entries in Java heap memory. It shares the storage with Java application. It is
fast because it uses heap but has limited storage space. The garbage collector also scans the
on-heap store.
Off-Heap Store
It uses the primary memory (RAM) to store cache entries. The garbage collector does not scan
it. It is slower than the on-heap store because the cache entries move to the on-heap store
before use. It is limited in size.
Disk Store
It uses a disk to store cache entries. It is much slower than RAM-based stores (on and off-heap
store). It is better to use a dedicated disk if you are using a disk store pattern. It enhances
throughput.
Clustered Store
It stores cache entries on the remote server. It is slower than off-heap storage. It may have a
failover server that provides high availability.
Step 3: Provide the Group name. We have provided the Group name [Link].
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT
Step 6: Click on the Generate button. When we click on the Generate button, it wraps all the
specifications related to application into a Jar file and downloads it to the local system.
File -> Import -> Existing Maven Projects -> Next -> Browse -> Select the folder
spring-boot-ehcache-example -> Select Folder -> Finish
ADVERTISEMENT
ADVERTISEMENT
Step 10: Copy the following dependency one by one from the Maven Repository
[Link] and paste it into the [Link] file.
spring-boot-starter-cache
ehcache 3
cache API.
Note: Do not use the ehcache of the package [Link].
[Link]
Step 11: Open the [Link] file and configure the EhCache by using the following
property.
[Link]
#configuring [Link]
[Link]=classpath:[Link]
Step 12: Open the [Link] file and enable caching by
using the annotation @EnableCaching.
[Link]
ADVERTISEMENT
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
@SpringBootApplication
//enables the cache management capability
@EnableCaching
public class SpringBootEhcacheExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Note: If we do not want to use annotation @EnableCaching in main application file, we can
create a separate CacheConfig class and annotate that call with the annotation.
package [Link];
import [Link];
import [Link];
@Configuration
//enable caching
@EnableCaching
public class CacheConfig
{
}
Step 13: Create a model class. We have created the model class in the package [Link]
with the name Student. In the model class do the following:
[Link]
package [Link];
public class Student
{
private int id;
private String name;
private String gender;
private String city;
public Student(int id, String name, String gender, String city)
{
super();
[Link] = id;
[Link] = name;
[Link] = gender;
[Link] = city;
}
public int getId()
{
return id;
}
public void setId(int id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public String getGender()
{
return gender;
}
public void setGender(String gender)
{
[Link] = gender;
}
public String getCity()
{
return city;
}
public void setCity(String city)
{
[Link] = city;
}
@Override
public String toString()
{
return "Student [id=" + id + ", name=" + name + ", gender=" + gender + ", city=" + city + "]";
}
}
Step 14: Create a Service class that manages the student. We have created the service class
with the name StudentManager. In this class, we have done the following:
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
@Service
public class StudentManager
{
static HashMap<Integer, Student> student = new HashMap<>();
static
{
[Link](1, new Student(100, "Alex", "Male", "Berlin"));
[Link](2, new Student(101, "Tony", "Male", "Maxico"));
[Link](3, new Student(102, "Andrew", "Male", "Chicago"));
[Link](4, new Student(103, "Alexa", "Female", "Brussels"));
[Link](5, new Student(104, "Maria", "Female", "Houston"));
}
@Cacheable(cacheNames="demoCache", key="#id")
public Student getStudentById(Integer id)
{
[Link]("Fetching student data from cache");
return [Link](id);
}
}
Now we need to create [Link] file. It contains the information related to cache such as
name of the cache, no of element in the memory, time to live data in the cache, etc.
ADVERTISEMENT
ADVERTISEMENT
Step 15: Create a cache configure file named [Link] in the src/main/resources folder.
[Link]
<config
xmlns:xsi='[Link]
xmlns='[Link]
xmlns:jsr107='[Link]
<ehcache>
<diskStore path="[Link]" />
<defaultCache maxElementsInMemory="2000"
eternal="true"
overflowToDisk="false"
timeToLiveSeconds="1200" />
<cache name="demoCache"
maxElementsInMemory="2000"
eternal="false"
overflowToDisk="false"
timeToLiveSeconds="10000" />
</ehcache>
</config>
Now we have created all the required files. After creating all the files, the project directory looks
like the following:
================================================================
Spring Boot Misc
-------------------------------------------------------------------------------------------------------------------------------
Run SB Application
===============================================================
How to Run Spring Boot Application
In this section, we will create and run a simple Spring Boot application.
Step 6: Click on the Generate button. When we click on the Generate button, it wraps all the
specifications related to application into a Jar file and downloads it to the local system.
File -> Import -> Existing Maven Projects -> Next -> Browse -> Select the folder spring-
spring-boot-application-run -> Select Folder -> Finish
It takes time to import the project. When the project imports successfully, we can see it in the
Package Explorer section of the IDE.
We see that two files are automatically created, one is [Link], and the other is
[Link] file.
[Link]
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>[Link]</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>[Link]
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>[Link]
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>[Link]
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>[Link]
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
The main class is a class that contains the main() method. It starts the Spring
ApplicationContext. It is the class that we run for the execution of the application.
[Link]
ADVERTISEMENT
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootApplicationRun
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
Step 10: Create a Controller. We have created a controller with the name HelloWorldController.
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class HelloWorldController
{
@RequestMapping("/")
public String hello()
{
return "Hello User";
}
}
Now we have created all the required files related to Spring Boot application.
We can change the port in Spring Boot by using the following interfaces and properties files:
ADVERTISEMENT
ADVERTISEMENT
Using [Link] file
Using [Link] file
Using EmbeddedServletContainerCustomizer Interface
Using WebServerFactoryCustomizer Interface
Using Command-Line Parameter
Using [Link] file
We recommend you to use the [Link] file if you want to change the default port.
Because it is an easy and faster way to overwrite default values. We use the [Link]
property to overwrite the default property.
For example, if we want to change default port 8080 to 8082, specify the property in
[Link] file.
ADVERTISEMENT
[Link]
[Link]=8082
We can also set the port property to 0. It scans the random port for the application. It uses a
new port whenever we restart our application.
[Link]
[Link]=0
Using [Link] file
Similarly, we can also change the default port by using a yml file. Use either
[Link] or [Link] file, both the files works in the same manner.
[Link]
server:
port:8082
Using EmbeddedServletContainerCustomizer Interface
If you are using Spring Boot 1.x version, it provides an interface
EmbeddedServletContainerCustomizer to change the default port.
ADVERTISEMENT
ADVERTISEMENT
EmbeddedServletContainerCustomizer Interface
The interface contains a method called customize(). It allows us to customize and specify
ConfigurableEmbeddedServletContainer. It parses a parameter called container that we want to
customize.
Syntax
void customize(ConfigurableEmbeddedServletContainer container)
ConfigurableEmbeddedServletContainer Interface
setPort() method
The setPort() method configures the port of embedded servlet container should listen on. When
we do not specify the port, it uses the default port 8080. If we want to disable the auto-start
feature of the embedded server, use the port -1. The port -1 represents that it will not listen to
any port but start the web application context. The method parses a parameter port (the port to
set) of type int.
ADVERTISEMENT
ADVERTISEMENT
Syntax
void setPort(int port)
In the following example, we have created a class named ServerCustomizer and implements
the EmbeddedServletContainerCustomizer Interface. We have overridden the customize()
method and invoke the setPort() method that sets the port 8097.
[Link]
@Component
public class ServerCustomizer implements EmbeddedServletContainerCustomizer
{
@Override
public void customize(ConfigurableEmbeddedServletContainer container)
{
[Link](8097);
}
}
Using WebServerFactoryCustomizer Interface
Spring Boot 2.x version provides WebServerFactoryCustomizer interface to change the default
port. It defined in the package [Link]. It parses a parameter T of
type web server factory.
ADVERTISEMENT
ADVERTISEMENT
Syntax
public interface WebServerFactoryCustomizer<T extends WebServerFactory<
The interface contains a method called customize(). It allows us to customize web server
factories. It parses a parameter called factory that we want to customize. All the beans of this
type get a callback with the server factory before starting the container itself. Therefore, we can
set the port, addresses, and even error pages.
Syntax
void customize(T factory)
WebServerFactory Interface
ADVERTISEMENT
ADVERTISEMENT
It is a tagging interface for factories. It is defined in [Link]
package. It creates a WebServer.
ConfigurableWebServerFactory
setPort()
The setPort() method configures the port of embedded servlet container should listen on. When
we do not specify the port, it uses the default port 8080. If we want to disable the auto-start
feature of the embedded server, use the port -1. The port -1 represents that it will not listen to
any port but start the web application context. The method parses a parameter port (the port to
set) of type int.
Syntax
void setPort(int port)
Note: This setPort() method is of interface ConfigurableWebServerFactory
In the following example, we have created a class named ServerCustomizer that implements
the WebServerFactoryCustomizer Interface. We have overridden the customize() method and
invoke the setPort() method that sets the port 9001.
ADVERTISEMENT
ADVERTISEMENT
[Link]
@Component
public class ServerCustomizer implements WebServerFactoryCustomizer<
ConfigurableWebServerFactory <
{
@Override
public void customize(ConfigurableWebServerFactory factory)
{
[Link](9001);
}
}
ADVERTISEMENT
Using Command Line Parameter
We can also change the port in Spring Boot by using the command line parameter. We must
follow the steps given below:
Let's implement it in RSET application and understand the REST approach by using the
following steps.
ADVERTISEMENT
Step 3: Provide the Group name. We have provided the Group name [Link].
Step 6: Click on the Generate button. When we click on the Generate button, it wraps all the
specifications related to application into a Jar file and downloads it to the local system.
It takes time to import the project. When the project imports successfully, we can see it in the
Package Explorer section of the IDE.
Step 10: Create a model class in the package [Link]. We have created a model class
with the name Product. In this class, do the following:
ADVERTISEMENT
ADVERTISEMENT
After completing all the steps, the model class looks like the following.
ADVERTISEMENT
ADVERTISEMENT
[Link]
package [Link];
public class Product
{
private int id;
private String pname;
private String batchno;
private double price;
private int noofproduct;
//default constructor
public Product()
{
}
//constructor using fields
public Product(int id, String pname, String batchno, double price, int noofproduct)
{
super();
[Link] = id;
[Link] = pname;
[Link] = batchno;
[Link] = price;
[Link] = noofproduct;
}
//getters and setters
public int getId()
{
return id;
}
public void setId(int id)
{
[Link] = id;
}
public String getPname()
{
return pname;
}
public void setPname(String pname)
{
[Link] = pname;
}
public String getBatchno()
{
return batchno;
}
public void setBatchno(String batchno)
{
[Link] = batchno;
}
public double getPrice()
{
return price;
}
public void setPrice(double price)
{
[Link] = price;
}
public int getNoofproduct()
{
return noofproduct;
}
public void setNoofproduct(int noofproduct)
{
[Link] = noofproduct;
}
}
Now, we need to create a controller.
Step 11: In the [Link] package, create a Controller. We have created a controller with
the name ProductController.
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class ProductController
{
@Autowired
private IProductService productService;
//mapping the getProduct() method to /product
@GetMapping(value = "/product")
public List<Product> getProduct()
{
//finds all the products
List<Product> products = [Link]();
//returns the product list
return products;
}
}
Step 12: Create an interface in the package [Link] with the name IProductService and
define the findAll() method that returns a List of products.
[Link]
package [Link];
import [Link];
public interface IProductService
{
List<Product> findAll();
}
Step 13: Create a Service class. We have created a service class in the package [Link]
with the name ProductService.
Annotate the class with the annotation @Service and implements the IProductService interface.
In this class, override the findAll() method by using the annotation @Override. The findAll()
method of the ProductService class overrides the findAll() method of the IProductService
interface.
Create an object of ArrayList.
Add the products in the ArrayList.
Return the list of the products.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
@Service
public class ProductService implements IProductService
{
@Override
public List<Product> findAll()
{
//creating an object of ArrayList
ArrayList<Product> products = new ArrayList<Product>();
//adding products to the List
[Link](new Product(100, "Mobile", "CLK98123", 9000.00, 6));
[Link](new Product(101, "Smart TV", "LGST09167", 60000.00, 3));
[Link](new Product(102, "Washing Machine", "38753BK9", 9000.00, 7));
[Link](new Product(103, "Laptop", "LHP29OCP", 24000.00, 1));
[Link](new Product(104, "Air Conditioner", "ACLG66721", 30000.00, 5));
[Link](new Product(105, "Refrigerator ", "12WP9087", 10000.00, 4));
//returns a list of product
return products;
}
}
Step 14: In the static folder (src/main/resources/static), create an HTML file. We have created
an HTML file with the name index. In this file we have created a link of Get all Products.
[Link]
<!DOCTYPE html>
<html>
<head>
<title>Home page</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>
<a href="product">Get all Products</a>
</p>
</body>
</html>
Now we have created all the files and folders. After creating all the files, the project directory
looks like the fooling:
Step 15: Open the [Link] file and run it as Java Application.
By default, it runs on port 8080.
[Link]
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class SpringBootRestExampleApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
When the application runs successfully, it shows the message, as shown below
================================================================
Spring Boot - RESTful
-------------------------------------------------------------------------------------------------------------------------------
-
Introduction to RESTful Web Services With Spring Boot
================================================================
REST stands for REpresentational State Transfer. It is developed by Roy Thomas Fielding, who
also developed HTTP. The main goal of RESTful web services is to make web services more
effective. RESTful web services try to define services using the different concepts that are
already present in HTTP. REST is an architectural approach, not a protocol.
It does not define the standard message exchange format. We can build REST services with
both XML and JSON. JSON is more popular format with REST. The key abstraction is a
resource in REST. A resource can be anything. It can be accessed through a Uniform Resource
Identifier (URI). For example:
The resource has representations like XML, HTML, and JSON. The current state capture by
representational resource. When we request a resource, we provide the representation of the
resource. The important methods of HTTP are:
ADVERTISEMENT
ADVERTISEMENT
Step 3: Click on File menu -> New -> Spring Starter Project ->
Name: restful-web-services
Group: [Link]
Package: [Link]
[Link]
<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>[Link]</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>[Link]</groupId>
<artifactId>restful-web-services</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>restful-web-services</name>
<description>Demo project for Spring Boot</description>
<properties>
<[Link]>1.8</[Link]>
</properties>
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<!-- [Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- [Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>[Link]</version>
</dependency>
<!-- [Link] -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>maven-archiver</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>[Link]</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Step 8: Now open the [Link] file and Run the file as Java
Application.
package [Link];
import [Link];
import [Link];
@SpringBootApplication
public class RestfulWebServicesApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
}
It does not perform any service but ensures that the application is running properly.
Output
Step 2: Whenever we create a web service, we need to define two things Get method and the
URI. Now create the helloWorld() method which returns the string "Hello World." If we want to
tell the spring MVC that it is going to handle the REST request, we have to add @RestController
annotation. Now it becomes a rest controller which can handle the Rest request.
The next thing we have to do is create a mapping for the method. Add @RequestMapping
annotation just above the helloWorld() method. The HelloWorldController looks like the
following:
package [Link];
import [Link];
import [Link];
import [Link];
//Controller
@RestController
public class HelloWorldController
{
//using get method and hello-world as URI
@RequestMapping(method=[Link], path="/hello-world")
public String helloWorld()
{
return "Hello World";
}
}
We can also improve the above code by using the @GetMapping annotation instead of
@RequestMapping. Here the method specification is not required.
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
//Controller
@RestController
public class HelloWorldController
{
//using get method and hello-world as URI
@GetMapping(path="/hello-world")
public String helloWorld()
{
return "Hello World";
}
}
Step 3: Run the RestfulWebServiceApplication. It displays the string Hello World on the browser.
ADVERTISEMENT
[Link]
package [Link];
import [Link];
import [Link];
//Controller
@RestController
public class HelloWorldController
{
//using get method and hello-world URI
@GetMapping(path="/hello-world")
public String helloWorld()
{
return "Hello World";
}
@GetMapping(path="/hello-world-bean")
public HelloWorldBean helloWorldBean()
{
return new HelloWorldBean("Hello World"); //constructor of HelloWorldBean
}
}
Step 2: Create a class HelloWorldBean.
Right-click -> Source -> Generate Getters and Setters -> check the box -> Ok
ADVERTISEMENT
[Link]
package [Link];
public class HelloWorldBean
{
public String message;
//constructor of HelloWorldBean
public HelloWorldBean(String message)
{
[Link]=message;
}
//generating getters and setters
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
[Link] = message;
}
@Override
//generate toString
public String toString()
{
return [Link] ("HelloWorldBean [message=%s]", message);
}
}
Step 5: Launch the HelloWorldController. The URL of the browser changes to
localhost:8080/hello-world-bean.
It returns the message "Hello World" in JSON format.
{
message: "Hello World"
}
Click here to download Initializing a RESTful Web Service with Spring Boot project
Click here to download Enhacing the Hello World Service to Return a Bean project
← prevnext →
=============================================================
Spring Boot Auto Configuration and Dispatcher Servlet
================================================================In this
section, we will see the background functionality of the application:
ADVERTISEMENT
ADVERTISEMENT
Spring Boot automatically configures a spring application based on dependencies present or not
present in the classpath as a jar, beans, properties, etc.
It makes development easier and faster as there is no need to define certain beans that are
included in the auto-configuration classes.
A typical MVC database driven Spring MVC application requires a lot of configuration such as
dispatcher servlet, a view resolver, Jackson, data source, transaction manager, among many
others.
Spring Boot auto-configures a Dispatcher Servlet if Spring MVC jar is on the classpath.
Auto-configures the Jackson if Jackson jar is on the classpath.
Auto-configures a Data Source if Hibernate jar is on the classpath.
Auto-configuration can be enabled by adding @SpringBootApplication or
@EnableAutoConfiguration annotation in startup class. It indicates that it is a spring context file.
It enables something called auto-configuration.
It enable something called components scan. It is the features of Spring where it will start
automatically scanning classes in the package and sub package for any bean file.
There is some example of auto configuration done by Spring Boot:
DispatcherServletAutoConfiguration
DataSourceAutoConfiguration
JacksonAutoConfiguration
ErrorMvcAutoConfiguration (#basicErrorController)
We can see the auto-configuration done by Spring Boot in the AUTO-CONFIGURATION
REPORT or CONDITIONS EVALUATION REPORT.
Classes can be excluded from auto-configuration by adding:
@SpringBootApplication (exclude={[Link],
[Link]})
Or add the following statement in the [Link] file.
[Link]=[Link]
Configuration
We exclude classes form the auto-configuration for faster startup and better performance of the
application.
-----------------------------------------------
CONDITIONS EVALUATION REPORT
-----------------------------------------------
Positive matches:
----------------------
ActiveMQAutoConfiguration matched:
- @ConditionalOnClass found required classes '[Link]',
'[Link]' (OnClassCondition)
- @ConditionalOnMissingBean (types: [Link]; SearchStrategy: all) did
not find any beans (OnBeanCondition)
------------------
------------------
------------------
Negative matches:
-------------------------
[Link]: Did not
match:
-@ConditionalOnClass did not find required classes
'[Link]','[Link]
Object' (OnClassCondition)
----------------
----------------
----------------
Exclusions:
---------------
None
Unconditional classes:
-----------------------------
[Link]
[Link]
There is a lot of information inside the report, so it is not possible to show all the detail. If we
scroll down the report and have a closure look at auto configuration log, we found
DispatcherServletAutoConfiguration matched.
ADVERTISEMENT
DispatcherServletAutoConfiguration matched:
-@ConditionalOnClass found required class
'[Link]' (OnClassCondition)
- found 'session' scope (OnWebApplicationCondition)
It is because, the dependency spring-boot-starter-web depends on spring-webmvc dependency.
Therefore we get the DispatcherServlet class in our classpath.
Dispatcher Servlet
In Spring MVC all incoming requests go through a single servlet is called Dispatcher Servlet
(front controller). The front controller is a design pattern in web application development. A
single servlet receives all the request and transfers them to all other components of the
application.
ErrorMvcAutoConfiguration matched:
-@ConditionalOnClass found required classes '[Link]',
'[Link]' (OnClassCondition)- found 'session' scope
(OnWebApplicatiossssnCondition)
It configures the basicErrorController, errorAttributes, ErrorMvcAutoConfiguration, and
DefaultErrorViewResolverConfiguration. It creates the default error page which is known as
Whitelabel Error Page.
HttpMessageConvertersAutoConfiguration matched:
-@ConditionalOnClass found required class
'[Link]' (OnClassCondition)
----------------
-----------------
JacksonAutoConfiguration.Jackson2ObjectMapperBuilderCustomizerConfiguration matched: -
@ConditionalOnClass found required class
'[Link].Jackson2ObjectMapperBuilder'(OnClassCondition)
It initializes the Jackson bean and the message converter. The Jackson2ObjectMapper does the
conversion from bean to JSON and JSON to bean.
ADVERTISEMENT
ADVERTISEMENT
Click here to download Quick Review of Spring Boot Auto Configuration and Dispatcher Servlet
project
================================================================
Enhancing the Hello World Service with a Path Variable
================================================================
Enhancing the Hello World Service with a Path Variable
The @PathVariable annotation is used to extract the value from the URI. It is most suitable for
the RESTful web service where the URL contains some value. Spring MVC allows us to use
multiple @PathVariable annotations in the same method. A path variable is a critical part of
creating rest resources.
Step 1: Open the [Link] file and add another helloWorldBean() service.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Configuration
//Controller
@RestController
public class HelloWorldController
{
//using get method and hello-world URI
@GetMapping(path="/hello-world")
public String helloWorld()
{
return "Hello World";
}
@GetMapping(path="/hello-world-bean")
//method- which returns "Hello World"
public HelloWorldBean helloWorldBean()
{
return new HelloWorldBean("Hello World");//constructor of HelloWorldBean
}
//passing a path variable
@GetMapping(path="/hello-world/path-variable/{name}")
public HelloWorldBean helloWorldPathVariable(@PathVariable String name)
{
return new HelloWorldBean([Link]("Hello World, %s", name)); //%s replace the name
}
}
Whatever value we will pass to the path variable is picked up by the controller and returned to
the response.
Step 3: Run the [Link] file. We get the following response on the browser.
Enhancing the Hello World Service with a Path Variable
Let's change the path variable once again:
[Link]
ADVERTISEMENT
Right click on the package user -> New -> Class -> Provide Name -> Finish. Here, we have
provided class name User.
Right click on the file -> Source -> Generate Getters and Setters... ->Select All -> Generate.
ADVERTISEMENT
Right click on the file -> Source -> Generate toString... ->Select All -> Generate.
Right click on the file -> Source -> Generate Constructor using Fields... -> Generate.
ADVERTISEMENT
[Link]
package [Link];
import [Link];
public class User
{
public User(Integer id, String name, Date dob)
{
super();
[Link] = id;
[Link] = name;
[Link] = dob;
}
private Integer id;
private String name;
private Date dob;
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public Date getDob()
{
return dob;
}
public void setDob(Date dob)
{
[Link] = dob;
}
@Override
public String toString()
{
//return "User [id=" + id + ", name=" + name + ", dob=" + dob + "]";
return [Link]("User [id=%s, name=%s, dob=%s]", id, name, dob);
}
}
Before moving to the next step first move [Link] and [Link] in
the package [Link].
ADVERTISEMENT
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Component
public class UserDaoService
{
public static int usersCount=5;
//creating an instance of ArrayList
private static List<User> users=new ArrayList<>();
//static block
static
{
//adding users to the list
[Link](new User(1, "John", new Date()));
[Link](new User(2, "Robert", new Date()));
[Link](new User(3, "Adam", new Date()));
[Link](new User(4, "Andrew", new Date()));
[Link](new User(5, "Jack", new Date()));
}
//method that retrieve all users from the list
public List<User> findAll()
{
return users;
}
//method that add the user in the list
public User save(User user)
{
if([Link]()==null)
{
//increments the user id
[Link](++usersCount);
}
[Link](user);
return user;
}
//method that find a particular user from the list
public User findOne(int id)
{
for(User user:users)
{
if([Link]()==id)
return user;
}
return null;
}
}
Implementing Get Methods for User Resource
Step 8: Now create a user controller class with name UserResource.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
}
Step 9: Run the application and type the localhost:8080/users in the address bar of the browser.
It returns the users list in JSON format.
Enhancing the Hello World Service with a Path Variable
If the date is displaying in the default timestamp format as:
ADVERTISEMENT
ADVERTISEMENT
"dob": "1500370250075"
Open the [Link] file. Remove the debug configuration and add the following
configuration:
[Link]-dates-as-timestamps=false
The above statement telling the Jackson framework that when serializing don't treat the date as
a timestamp.
Step 10: If we want to display a specific user detail on the browser, add the mapping "/user/{id}"
and create a method retriveUser() in the UserResource.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
//retrieves a specific user detail
@GetMapping("/users/{id}")
public User retriveUser(@PathVariable int id)
{
return [Link](id);
}
}
Step 11: Run the application and type localhost:8080/users/{id} in the browser. It returns the
detail of the specific user id which we are passing in the path variable.
ADVERTISEMENT
ADVERTISEMENT
In the following image, we have retrieved the detail of the user having id 4.
Click here to download Enhancing the Hello World Service with a Path Variable project
Click here to download Implementing Get Method for User Resource-Display All Users project
===============================================================
Implementing the POST Method to create User Resource
==============================================================
In the previous few steps, we have created simple RESTful services. In this section, we will use
the POST method to post the user resource for the specific URI "/users."
@RequestBody
The @RequestBody annotation maps body of the web request to the method parameter. The
body of the request is passed through an HttpMessageConverter. It resolves the method
argument depending on the content type of the request. Optionally, automatic validation can be
applied by annotating the argument with @Valid.
In the following example, when we pass the @RequestBody annotation in the createUser()
method, it maps to the user parameter.
@PathMapping
The @PathMapping annotation is the specialized version of the @RequestMapping annotation
which acts as a shortcut for @RequestMapping(method=RequestMethod=POST).
@PostMapping method handles the Http POST requests matched with the specified URI.
Let's create a user resource and post that resource through the POST method.
[Link]
ADVERTISEMENT
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
//retrieves a specific user detail
@GetMapping("/users/{id}")
public User retriveUser(@PathVariable int id)
{
return [Link](id);
}
//method that posts a new user detail
@PostMapping("/users")
public void createUser(@RequestBody User user)
{
User sevedUser=[Link](user);
}
}
When we refresh the page it returns the get request. But we need to send POST request. We
can send POST request through REST client. REST client is a client that is designed to use a
service (RESTful) from a server.
Step 5: Launch the Postman and Signup. Create a user name. Here we have created user
name javatpoint and clicked on Submit button. Consider the below image:
ADVERTISEMENT
ADVERTISEMENT
ResponseEntity Class
The ResponseEntity is a class which extends HttpEntity and HttpStatus class. It is defined in
[Link].
It is used in RestTemplate and @Controller methods.
It is used as parameter in getForEntity() and exchange() method.
It is also used in Spring MVC, as a parameter in a @Controller method.
created() method of RequestEntity Class
The created() method is the static method of RequestEntity class. It creates a new builder with a
CREATED status and a location header set to the given URI.
ADVERTISEMENT
ADVERTISEMENT
Syntax
ADVERTISEMENT
ADVERTISEMENT
All Http status codes are Enum constant, which is defined in the HttpStatus class.
ServletUriComponentsBuilder
The ServletUriComponentsBuilder is a class which is defined in
[Link]. It extends
UriComponentsBuilder class. It has additional static factory methods to create a link based on
the current HttpServletRequest.
fromCurrentRequest() method
It is similar to fromRequest(HttpServletRequest) method except the request is obtained through
RequestContextHolder.
path() method
The path() is the method of UriComponentsBuilder class. It appends the given path to the
existing path of this builder. The given path may contain URI template variable.
Syntax
buildAndExpand() method
It builds UriComponents instance and replaces URI template variables with the values obtained
from an array. It is the shortcut method which combines calls to build() and then
[Link](Object... uriVariableValues).
Syntax
build() method
It builds UriComponents instance from the various components contained in the builder.
ADVERTISEMENT
Syntax
Let's see how to return the status of the created resource and how to set URI of the created
resource in the response.
Step 1: Create a method that creates a user resource and returns the ResponseEntity.
[Link]
ADVERTISEMENT
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
//retrieves a specific user detail
@GetMapping("/users/{id}")
public User retriveUser(@PathVariable int id)
{
return [Link](id);
}
//method that posts a new user detail and returns the status of HTTP and location of the user
resource
@PostMapping("/users")
public ResponseEntity<Object> createUser(@RequestBody User user)
{
User sevedUser=[Link](user);
URI
location=[Link]().path("/{id}").buildAndExpand(seve
[Link]()).toUri();
return [Link](location).build();
}
}
Step 2: Now open REST client Postman and create a POST request.
Step 4: Click on the Body tab and change the user name to James.
Step 5: Ensure that you have selected JSON (application/json) media type.
On the right-hand side of the window, we can see the Status: 201 Created. It means resource
has been properly created.
Step 6: Now click on the Headers tab to see the location. Location is the URI of the created
resource. It shows the location of the created user James that is "/users/6".
Click here to download Implementing POST Method to Create User Resource project
Click here to download Enhancing POST Method to Return Correct HTTP Code and Status
Location project
← prevnext →
================================================================
Implementing Exception Handling- 404 Resource Not Found
================================================================
n the previous section, we had returned the proper response status of CREATED when we
created the resource. In this section, we will discuss what should be the response when a user
resource does not exist.
Step 1: Open Rest client Postman and select the Get method.
Step 2: Click on the History tab and choose the Get request.
Step 3: Type the URI [Link] The user id should not exist.
@GetMapping("/users/{id}")
public User retriveUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
return user;
}
Step 3: Create UserNotFoundException class.
Right-click on the file -> Source -> Generate Constructors from Superclass... -> check the
RuntimeException(String) -> Generate.
package [Link];
public class UserNotFoundException extends RuntimeException
{
public UserNotFoundException(String message)
{
super(message);
}
}
Step 5: Open the Rest Client Postman and generate a Get response as we have done before. It
shows the Status: 500 Internal Server Error.
package [Link];
import [Link];
import [Link];
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException
{
public UserNotFoundException(String message)
{
super(message);
}
}
Step 6: Again move to Postman and generate a Get request.
If we have a big organization and each of the services returns the exception messages in a
different way, so it is not good. It would be good if we define a standard exception structure
which is followed by across all the RESTful Services.
================================================================
Step 2: Create a class with the name ExceptionResponse in the above package.
Step 3: At the basic level, there are three crucial things for the exception structure: timestamp,
message, and detail. Define these three fields.
Once the structure is defined, we can define Java implementation for it. Whenever an exception
occurs, we would return a response in the specific format. The structure is the most important
part and must have to be language independent.
Step 10: Override the ResponseEntityMethod method. Rename the method name as
handleAllExceptions().
Step 12: Create a ResponseEntity object and pass the exception response and Http status as
arguments.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import
[Link];
import [Link];
//defining exception handling for all the exceptions
@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends
ResponseEntityExceptionHandler
{
@ExceptionHandler([Link])
//override method of ResponseEntityExceptionHandler class
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request)
{
//creating exception response structure
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(),
[Link](), [Link](false));
//returning exception structure and specific status
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Step 13: Open rest client Postman and send a Get request. We get the Status: 500 Internal
Server Error and exception structure which we have defined.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import
[Link];
import [Link];
import [Link];
//defining exception handling for all the exceptions
@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends
ResponseEntityExceptionHandler
{
@ExceptionHandler([Link])
//override method of ResponseEntityExceptionHandler class
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request)
{
//creating exception response structure
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(),
[Link](), [Link](false));
//returning exception structure and Internal Server status
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler([Link])
//override method of ResponseEntityExceptionHandler class
public final ResponseEntity<Object> handleUserNotFoundExceptions(UserNotFoundException
ex, WebRequest request)
{
//creating exception response structure
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(),
[Link](), [Link](false));
//returning exception structure and Not Found status
return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
}
}
Again move to Postman and send a Get request. We get the Status: 404 Not Found with the
defined exception structure.
Click here to download Implementing Generic Exception Handing For All Users project
================================================================
Implementing DELETE Method to Delete a User Resource
===============================================================
In this section, we will implement a delete method to delete a user resource.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Component
public class UserDaoService
{
public static int usersCount=5;
//creating an instance of ArrayList
private static List<User> users=new ArrayList<>();
//static block
static
{
//adding users to the list
[Link](new User(1, "John", new Date()));
[Link](new User(2, "Robert", new Date()));
[Link](new User(3, "Adam", new Date()));
[Link](new User(4, "Andrew", new Date()));
[Link](new User(5, "Jack", new Date()));
}
//method that retrieve all users from the list
public List<User> findAll()
{
return users;
}
//method that adds a user in the list
public User save(User user)
{
if([Link]()==null)
{
[Link](++usersCount);
}
[Link](user);
return user;
}
//method that find a particular user from the list
public User findOne(int id)
{
for(User user:users)
{
if([Link]()==id)
return user;
}
return null;
}
//method that delete a user resource
public User deleteById(int id)
{
Iterator<User> iterator = [Link]();
while([Link]())
{
User user=[Link]();
if([Link]()==id)
{
[Link]();
return user; //returns the deleted resource back
}
}
return null;
}
}
Step 3: Open the [Link] file and create a delete mapping to delete a user resource.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
//retrieves a specific user detail
@GetMapping("/users/{id}")
public User retriveUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
return user;
}
//method that delete a user resource
//if the user deleted successfully it returns status 200 OK otherwise 404 Not Found
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
}
//method that posts a new user detail and returns the status of the user resource
@PostMapping("/users")
public ResponseEntity<Object> createUser(@RequestBody User user)
{
User sevedUser=[Link](user);
URI
location=[Link]().path("/{id}").buildAndExpand(seve
[Link]()).toUri();
return [Link](location).build();
}
}
Step 4: Open Postman, select DELETE request, and specify the user id which you want to
delete. Now click on the Send button.
Click here to download Implementing DELETE Method to Delete a User Resource project
================================================================
Implementing Validations for RESTful Services
===============================================================
Implementing Validations for RESTful Services
The validation is a common requirement in all the services. We will discuss Java Validation API
to add validation in our beans file. When we get a request to create a user, we should validate
its content. If it is invalid, we should return a proper response.
Step 2: Add @Valid annotation. It is a Javax validation API. Its default classpath is
spring-boot-starter-web.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
//retrieves a specific user detail
@GetMapping("/users/{id}")
public User retriveUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
return user;
}
//method that delete a user resource
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
}
//method that posts a new user detail and returns the status of the user resource
@PostMapping("/users")
public ResponseEntity<Object> createUser(@Valid @RequestBody User user)
{
User sevedUser=[Link](user);
URI
location=[Link]().path("/{id}").buildAndExpand(seve
[Link]()).toUri();
return [Link](location).build();
}
}
Now we will add validations in User class on name and date of birth. Let suppose that name
should have at least five characters and date of birth should be in past not in present.
Step 3: Open the [Link] file.
[Link]
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
public class User
{
private Integer id;
@Size(min=5)
private String name;
@Past
private Date dob;
//default constructor
protected User()
{
}
public User(Integer id, String name, Date dob)
{
super();
[Link] = id;
[Link] = name;
[Link] = dob;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public Date getDob()
{
return dob;
}
public void setDob(Date dob)
{
[Link] = dob;
}
@Override
public String toString()
{
//return "User [id=" + id + ", name=" + name + ", dob=" + dob + "]";
return [Link]("User [id=%s, name=%s, dob=%s]", id, name, dob);
}
}
Step 5: Open the Rest client Postman and send a POST request with new user name Tony k. It
returns Status: 201 Created.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import
[Link];
import [Link];
import [Link];
//defining exception handling for all the exceptions
@ControllerAdvice
@RestController
public class CustomizedResponseEntityExceptionHandler extends
ResponseEntityExceptionHandler
{
@ExceptionHandler([Link])
//override method of ResponseEntityExceptionHandler class
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request)
{
//creating exception response structure
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(),
[Link](), [Link](false));
//returning exception structure and specific status
return new ResponseEntity(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler([Link])
//override method of ResponseEntityExceptionHandler class
public final ResponseEntity<Object> handleUserNotFoundExceptions(UserNotFoundException
ex, WebRequest request)
{
//creating exception response structure
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(),
[Link](), [Link](false));
//returning exception structure and specific status
return new ResponseEntity(exceptionResponse, HttpStatus.NOT_FOUND);
}
@Override
protected ResponseEntity<Object>
handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatus status, WebRequest request)
{
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(),
[Link](), [Link]().toString());
//returning exception structure and specific status
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
}
}
Step 8: Now, we send a POST request through Postman. It returns the exception structure with
message Validation failed for argument and other details.
@Override
protected ResponseEntity<Object>
handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatus status, WebRequest request)
{
ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), "Validation
Failed", [Link]().toString());
//returning exception structure and specific status
return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
}
Step 9: Again send a POST request. It returns the message which we have customized.
Step 10: Open [Link] file and add an attribute message="Name should have at least 5
characters" in @Size annotation.
===============================================================
Implementing HATEOAS for RESTful Services
================================================================
Implementing HATEOAS for RESTful Services
HATEOAS
HATEOAS acronyms for Hypermedia as the Engine of Application State. The term hypermedia
refers to content that contains a link to other forms of media like images, movies, and text. It is a
component of the REST application that distinguishes it from other network architecture. Using
HATEOAS, a client interacts with a network application, whose application server provides
information dynamically through Hypermedia.
Spring-HATEOAS
Spring-HATEOAS is the library of APIs. We can use these APIs for creating REST
representations that follow the HATEOAS principle while working with Spring MVC.
In the Spring HATEOAS project, we do not require Servlet Context and concatenate the path
variable to the base URI. Instead of this, Spring HATEOAS offers three abstractions for creating
the URI: ContrrollerLinkBuilder, Link, and Resource Support. We can use these abstractions to
create metadata, which associates with the resource representation.
Features
ADVERTISEMENT
<dependency>d
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
Step 2: Open [Link] and copy the retrieveUser() method.
Add a link to retrieve all users by using the ControllerLinkBuilder class. It enables us to create a
link from methods.
Import the ControllerLinkBuilder.
import static [Link].
Use the method linkTo() of ControllerLinkBuilder class. It creates a new ControllerLinkBuilder
with a base of mapping annotated to the given controller class.
ControllerLinkBuilder linkTo=linkTo(methodOn([Link]().retrieveAllUsers());
methodOn() is a wrapper for [Link](class, Object) to be available in
case you work with the static import of ControllerLinkBuilder.
Add this link to the resource with the name which we want to use inside the HATEOAS.
[Link]([Link]("all-users"));
withRel(String rel) is the method that creates the link built by the current builder instance with
the given rel. The parameter rel must not be null.
[Link]
package [Link];
import static [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserResource
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
@GetMapping("/users/{id}")
public Resource<User> retriveUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
//"all-users", SERVER_PATH + "/users"
//retrieveAllUsers
Resource<User> resource=new Resource<User>(user); //constructor of Resource class
//add link to retrieve all the users
ControllerLinkBuilder linkTo=linkTo(methodOn([Link]()).retriveAllUsers());
[Link]([Link]("all-users"));
return resource;
}
//method that delete a user resource
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
}
//method that posts a new user detail and returns the status of the user resource
@PostMapping("/users")
public ResponseEntity<Object> createUser(@Valid @RequestBody User user)
{
User sevedUser=[Link](user);
URI
location=[Link]().path("/{id}").buildAndExpand(seve
[Link]()).toUri();
return [Link](location).build();
}
}
Step 4: Open the REST client Postman and send a GET request.
================================================================
Internationalization of RESTful Services
================================================================
Internationalization is the process of designing web applications or services in such a way that it
can provide support for various countries, various languages automatically without making the
changes in the application. It is also known as I18N because the word internationalization has
total 18 characters starting from I to N.
Java provides the foundation for internationalization for desktop and server applications. There
are following important internationalized areas of functionality.
ADVERTISEMENT
Text Representation: Java is based on the Unicode character set, and several libraries
implement the Unicode standard.
Locale identification and localization: Locale in Java are identifiers that can be used to request
locale-specific behavior in different areas of functionality. Localization is supported by
ResourceBundle class. The class provides access to local specific objects, including strings.
Date and time handling: Java provides various calendars. It supports conversion to and from
calendar independent Date objects. Java supports all the time zones in the world.
Text processing: It includes character analysis, case mapping, string comparison, breaking text
into words, formatting numbers, dates, and time values into strings or parsing them back from
strings. Most of these functions are locale-dependent.
Character encoding: It supports converting text between Unicode and other character encodings
when reading incoming text from the streams or writing outgoing text to the streams.
We need to configure two things to make the service internationalized.
LocaleResolver
ResourceBundleMessageSource
Default Locale is [Link]. If somebody does not specify the location, it returns the default
locale. We also need to customize the ResourceBundle. It has a list of properties that are to be
internationalized. We will store the properties in ResourceBundle.
ResourceBundleMessageSource is a Spring MVC concept for handling properties. After that,
we will use MessageSource, and a header called Accept-Language.
@Bean
public LocaleResolver localeResolver()
{
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
[Link]([Link]);
return localeResolver;
}
Note: Import import [Link] package while importing
LocaleResolver.
Step 3: Now, we will store properties in a specific file called [Link].
Right-click on src/main/resources folder -> New -> File -> Provide the file name:
[Link]. It contains the default locale message.
[Link]
[Link]=Good Morning
Step 4: Create another property file with the name messages_fr.properties for French locale. It
contains a message for the French locale.
messages_fr.properties
[Link]=Bonjour
Step 5: Read properties and customize them based on the input accept header. Open the
[Link] and configure another Bean for ResourceBundle.
//configuring ResourceBundle
@Bean
public ResourceBundleMessageSource bundleMessageSource()
{
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
[Link]("messages");
return messageSource;
}
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@SpringBootApplication
public class RestfulWebServicesApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
//configuring default locale
@Bean
public LocaleResolver localeResolver()
{
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
[Link]([Link]);
return localeResolver;
}
//configuring ResourceBundle
@Bean
public ResourceBundleMessageSource messageSource()
{
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
[Link]("messages");
return messageSource;
}
}
Step 6: Update the service to use these sources. Open the [Link] and
autowired the MessageSource.
@Autowired
private MessageSource messageSource;
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Configuration
//Controller
@RestController
public class HelloWorldController
{
@Autowired
private MessageSource messageSource;
//using get method and hello-world URI
@GetMapping(path="/hello-world")
public String helloWorld()
{
return "Hello World";
}
@GetMapping(path="/hello-world-bean")
//method- which returns "Hello World"
public HelloWorldBean helloWorldBean()
{
return new HelloWorldBean("Hello World");//constructor of HelloWorldBean
}
//passing a path variable
//hello-world/path-variable/javatpoint
@GetMapping(path="/hello-world/path-variable/{name}")
public HelloWorldBean helloWorldPathVariable(@PathVariable String name)
{
return new HelloWorldBean([Link]("Hello World, %s",name)); //%s replace the name
}
//internationalization
@GetMapping(path="/hello-world-internationalized")
public String helloWorldInternationalized(@RequestHeader(name="Accept-Language",
required=false) Locale locale)
{
return [Link]("[Link]", null, locale);
}
}
Step 7: Open the REST client Postman and perform the following changes:
Again, change the RequestHeader fr to other RequestHeader, say nl. It returns the default
locale (US) message Good Morning.
messages_nl.properties
[Link]=Goede Morgen
Again send a GET request that returns the message, Goede Morgen.
Step 1: Open the [Link] and change the return type of the
helloWorldInternationalized() method.
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Configuration
//Controller
@RestController
public class HelloWorldController
{
@Autowired
private MessageSource messageSource;
//using get method and hello-world URI
@GetMapping(path="/hello-world")
public String helloWorld()
{
return "Hello World";
}
@GetMapping(path="/hello-world-bean")
//method- which returns "Hello World"
public HelloWorldBean helloWorldBean()
{
return new HelloWorldBean("Hello World");//constructor of HelloWorldBean
}
//passing a path variable
//hello-world/path-variable/javatpoint
@GetMapping(path="/hello-world/path-variable/{name}")
public HelloWorldBean helloWorldPathVariable(@PathVariable String name)
{
return new HelloWorldBean([Link]("Hello World, %s",name)); //%s replace the name
}
//internationalization
@GetMapping(path="/hello-world-internationalized")
public String helloWorldInternationalized(@RequestHeader(name="Accept-Language",
required=false) Locale locale)
{
return [Link]("[Link]", null,
[Link]());
}
}
Step 2: Open [Link] and change SessionLocaleResolver to
AcceptHeaderLocaleResolver. LocaleResolver implementation uses the primary locale specified
in the "accept-language" header of the HTTP request (locale send by the client browser).
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@SpringBootApplication
public class RestfulWebServicesApplication
{
public static void main(String[] args)
{
[Link]([Link], args);
}
//configuring default locale
@Bean
public LocaleResolver localeResolver()
{
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
[Link]([Link]);
return localeResolver;
}
//configuring ResourceBundle
@Bean
public ResourceBundleMessageSource messageSource()
{
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
[Link]("messages");
return messageSource;
}
}
The advantage of AcceptHeaderLocaleResolver is that we do not require to configure request
header as a parameter in every controller method.
Step 3: Open the REST client Postman and send a GET request by setting the key as
Accept-Language and value as fr. It returns the message Bonjour.
Now uncheck the RequestHeader, change the value fr to en. It returns the default locale (US)
message Good Morning.
Step 5: Open [Link] file and configure the message basename instead of
creating a separate bean in [Link].
[Link]
[Link]=info
[Link]=messages
Step 6: Repeat step 3.
=================================================================
Content Negotiation Implementing Support for XML
===============================================================
Content Negotiation
A resource can have many representations, mostly because there may be multiple clients
expecting different representations.
Content negotiation is the process of selecting the best representation for a given response
when there are multiple representations available. It is a part of HTTP that makes it possible to
serve different versions of a document at the same URI.
In web API, content negotiation is performed at the server side to determine the media type
formatted to be used based on return the response for an incoming request from the client-side.
Content negotiation is centered on the media type and media type formatter.
An agent makes the selection of representation for a response, is called agent-driven content
negotiation.
So, most of RSET API implementations rely on agent-driven content negotiations. Agent driven
content negotiation rely on the usage of HTTP requests or resource URI patterns.
Content-Type: application/xml
HTTP header ACCEPT is used to determine what type of representation is desired at the
client-side. It contains a value as mentioned for Content-Type.
Accept: application/json
If there is no header is present in the request, the server can send preconfigured default
representation type.
[Link]
[Link] galaxy-s8/[Link]
The first request URI returns the XML response, and the second URI returns the JSON
response.
Defining Preferences
The preference is defined through the q parameter that has values between 0 and 1. If the client
does not specify the request header, it takes the implicit value, i.e., 1.
If the client is not sure about its desired representation and wants to give multiple values in the
accept header. For example:
All services we are created until now only work with JSON input and JSON output. If we want to
send a GET request by using HTTP header application/xml, it will return the status: 406 Not
Acceptable.
Step 3: Open the REST client Postman and send a GET request by specifying the HTTP header
Accept: application/xml.
ADVERTISEMENT
Under the Header tab add Content-Type: application/xml and Accept: application/xml.
Select the Body tab.
Enter the name and dob of the user in XML format.
Select the XML format XML (application/xml).
Click on the Send button.
Content Negotiation Implementing Support for XML
We get the Status: 201 Created. It means that user has been created successfully. Now it can
support both the formats XML and JSON.
================================================================
Configuring Auto Generation of Swagger Documentation
================================================================
Swagger
A Swagger is an open-source tool. It builds around the OpenAPI Specification that helps
developers to design, build, document, and consume RESTful APIs. It is the most popular API
documentation format for RESTful Web Services. It provides both JSON and UI support. JSON
can be used as a machine-readable format, and Swagger-UI is for visual display, which is easy
for humans to understand by just browsing the API documentation. The main Swagger tools
are:
ADVERTISEMENT
Available endpoints (/users) and operations on each endpoint (GET /users, POST /users).
Operation parameters for each operation.
Authentication methods.
Contact information, license, the term of use and other information
Let's generate Swagger documentation for our RESTful services.
<dependency>
<groupId>[Link]</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
Add another dependency springfox-swagger-ui
<dependency>
<groupId>[Link]</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
Now we need to configure Swagger.
Step 2: Create a class with the name [Link] and write the following code.
Docket: A builder that is intended to be the primary interface into the swagger-Spring MVC
Framework. Docket provides sensible defaults and convenience methods for configuration.
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link].EnableSwagger2;
@Configuration
//Enable Swagger
@EnableSwagger2
public class SwaggerConfig
{
//creating bean
@Bean
public Docket api()
{
//creating constructor of Docket class that accepts parameter DocumentationType
return new Docket(DocumentationType.SWAGGER_2);
}
}
Step 3: Run the application.
It shows the complete documentation in JSON format, as shown in the following image. It is not
much easy to read and understand. Swagger has provided it to be used in other systems like
API management tools that offer functionality like API gateways, API caching, API
documentation, etc.
================================================================
Introduction to Swagger Documentation Format
================================================================
In this section, we look at the generated documentation in detail. Swagger is a specification for
documenting REST API. It specifies the format (URL, method, and representation) to describe
REST web services. It also provides tools to generate/compute the documentation from the
application code.
We're going to see what is inside the Swagger documentation. When we have a close look at
the documentation of the web API, we see some important elements in the starting of the
documentation, as shown in the following image.
ADVERTISEMENT
"info":{"description":"Api Documentation","version":"1.0","title":"Api
Documentation","termsOfService":"urn:tos","contact":{},"license":{"name":"Apache
2.0","url":"[Link]
description: It contains the high level information of API.
version: It shows the version of API which we are exposing.
title: It specifies the title of API.
termOfService: It specifies the term of service, if any.
contact: It specifies the contact detail of a person, if any.
license: It specifies the default license Apache 2.0.
Let's expand the path element. It contains all the path that we are exposing.
paths: {
/error: {-}
/hello-world: {-}
/hello-world-bean: {-}
/hello-world-internationalized: {-}
/hello-world/path-variable/{name}: {-}
/users: {-}
/users/{id}: {-}
},
The two most important resources are "/users" and "/users/{id}". These resources exposes the
group of users. Let's expand these two resources one by one.
"/users":{"get":{"tags":["user-resource"],"summary":"retriveAllUsers","operationId":"retriveAllUser
sUsingGET","produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"type":"array","it
ems":{"$ref":"#/definitions/User"}}},"401":{"description":"Unauthorized"},"403":{"description":"For
bidden"},"404":{"description":"Not
Found"}},"deprecated":false},"post":{"tags":["user-resource"],"summary":"createUser","operationI
d":"createUserUsingPOST","consumes":["application/json"],"produces":["*/*"],"parameters":[{"in":
"body","name":"user","description":"user","required":true,"schema":{"$ref":"#/definitions/User"}}],"
responses":{"200":{"description":"OK","schema":{"type":"object"}},"201":{"description":"Created"},
"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not
Found"}},"deprecated":false}},
The above resource contains the two operations get and post that can be performed. We can
use get operation to retrieve all the users and post operation to post a user.
Inside the get operation, we get all the response status present there. Response status 200
denotes the successful creation of a user, 401 denotes the unauthorized access of resources,
404 denotes not found, and 403 denotes the forbidden. When we look at the status 200, there is
a schema definition. Schema definition shows that we are sending an array of the user as a
response. An array of the user is present in the definitions. Similarly, we can also expand the
definitions tag to see the definition of the user.
In addition to a POST request, we have parameters that send as part of the body of the request.
We accept an input type user as the body of the request.
"/users/{id}":{"get":{"tags":["user-resource"],"summary":"retriveUser","operationId":"retriveUserUs
ingGET","produces":["*/*"],"parameters":[{"name":"id","in":"path","description":"id","required":true
,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/defi
nitions/Resource«User»"}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}
,"404":{"description":"Not
Found"}},"deprecated":false},"delete":{"tags":["user-resource"],"summary":"deleteUser","operatio
nId":"deleteUserUsingDELETE","produces":["*/*"],"parameters":[{"name":"id","in":"path","descript
ion":"id","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK"},
"204":{"description":"No
Content"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"}},"deprecated":fal
se}}},
The /users/{id} resource allows two operations get and delete. Inside the delete method, there is
a parameter called id. This id we are accepting in the path while in the post request, we put
content as a part of the body of the request.
Definition defines different kinds of objects that are being used. These definitions are used in the
different operations exposed by each resource. When we perform get operation on /users, it
returns a list of users. This resource of the user sending back to get the operation of the
resource /user/{id} and the resource of the user contains the additional links. The definition of
links is also present in the resource of user type.
Links contains a rel and href. A rel is all -users, and href is the link to a particular resource.
Step 4: Copy the two constants DEFAULT _CONTACT and DEFAULT from the class. or copy
the following code and paste it in the [Link]. Rename the constant DEFAULT to
DEFAULT_API_INFO.
public static final ApiInfo DEFAULT_API_INFO = new ApiInfo("RESTful API Demo", "Api
Documentation Demo", "1.0", "urn:tos",
DEFAULT_CONTACT, "Apache 2.0", "[Link] new
ArrayList<VendorExtension>());
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link].EnableSwagger2;
//Configuration
@Configuration
//Enable Swagger
@EnableSwagger2
public class SwaggerConfig
{
//configuring the contact detail
public static final Contact DEFAULT_CONTACT = new Contact("Andrew",
"[Link] "javatpoint");
//configuring DEFAULT_API_INFO
public static final ApiInfo DEFAULT_API_INFO = new ApiInfo("RESTful API Demo", "Api
Documentation Demo", "1.0", "urn:tos",
DEFAULT_CONTACT, "Apache 2.0", "[Link] new
ArrayList<VendorExtension>());
//creating bean
@Bean
public Docket api()
{
ApiInfo apiInfo;
return new Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO);
}
}
Step 7: Restart the application.
Step 8: Open the browser and type the URI [Link] It shows the
updated contact detail and API info in the documentation.
ADVERTISEMENT
ADVERTISEMENT
return new
Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO).produces(DEFAULT_
PRODUCES_AND_CONSUMES).consumes(DEFAULT_PRODUCES_AND_CONSUMES);
Step 2: Create a constant DEFAULT_PRODUCES_AND_CONSUMES.
private static final Set<String> DEFAULT_PRODUCES_AND_CONSUMES = null;
Step 3: Create a HashSet and add two values application/json and application/xml.
Note that we cannot directly pass the values to the HashSet. So we have passed a List to the
constructor of HashSet.
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link].EnableSwagger2;
//Configuration
@Configuration
//Enable Swagger
@EnableSwagger2
public class SwaggerConfig
{
//configuring the contact detail
public static final Contact DEFAULT_CONTACT = new Contact("Andrew",
"[Link] "javatpoint");
//configuring DEFAULT_API_INFO
public static final ApiInfo DEFAULT_API_INFO = new ApiInfo("RESTful API Demo", "Api
Documentation Demo", "1.0", "urn:tos",
DEFAULT_CONTACT, "Apache 2.0", "[Link] new
ArrayList<VendorExtension>());
//two format which we want to produce and consume
private static final Set<String> DEFAULT_PRODUCES_AND_CONSUMES = new
HashSet<String>([Link]("application/json","appication/xml"));
//creating bean
@Bean
public Docket api()
{
ApiInfo apiInfo;
return new
Docket(DocumentationType.SWAGGER_2).apiInfo(DEFAULT_API_INFO).produces(DEFAULT_
PRODUCES_AND_CONSUMES).consumes(DEFAULT_PRODUCES_AND_CONSUMES);
}
}
Step 4: Open the browser and type the URI [Link]
We can add more description about user model such as date of birth must be in the past, the
name must have at least five characters, etc. Let's add more description in the User model.
ADVERTISEMENT
Step 1: Open the [Link] and add @ApiModel annotation just above the class name. Add the
description about the User model.
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@ApiModel(description="All details about the user")
public class User
{
private Integer id;
@Size(min=5, message="Name should have atleast 5 characters")
@ApiModelProperty(notes="name should have atleast 5 characters")
private String name;
@Past
@ApiModelProperty(notes="Birth date should be in the past")
private Date dob;
//default constructor
protected User()
{
}
public User(Integer id, String name, Date dob)
{
super();
[Link] = id;
[Link] = name;
[Link] = dob;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public Date getDob()
{
return dob;
}
public void setDob(Date dob)
{
[Link] = dob;
}
@Override
public String toString()
{
//return "User [id=" + id + ", name=" + name + ", dob=" + dob + "]";
return [Link]("User [id=%s, name=%s, dob=%s]", id, name, dob);
}
}
Step 4: Restart the application.
ADVERTISEMENT
Step 5: Open the browser and type the URI [Link] If we look at the
description of the User model, the description which we have specified appears here.
Hence, the Swagger documentation is beneficial for the consumer of service. Swagger provides
a lot of annotations that can be used to enhance model, operations, and swagger
configurations.
================================================================
Monitoring APIs with Spring Boot Actuator
===============================================================
Spring Boot Actuator
Spring Boot provides the actuator to monitor and manage applications effectively. It is a tool that
has HTTP endpoints (the place where the resource lives). It is a sub-project of Spring Boot. It
adds several production grade services to our application with less effort.
If the performance of a service goes down or failure, we should know the reason as quickly as
possible. We need to build monitoring around the API, especially when we build microservices.
Spring Boot has great support to provide monitoring.
Spring Boot Starter Actuator: It provides a lot of monitoring facilities around your services.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Spring Data Rest HAL Browser: HAL makes our API exportable, and its documentation easily
discoverable from within the API itself.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-data-rest-hal-browser</artifactId>
</dependency>
Hypertext Application Language (HAL) is a simple language that gives a consistent and easy
way to hyperlink between resources in API. The spring boot starter actuator is actually in the
HAL format. HAL browser searches for APIs and identifies the links. It shows the link on the
screen so that we can easily browse through the API.
Start 3: Type the URL localhost:8080/actuator in the browser and hit the enter key. If it does not
work, use the URL localhost:8080/application.
ADVERTISEMENT
It launches the actuator that shows the three URLs: self, health, and info.
{"_links":{"self":{"href":"[Link]
calhost:8080/actuator/health","templated":false},"health-component":{"href":"[Link]
0/actuator/health/{component}","templated":true},"health-component-instance":{"href":"[Link]
lhost:8080/actuator/health/{component}/{instance}","templated":true},"info":{"href":"[Link]
st:8080/actuator/info","templated":false}}}
When we click on the health URL, it shows the health of the application. In the following image,
status up denotes that application is running.
ADVERTISEMENT
Type /actuator in the Explorer's text box and click on the Go button.
Filters are one of the important features provided by the JAX-RS framework. It is used in various
contexts. It may be applied on either request to a resource or the response from a resource, or
both.
Consider a scenario in which we do not want to show some class members in the response.
This process is called filtering. Jackson has two annotations that are used in filtering are:
@JsonIgnore and @JsonIgnoreProperties.
@JsonIgnore
It is a member or method level annotation. It expects that the properties to be excluded are
marked one by one. If we want to eliminate a member from the process of serialization and
deserialization, we can annotate the actual property or its setter or getter.
Let's create a filter that filters the response. We will not touch the user example, but instead of
this, we will create a new controller and bean to perform filtering.
Step 1: Create a Controller class with the name [Link] in the package
[Link].
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class FilteringController
{
@RequestMapping("/filtering")
public SomeBean retrieveSomeBean()
{
return new SomeBean("Amit", "9999999999","39000");
}
}
Step 3: Create a class with the name [Link]. Define three attributes name, phone, and
salary.
[Link]
package [Link];
import [Link];
public class SomeBean
{
private String name;
private String phone;
//JsonIgnore indicates that the annotated method or field is to be ignored
@JsonIgnore
private String salary;
//generating constructor
public SomeBean(String name, String phone, String salary)
{
super();
[Link] = name;
[Link] = phone;
[Link] = salary;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
[Link] = phone;
}
public String getSalary()
{
return salary;
}
public void setSalary(String salary)
{
[Link] = salary;
}
}
Step 6: Open the REST client Postman and send the GET request. It returns two fields: name
and phone. The field salary will not send with the response.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class FilteringController
{
//returning a single bean as response
@RequestMapping("/filtering")
public SomeBean retrieveSomeBean()
{
return new SomeBean("Amit", "9999999999","39000");
}
//returning a list of SomeBeans as response
@RequestMapping("/filtering-list")
public List<SomeBean> retrieveListOfSomeBeans()
{
return [Link](new SomeBean("Saurabh", "8888888888","20000"), new
SomeBean("Devesh", "1111111111","34000"));
}
}
Step 8: Send a GET request again with the URI [Link] that returns a list of
SomeBeans.
@JsonIgnoreProperties
@JsonIgnoreProperties is a class-level annotation. It ignores the logical properties in JSON
serialization and deserialization.
In the following [Link] file, we have specified the property name and phone, which we
want to ignore in the response. These two properties will take part in the JSON serialization and
deserialization.
ADVERTISEMENT
If the property salary is annotated with @JsonIgnore, then all the properties ignored in the
JSON serialization and deserialization.
[Link]
package [Link];
import [Link];
import [Link];
@JsonIgnoreProperties({"name", "phone"})
public class SomeBean
{
private String name;
private String phone;
//JsonIgnore indicates that the annotated method or field is to be ignored
@JsonIgnore
private String salary;
//generating constructor
public SomeBean(String name, String phone, String salary)
{
super();
[Link] = name;
[Link] = phone;
[Link] = salary;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
[Link] = phone;
}
public String getSalary()
{
return salary;
}
public void setSalary(String salary)
{
[Link] = salary;
}
}
When we fire a GET request, it returns an empty list because the properties name and phone
are specified in the @JsonIgnoreProperties and the property salary annotated with
@JsonIgnore. Hence it returns the empty list.
Suppose there are three fields: name, phone, and salary. We want to send two fields: name and
salary for the first service and name and phone for the second service.
But there is a limitation in dynamic filtering. We cannot configure the dynamic filtering directly in
the bean. We need to start configuring filtering, where we are retrieving the values. To
implement dynamic filtering, we use a class named MappingJacksonValue. If we look at the
class definition, we found the filter method definition there.
In the following example, we will send a name and salary for "/filtering" mapping.
[Link](filters);
Step 6: Instead of returning the someBean return mapping.
return mapping;
Step 7: We have returned mapping, so we are required to change the return type of the method
to MappingJacksonValue.
@RequestMapping("/filtering")
public MappingJacksonValue retrieveSomeBean()
{
SomeBean someBean=new SomeBean("Amit", "9999999999","39000");
//invoking static method filterOutAllExcept()
SimpleBeanPropertyFilter filter=[Link]("name", "salary");
//creating filter using FilterProvider class
FilterProvider filters=new SimpleFilterProvider().addFilter("SomeBeanFilter",filter);
//constructor of MappingJacksonValue class that has bean as constructor argument
MappingJacksonValue mapping = new MappingJacksonValue(someBean);
//configuring filters
[Link](filters);
return mapping;
}
Remember: The list of valid filters should be defined in the bean. If we don't do that it will return
all the fields.
Step 8: Open [Link] file and define a filter by using the annotation @JsonFilter. It is
used at class level. It defines a filter name which we filter out properties in JSON serialization.
@JsonFilter("SomeBeanFilter")
[Link]
package [Link];
import [Link];
@JsonFilter("SomeBeanFilter")
public class SomeBean
{
private String name;
private String phone;
//JsonIgnore indicates that the annotated method or field is to be ignored
//@JsonIgnore
private String salary;
//generating constructor
public SomeBean(String name, String phone, String salary)
{
super();
[Link] = name;
[Link] = phone;
[Link] = salary;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public String getPhone()
{
return phone;
}
public void setPhone(String phone)
{
[Link] = phone;
}
public String getSalary()
{
return salary;
}
public void setSalary(String salary)
{
[Link] = salary;
}
}
Let's implement the dynamic filtering in the second method. In this method we will return name
and phone field for "/filtering-list" mapping.
ADVERTISEMENT
Step 1: In this method, we first change the return type of the method to MappingJacksonValue.
@RequestMapping("/filtering-list")
public MappingJacksonValue retrieveListOfSomeBeans()
{
List<SomeBean> list=[Link](new SomeBean("Saurabh", "8888888888","20000"), new
SomeBean("Devesh", "1111111111","34000"));
//invoking static method filterOutAllExcept()
SimpleBeanPropertyFilter filter=[Link]("name", "phone");
FilterProvider filters=new SimpleFilterProvider().addFilter("SomeBeanFilter",filter);
//constructor of MappingJacksonValue class that has list as constructor argument
MappingJacksonValue mapping = new MappingJacksonValue(list);
//configuring filter
[Link](filters);
return mapping;
}
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class FilteringController
{
//returning a single bean as response
//values to send name and salary
@RequestMapping("/filtering")
public MappingJacksonValue retrieveSomeBean()
{
SomeBean someBean=new SomeBean("Amit", "9999999999","39000");
//invoking static method filterOutAllExcept()
SimpleBeanPropertyFilter filter=[Link]("name", "salary");
//creating filter using FilterProvider class
FilterProvider filters=new SimpleFilterProvider().addFilter("SomeBeanFilter",filter);
//constructor of MappingJacksonValue class that has bean as constructor argument
MappingJacksonValue mapping = new MappingJacksonValue(someBean);
//configuring filters
[Link](filters);
return mapping;
}
//returning a list of SomeBeans as response
//values to send name and phone
@RequestMapping("/filtering-list")
public MappingJacksonValue retrieveListOfSomeBeans()
{
List<SomeBean> list=[Link](new SomeBean("Saurabh", "8888888888","20000"), new
SomeBean("Devesh", "1111111111","34000"));
//invoking static method filterOutAllExcept()
SimpleBeanPropertyFilter filter=[Link]("name", "phone");
FilterProvider filters=new SimpleFilterProvider().addFilter("SomeBeanFilter",filter);
//constructor of MappingJacksonValue class that has list as constructor argument
MappingJacksonValue mapping = new MappingJacksonValue(list);
//configuring filter
[Link](filters);
return mapping;
}
}
Now Open the REST Client Postman and send a GET request with the URI
[Link] It returns the two fields name and salary in the response as shown
in the following image.
Click here to download Implementing Dynamic Filtering for RESTful Services project
================================================================
Versioning RESTful Web Services-Basic Approach With URIs
================================================================
Versioning is the most important and difficult part of the API as it takes backward API
compatible. Versioning helps us to iterate faster when the changes are identified. We should
always version our Web API.
Consider a scenario in which we have a Web API that is up (status) and running. The users are
consuming that API. Now we want to add more functionality in the Web API but want to keep the
existing functionality unchanged. There may be few users who still want to use the old API while
the other users want a new version of API with new or extended features. It is the scenario
where Web API versioning comes into existence.
ADVERTISEMENT
ADVERTISEMENT
A change in the format of the response data for one or more calls.
Change in the response type.
Remove any part of the API.
Breaking changes should always result in a change to the major version number for an API or
content response type.
Non-breaking changes (adding new points or new response parameters) do not require a
change to the major version number. However, it can be helpful to track the minor version of the
APIs.
How to Version
The most commonly used approaches fall into three categories:
URI Versioning
Versioning using Custom Request Header
Versioning using Accept Header
URI Versioning
URI versioning is the most straightforward approach. It specified in the URL as a query string. It
violates the principle that a URI should refer to a unique resource. You are also guaranteed to
break client integration when a version is updated. Twitter uses URI versioning.
Example
[Link]
[Link]
The version need not be numeric, nor specified using v[x] syntax. Alternatives include the date,
project name, season, or other identifiers that are meaningful enough to change as the version
change.
Example
Accept-version: v1
Accept-version: v2
Example
URI Versioning
Step 1: Create a class with the name [Link] in the package
[Link]. PersonV1 denotes the first version of API. The initial
version of API has a name variable.
[Link]
package [Link];
public class PersonV1
{
private String name;
}
Step 2: Over a period, we recognize the need for having the first name and last name
separately. So we created a class with the name [Link]. It denotes the second version of
API.
[Link]
package [Link];
public class PersonV2
{
private Name name;
}
Step 3: Create a class with the name [Link] that has two variables firstName and lastName
separately.
[Link]
package [Link];
public class Name
{
private String firstName;
private String lastName;
}
The old version is still returning the full name, and the second version is returning firstName and
lastName separately. Now we are required to create two different versions of the same service.
Let's see how to create two different versions of the same service and what are the different
versions of the service are present.
Step 4: In the [Link] file, Generate Getters and Setters, Generate Constructor using Fields.
Create a no-argument constructor of the class Name.
[Link]
package [Link];
public class Name
{
private String firstName;
private String lastName;
//no argument constructor
public Name()
{
}
public Name(String firstName, String lastName)
{
super();
[Link] = firstName;
[Link] = lastName;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
[Link] = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
[Link] = lastName;
}
}
Step 5: Open [Link] class. Generate Getters and Setters, Generate Constructor using
Fields. Create a no argument constructor of the class [Link].
[Link]
package [Link];
public class PersonV1
{
private String name;
//no argument constructor
public PersonV1()
{
super();
}
public PersonV1(String name)
{
super();
[Link] = name;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
}
Step 6: Open [Link]. Generate Getters and Setters, Generate Constructor using Fields.
Create a no argument constructor of the class [Link].
[Link]
package [Link];
public class PersonV2
{
private Name name;
public PersonV2()
{
super();
}
public PersonV2(Name name)
{
super();
[Link] = name;
}
public Name getName()
{
return name;
}
public void setName(Name name)
{
[Link] = name;
}
}
Now we need to create a service.
Step 7: Create a class with the name [Link]. Create two methods for
different versions and map them to different URIs.
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class PersonVersoningController
{
//this method is for the first version that returns the entire name
@GetMapping("v1/person")
public PersonV1 personv1()
{
return new PersonV1("Tom Cruise");
}
//this method is for the second version that returns firstName and lastName separately
@GetMapping("v2/person")
public PersonV2 personv2()
{
return new PersonV2(new Name("Tom", "Cruise"));
}
}
Step 8: Open the Postman and send a GET request with the URI
[Link] It returns the full name, as shown in the following image.
Change the URI for the first method from /v1/person to /person/param.
Change the name of the method from personV1 to paramV1.
Similarly, change the URI for the second method from /v2/person to /person/param.
Both the methods have the same get mapping, so we will distinguish them by using the value
and params attribute. The value attribute contains the URI, which we want to use, and the
params attribute contains the parameter which distinguishes between versions.
[Link]
package [Link];
import [Link];
import [Link];
@RestController
public class PersonVersoningController
{
//this method is for first version that returns the entire name
@GetMapping(value="/person/param", params="version=1")
public PersonV1 personV1()
{
return new PersonV1("Tom Cruise");
}
//this method is for second version that returns firstName and lastName separately
@GetMapping(value="/person/param", params="version=2")
public PersonV2 personV2()
{
return new PersonV2(new Name("Tom", "Cruise"));
}
}
Now, move to Postman and send a GET request with the URI
[Link] It returns the full name, as shown in the following
image.
Select the Headers tab and set key: X-API-VERSION and Value: 1.
Type the URI [Link] and send a GET request.
It returns the name full name.
Select the Headers tab and set key: Accept and Value: application/[Link]-v1+json.
Uncheck the X-API-VERSION key.
Type the URI [Link] and send a GET request.
It returns the full name.
================================================================
Implementing Basic Authentication with Spring Security
===============================================================
There are multiple ways to authenticate our RESTful web services. The basic way is to use
basic authentication. In the basic authentication, we send a username and password as part of
our request. When we provide a username and password, it allows us to access the resource.
There are other advanced forms of authentication like digest authentication, where the
password digest is created, and the digest is sent across. It does not send the actual password
to the server. The other advanced form of authentication is OAuth (Open Authorization) or
OAuth2 authentication.
Step 1: Open [Link] and add the spring-boot-starter-security. It automatically configures the
basic security for us.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Step 2: Restart the server, we get a password in the log. Each time the server starts up the
password will be different.
Step 4: Open the REST Client Postman and send a POST request. We are sending a POST to
create a user.
ADVERTISEMENT
[Link]
[Link]=user
[Link]=password
Now, move to Postman and try to send a POST request that returns Status: 401 Unauthorized.
It is because we are still using an old password. So we are required to change the username
and password with the new one. Provide the username and password which we have
configured in the properties file. We get the Status: 201 Created.
================================================================
Connecting RESTful Services to JPA
===============================================================
Connecting RESTful Services to JPA
Creating a User Entity and some test Data
Let's create a User entity and a UserRepository so that we can access the detail of the user.
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Step 2: Make the User class as an entity by adding an annotation @Entity just above the User
class.
ADVERTISEMENT
@Entity: Entities are nothing but POJO (Plain Old Java Object). It represents the data that can
be persisted to the database. It represents a table in a database. Every instance of an entity
represents a row in a table. We cannot declare an entity class as final.
Step 3: Make the Id primary key by adding an annotation @Id just above the Id variable. Also,
add an annotation @GeneratedValue.
@Id: It defines that the member field below is the primary key of the current entity. Every entity
must have a primary key that uniquely defines the column.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@ApiModel(description="All details about the user")
@Entity
public class User
{
//making Id as primary key
@Id
@GeneratedValue
private Integer id;
@Size(min=5, message="Name should have atleast 5 characters")
@ApiModelProperty(notes="name should have atleast 5 characters")
private String name;
@Past
@ApiModelProperty(notes="Birth date should be in the past")
private Date dob;
//default constructor
protected User()
{
}
public User(Integer id, String name, Date dob)
{
super();
[Link] = id;
[Link] = name;
[Link] = dob;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public Date getDob()
{
return dob;
}
public void setDob(Date dob)
{
[Link] = dob;
}
@Override
public String toString()
{
//return "User [id=" + id + ", name=" + name + ", dob=" + dob + "]";
return [Link]("User [id=%s, name=%s, dob=%s]", id, name, dob);
}
}
Before moving to the next step, remove or comment the basic security dependency in the
[Link].
ADVERTISEMENT
Step 4: Open [Link] file and enable the H2 console so that we can see what
data we have inserted in the table.
[Link]=true
We also need to enable the SQL logging to see which SQL statements are executing. It starts
SQL logging in the log when the statement executes.
[Link]-sql=true
Now restart the application to pick up the changes. We can see in the following image that the
table is created.
Right-click on the folder src/main/resource -> New ->Other -> Select SQL File -> provide the file
name [Link] -> Click on finish.
Step 6: In the [Link] file, insert the data into user table. We have inserted the following data:
Step 7: Open the browser and type [Link] to connect the H2 console.
Make sure that it has JDBC URL: jdbc:h2:mem:testdb. Do not write anything in the password
field.
Step 2: Now, we have two URIs with the same name that create conflict. To remove this conflict,
we will add /jpa in [Link] file.
[Link]
package [Link];
import static [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@RestController
public class UserJPAResource
{
@Autowired
private UserDaoService service;
@GetMapping("/jpa/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
@GetMapping("/jpa/users/{id}")
public Resource<User> retriveUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
//"all-users", SERVER_PATH + "/users"
//retrieveAllUsers
Resource<User> resource=new Resource<User>(user); //constructor of Resource class
//add link to retrieve all the users
ControllerLinkBuilder linkTo=linkTo(methodOn([Link]()).retriveAllUsers());
[Link]([Link]("all-users"));
return resource;
}
//method that delete a user resource
@DeleteMapping("/jpa/users/{id}")
public void deleteUser(@PathVariable int id)
{
User user= [Link](id);
if(user==null)
//runtime exception
throw new UserNotFoundException("id: "+ id);
}
//method that posts a new user detail and returns the status of the user resource
@PostMapping("/jpa/users")
public ResponseEntity<Object> createUser(@Valid @RequestBody User user)
{
User sevedUser=[Link](user);
URI
location=[Link]().path("/{id}").buildAndExpand(seve
[Link]()).toUri();
return [Link](location).build();
}
}
But it is not really talking to the database. We need to create a spring data repository.
Step 3: Create an interface with the name UserRepository that extends JpaRepository. Specify
the entity that has to be managed. We have specified User and Integer. Now we have the
UserRepository ready.
[Link]
package [Link];
import [Link];
import [Link];
@Repository
public interface UserRepository extends JpaRepository<User, Integer>
{
}
Step 4: Create the use of UserResource. We have autowired the UserRepository interface in the
UserJPAResource class.
@Autowired
private UserRepository userRepository;
Step 5: Return the [Link]() in the retriveAllUsers() method.
ADVERTISEMENT
@GetMapping("/jpa/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
The retriveAllUsers() is the only method that retrieve data form the embedded database, all the
other methods retrieve data from the static array list.
Step 6: Open the Postman. Type the URI [Link] and send a GET
request. It shows all the data that is fetched from the embedded database.
But we are required to fetch data from the embedded database. We need to change the
following services in the [Link].
@GetMapping("/jpa/users")
public List<User> retriveAllUsers()
{
return [Link]();
}
In the following service, the findById() returns the Option of User whether user is null or not null.
Whenever we use findById(), there is two possibilities: id exist or not exist. When it does not
exist it comes with a proper object. We will check the user exist or not by the statement
if(![Link]()). If the user is not present it throws an exception.
@GetMapping("/jpa/users/{id}")
public Resource<User> retriveUser(@PathVariable int id)
{
Optional<User> user= [Link](id);
if([Link]())
//runtime exception
throw new UserNotFoundException("id: "+ id);
//"all-users", SERVER_PATH + "/users"
//retrieveAllUsers
Resource<User> resource=new Resource<User>([Link]()); //constructor of Resource class
//add link to retrieve all the users
ControllerLinkBuilder linkTo=linkTo(methodOn([Link]()).retriveAllUsers());
[Link]([Link]("all-users"));
return resource;
}
Again send a GET request with the URL [Link] It returns a specified
user and the link to /jpa/users.
{
"name": "John",
"dob": "2019-10-01"T0726:52.596+0000",
"_links": {
"all-users": {
"href": "[Link]
}
}
}
================================================================
Updating POST and DELETE methods on UserResource to use JPA
===========================================================
In this section, we will convert deleteUser() method and createUser() method to use JPA. Let's
make the changes in the [Link].
Step 2: Delete the return type because userRepository's delete() method does not return
anything.
@DeleteMapping("/jpa/users/{id}")
public void deleteUser(@PathVariable int id)
{
[Link](id);
}
If it fails, it throws an exception.
Step 3: Open the Postman and send a DELETE request with the URL
[Link]
Again send a DELETE request with the same URL [Link] It returns a
message "no entity with id 1 exist".
{
"timesatmp": "2017-07-20T12:10:29.988+0000",
"message": "No class [Link]. User entity with
id 1 exists! ",
"details": "uri=/jpa/user/1"
}
Now we will generate a POST request to create a user.
Step 5: Click on the Headers tab and make sure that the Content-Type is application/json.
ADVERTISEMENT
It is because hibernate uses a sequence. In the User entity, Id is generated value, so it creates a
sequence for us. Hibernate is trying to insert a row with id 1. It conflicts with the data that we
already have. To remove this conflict, do the following:
Click here to download Updating POST and DELETE methods on User Resource to use JPA
project
================================================================
Creating Post Entity and Many to One Relationship with User Entity
==============================================================
n this section, we will create a Post entity that contains many to one relationship with the User
entity.
Step 1: Create a class with the name [Link] in the package [Link].
Step 6: A user can do many posts, so add @ManyToOne annotation. The User entity has many
to one relationship with the Post entity. The fetch type will not retrieve the details of the user
unless we called [Link].
@ManyToOne(fetch=[Link])
Step 7: Id is a primary key, so we need to add @Id annotation.
[Link]
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Entity
public class Post
{
@Id
@GeneratedValue
private Integer id;
private String description;
//many to one mapping
@ManyToOne(fetch=[Link])
private User user;
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
[Link] = id;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
description = description;
}
public User getUser()
{
return user;
}
public void setUser(User user)
{
[Link] = user;
}
@Override
public String toString()
{
return [Link]("Post [id=%s, description=%s]", id);
}
}
We have configured the relationship on the side of Post entity. Now we are required to configure
relationship on the side of User entity.
A user can make a list of posts, so the post has one-to-many relationships.
Step 8: Open [Link] file and create a list of posts.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@ApiModel(description="All details about the user")
@Entity
public class User
{
//Id as a primary key
@Id
@GeneratedValue
private Integer id;
@Size(min=5, message="Name should have atleast 5 characters")
@ApiModelProperty(notes="name should have atleast 5 characters")
private String name;
@Past
@ApiModelProperty(notes="Birth date should be in the past")
private Date dob;
//default constructor
@OneToMany(mappedBy="user")
private List<Post> posts;
protected User()
{
}
public User(Integer id, String name, Date dob)
{
super();
[Link] = id;
[Link] = name;
[Link] = dob;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
[Link] = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
[Link] = name;
}
public Date getDob()
{
return dob;
}
public void setDob(Date dob)
{
[Link] = dob;
}
public List<Post> getPosts()
{
return posts;
}
public void setPosts(List<Post> posts)
{
[Link] = posts;
}
@Override
public String toString()
{
//return "User [id=" + id + ", name=" + name + ", dob=" + dob + "]";
return [Link]("User [id=%s, name=%s, dob=%s]", id, name, dob);
}
}
Step 11: Restart the application.
Creating Post Entity and Many to One Relationship with User Entity
We can see in the log that there are two tables post and user. The Post table has a link to the
User table by a user id. A user can have multiple posts, and all of them have the same user id.
Step 12: Now, open the H2 Console. We can see that are two tables named USER and POST.
Creating Post Entity and Many to One Relationship with User Entity
Step 13: Open the [Link] file that we have created earlier and insert the data into POST table.
We have inserted the following data:
[Link]
Step 15: Restart the H2 Console and execute the query SELECT *FROM POST;
It shows the data which we have inserted into the [Link] file.
Creating Post Entity and Many to One Relationship with User Entity
Click here to download Creating Post Entity and Many to One Relationship with User Entity
project
================================================================
Implementing a GET service to retrieve all Posts of a User
===========================================================
Step 1: Open the [Link] file and create a mapping for the URI
"/jpa/users/{id}/posts"
@GetMapping("/jpa/users/{id}/posts")
public List<Post> retriveAllUsers(@PathVariable int id)
{
Optional<User> userOptional= [Link](id);
if(![Link]())
{
throw new UserNotFoundException("id: "+ id);
}
return [Link]().getPosts();
}
Step 2: There is no need to show user detail in the response, so we will add @JsonIgnore
annotation just above the User field in [Link] file.
Step 3: Open the Postman and send a GET request with the URI
[Link] In our case, we have specified user id 101. It shows all
the posts done by user 101.
[
{
"id": 111,
"description": "first post"
},
{
"id": 112,
"description": "second post"
}
]
Now, we send a GET request for the user who has not created any post yet. The user 105 has
not created any post so we will specify this user id in the URI
[Link]
It shows a pair of empty square brackets. The brackets denote that the user exists, but the user
has not created any post.
Again send a GET request for the user who does not exist in the database say 110. It shows the
Status: 404 Not Found with the following details:
{
"timesatmp": "2019-10-05T05:31:09.407+0000",
"message": "id-110",
"details": "uri=/jpa/users/110/posts"
}
================================================================
Implementing POST Service to Create a Post for a User
===============================================================
In this section, we will enable post-operation to create a post for the specific user.
Step 1: Open the [Link] file and create a PostMapping to create a post.
@PostMapping("/jpa/users/{id}/posts")
public ResponseEntity<Object> createUser(@PathVariable int id, @RequestBody Post post)
{
Optional<User> userOptional= [Link](id);
if(![Link]())
{
throw new UserNotFoundException("id: "+ id);
}
User user=[Link]();
//map the user to the post
[Link](user);
//save post to the database
[Link](post);
//getting the path of the post and append id of the post to the URI
URI
location=[Link]().path("/{id}").buildAndExpand(post.
getId()).toUri();
//returns the location of the created post
return [Link](location).build();
}
Step 2: Create a post repository.
[Link]
package [Link];
import [Link];
import [Link];
@Repository
public interface PostRepository extends JpaRepository<Post, Integer>
{
}
Step 3: Open the Postman and send a POST request with the URI
[Link] Under the Body tab, insert the post description.
================================================================
===============================================================
Dependency Injection
IOC container
================================================================
The IoC container is responsible to instantiate, configure and assemble the objects. The IoC
container gets informations from the XML file and works accordingly. The main tasks performed
by IoC container are:
ADVERTISEMENT
ADVERTISEMENT
BeanFactory
ApplicationContext
Difference between BeanFactory and the ApplicationContext
The [Link] and the
[Link] interfaces acts as the IoC container. The
ApplicationContext interface is built on top of the BeanFactory interface. It adds some extra
functionality than BeanFactory such as simple integration with Spring's AOP, message resource
handling (for I18N), event propagation, application layer specific context (e.g.
WebApplicationContext) for web application. So it is better to use ApplicationContext than
BeanFactory.
Using BeanFactory
The XmlBeanFactory is the implementation class for the BeanFactory interface. To use the
BeanFactory, we need to create the instance of XmlBeanFactory class as given below:
Using ApplicationContext
The ClassPathXmlApplicationContext class is the implementation class of ApplicationContext
interface. We need to instantiate the ClassPathXmlApplicationContext class to use the
ApplicationContext as given below:
ApplicationContext context =
new ClassPathXmlApplicationContext("[Link]");
The constructor of ClassPathXmlApplicationContext class receives string, so we can pass the
name of the xml file to create the instance of ApplicationContext.
Dependency Lookup
The Dependency Lookup is an approach where we get the resource after demand. There can
be various ways to get the resource for example:
A obj = [Link]();
This way, we get the resource (instance of A class) by calling the static factory method getA().
ADVERTISEMENT
Alternatively, we can get the resource by JNDI (Java Naming Directory Interface) as:
ADVERTISEMENT
ADVERTISEMENT
tight coupling The dependency lookup approach makes the code tightly coupled. If resource is
changed, we need to perform a lot of modification in the code.
Not easy for testing This approach creates a lot of problems while testing the application
especially in black box testing.
Dependency Injection
The Dependency Injection is a design pattern that removes the dependency of the programs. In
such case we provide the information from the external source such as XML file. It makes our
code loosely coupled and easier for testing. In such case we write the code as:
class Employee{
Address address;
Employee(Address address){
[Link]=address;
}
public void setAddress(Address address){
[Link]=address;
}
}
In such case, instance of Address class is provided by external souce such as XML file either by
constructor or setter method.
By Constructor
By Setter method
Upcoming topics in Spring Dependency Injection
Dependency Injection by constructor
Let's see how we can inject dependency by constructor.
Dependency Injection by setter method
Let's see how we can inject dependency by setter method.
================================================================
Constructor Injection
================================================================
Dependency Injection by Constructor Example
We can inject the dependency by constructor. The <constructor-arg> subelement of <bean> is
used for constructor injection. Here we are going to inject
ADVERTISEMENT
ADVERTISEMENT
[Link]
[Link]
[Link]
[Link]
It is a simple class containing two fields id and name. There are four constructors and one
method in this class.
package [Link];
ADVERTISEMENT
[Link]
We are providing the information into the bean by this file. The constructor-arg element invokes
the constructor. In such case, parameterized constructor of int type will be invoked. The value
attribute of constructor-arg element will assign the specified value. The type attribute specifies
that int parameter constructor will be invoked.
</beans>
[Link]
This class gets the bean from the [Link] file and calls the show method.
package [Link];
import [Link];
import [Link];
import [Link].*;
}
}
Output:10 null
....
<bean id="e" class="[Link]">
<constructor-arg value="10"></constructor-arg>
</bean>
....
If you change the bean element as given above, string parameter constructor will be invoked
and the output will be 0 10.
Output:0 10
....
<bean id="e" class="[Link]">
<constructor-arg value="Sonoo"></constructor-arg>
</bean>
....
Output:0 Sonoo
....
<bean id="e" class="[Link]">
<constructor-arg value="10" type="int" ></constructor-arg>
<constructor-arg value="Sonoo"></constructor-arg>
</bean>
....
Output:10 Sonoo
================================================================
setter injection
===============================================================
Dependency Injection by setter method
We can inject the dependency by setter method also. The <property> subelement of <bean> is
used for setter injection. Here we are going to inject
ADVERTISEMENT
[Link]
[Link]
[Link]
[Link]
It is a simple class containing three fields id, name and city with its setters and getters and a
method to display these informations.
package [Link];
}
[Link]
We are providing the information into the bean by this file. The property element invokes the
setter method. The value subelement of property will assign the specified value.
</bean>
</beans>
[Link]
This class gets the bean from the [Link] file and calls the display method.
package [Link];
import [Link];
import [Link];
import [Link].*;
Employee e=(Employee)[Link]("obj");
[Link]();
}
}
Output:20 Arun ghaziabad
===============================================================
Autowiring
================================================================
Autowiring in Spring
Autowiring feature of spring framework enables you to inject the object dependency implicitly. It
internally uses setter or constructor injection.
Autowiring can't be used to inject primitive and string values. It works with reference only.
Advantage of Autowiring
It requires the less code because we don't need to write the code to inject the dependency
explicitly.
Disadvantage of Autowiring
No control of programmer.
Autowiring Modes
Example of Autowiring
Let's see the simple code to use autowiring in spring. You need to use autowire attribute of bean
element to apply the autowire modes.
[Link]
[Link]
[Link]
[Link]
[Link]
This class contains a constructor and method only.
package [Link];
public class B {
B(){[Link]("b is created");}
void print(){[Link]("hello b");}
}
[Link]
This class contains reference of B class and constructor and method.
ADVERTISEMENT
package [Link];
public class A {
B b;
A(){[Link]("a is created");}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
void print(){[Link]("hello a");}
void display(){
print();
[Link]();
}
}
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="[Link]
xmlns:xsi="[Link]
xmlns:p="[Link]
xsi:schemaLocation="[Link]
[Link]
</beans>
[Link]
This class gets the bean from the [Link] file and calls the display method.
package [Link];
import [Link];
import [Link];
public class Test {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("[Link]");
A a=[Link]("a",[Link]);
[Link]();
}
}
Output:
b is created
a is created
hello a
hello b
1) byName autowiring mode
In case of byName autowiring mode, bean id and reference name must be same.
Let's see the code where we are changing the name of the bean from b to b1.
But, if you have multiple bean of one type, it will not work and throw exception.
If you have 3 constructors in a class, zero-arg, one-arg and two-arg then injection will be
performed by calling the two-arg constructor.
factory-method: represents the factory method that will be invoked to inject the bean.
factory-bean: represents the reference of the bean by which factory method will be invoked. It is
used if factory method is non-static.
A method that returns instance of a class is called factory method.
public class A {
public static A getA(){//factory method
return new A();
}
}
Factory Method Types
There can be three types of factory method:
1) A static factory method that returns instance of its own class. It is used in singleton design
pattern.
ADVERTISEMENT
Type 1
Let's see the simple code to inject the dependency by static factory method.
<bean id="a" class="[Link].A" factory-method="getA"></bean>
Let's see the full example to inject dependency using factory method in spring. To create this
example, we have created 3 files.
[Link]
[Link]
[Link]
[Link]
This class is a singleton class.
package [Link];
public class A {
private static final A obj=new A();
private A(){[Link]("private constructor");}
public static A getA(){
[Link]("factory method ");
return obj;
}
public void msg(){
[Link]("hello user");
}
}
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="[Link]
xmlns:xsi="[Link]
xmlns:p="[Link]
xsi:schemaLocation="[Link]
[Link]
</beans>
[Link]
This class gets the bean from the [Link] file and calls the msg method.
ADVERTISEMENT
package [Link];
import [Link];
import [Link];
public class Test {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("[Link]");
A a=(A)[Link]("a");
[Link]();
}
}
Output:
private constructor
factory method
hello user
Type 2
Let's see the simple code to inject the dependency by static factory method that returns the
instance of another class.
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
package [Link];
public interface Printable {
void print();
}
[Link]
package [Link];
public class A implements Printable{
@Override
public void print() {
[Link]("hello a");
}
}
[Link]
package [Link];
public class B implements Printable{
@Override
public void print() {
[Link]("hello b");
}
}
[Link]
package [Link];
public class PrintableFactory {
public static Printable getPrintable(){
//return new B();
return new A();//return any one instance, either A or B
}
}
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="[Link]
xmlns:xsi="[Link]
xmlns:p="[Link]
xsi:schemaLocation="[Link]
[Link]
</beans>
[Link]
This class gets the bean from the [Link] file and calls the print() method.
package [Link];
import [Link];
import [Link];
public class Test {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("[Link]");
Printable p=(Printable)[Link]("p");
[Link]();
}
}
Output:
hello a
Type 3
Let's see the example to inject the dependency by non-static factory method that returns the
instance of another class.
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
All files are same as previous, you need to change only 2 files: PrintableFactory and
[Link].
[Link]
package [Link];
public class PrintableFactory {
//non-static factory method
public Printable getPrintable(){
return new A();//return any one instance, either A or B
}
}
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="[Link]
xmlns:xsi="[Link]
xmlns:p="[Link]
xsi:schemaLocation="[Link]
[Link]
</bean>
output hello a
===============================================================
Spring MVC
MVC Introduction
============================================================
A Spring MVC is a Java framework which is used to build web applications. It follows the
Model-View-Controller design pattern. It implements all the basic features of a core spring
framework like Inversion of Control, Dependency Injection.
A Spring MVC provides an elegant solution to use MVC in spring framework by the help of
DispatcherServlet. Here, DispatcherServlet is a class that receives the incoming request and
maps it to the right resource such as controllers, models, and views.
Separate roles - The Spring MVC separates each role, where the model object, controller,
command object, view resolver, DispatcherServlet, validator, etc. can be fulfilled by a
specialized object.
Light-weight - It uses light-weight servlet container to develop and deploy your application.
Powerful Configuration - It provides a robust configuration for both framework and application
classes that includes easy referencing across contexts, such as from web controllers to
business objects and validators.
Rapid development - The Spring MVC facilitates fast and parallel development.
Reusable business code - Instead of creating new objects, it allows us to use the existing
business objects.
Easy to test - In Spring, generally we create JavaBeans classes that enable you to inject test
data using the setter methods.
Flexible Mapping - It provides the specific annotations that easily redirect the page.
Spring Web MVC Framework Example
Let's see the simple example of a Spring Web MVC framework. The steps are as follows:
Load the spring jar files or add dependencies in the case of Maven
Create the controller class
Provide the entry of controller in the [Link] file
Define the bean in the separate XML file
Display the message in the JSP page
Start the server and deploy the project
Directory Structure of Spring MVC
Spring MVC Tutorial
Directory Structure of Spring MVC using Maven
Spring MVC Tutorial
Required Jar files or Maven Dependency
To run this example, you need to load:
If you are using Maven, you don't need to add jar files. Now, you need to add maven
dependency to the [Link] file.
<project xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<modelVersion>4.0.0</modelVersion>
<groupId>[Link]</groupId>
<artifactId>SpringMVC</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>SpringMVC Maven Webapp</name>
<url>[Link]
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>SpringMVC</finalName>
</build>
</project>
2. Create the controller class
To create the controller class, we are using two annotations @Controller and
@RequestMapping.
The @Requestmapping annotation is used to map the class with the specified URL name.
[Link]
package [Link];
import [Link];
import [Link];
@Controller
public class HelloController {
@RequestMapping("/")
public String display()
{
return "index";
}
}
3. Provide the entry of controller in the [Link] file
In this xml file, we are specifying the servlet class DispatcherServlet that acts as the front
controller in Spring Web MVC. All the incoming request for the html file will be forwarded to the
DispatcherServlet.
[Link]
[Link]
</beans>
5. Display the message in the JSP page
This is the simple JSP page, displaying the message returned by the Controller.
[Link]
<html>
<body>
<p>Welcome to Spring MVC Tutorial</p>
</body>
</html>
Output:
=================================================================
Multiple View Page
===============================================================
Spring MVC Multiple View page Example
Here, we redirect a view page to another view page.
Let's see the simple example of a Spring Web MVC framework. The steps are as follows:
ADVERTISEMENT
Load the spring jar files or add dependencies in the case of Maven
Create the controller class
Provide the entry of controller in the [Link] file
Define the bean in the separate XML file
Create the other view components
Start the server and deploy the project
Directory Structure of Spring MVC
Spring MVC Multiple View page
1. Add dependencies to [Link]
<!-- [Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-webmvc</artifactId>
<version>[Link]</version>
</dependency>
[Link]
<html>
<body>
<a href="hello">Click here...</a>
</body>
</html>
3. Create the controller class
Let's create a controller class that returns the JSP pages. Here, we pass the specific name with
a @Requestmapping annotation to map the class.
[Link]
package [Link];
import [Link];
import [Link];
@Controller
public class HelloController {
@RequestMapping("/hello")
public String redirect()
{
return "viewpage";
}
@RequestMapping("/helloagain")
public String display()
{
return "final";
}
}
4. Provide the entry of controller in the [Link] file
[Link]
The prefix+string returned by controller+suffix page will be invoked for the view component.
[Link]
<html>
<body>
<a href="helloagain">Javatpoint Tutorials</a>
</body>
</html>
[Link]
<html>
<body>
<p>Welcome to Spring MVC Tutorial</p>
</body>
</html>
Output:
==========================================================
Multiple Controller
=======================================================
In Spring MVC, we can create multiple controllers at a time. It is required to map each controller
class with @Controller annotation. Here, we see a Spring MVC example of multiple controllers.
The steps are as follows:
ADVERTISEMENT
ADVERTISEMENT
Load the spring jar files or add dependencies in the case of Maven
Create the controller class
Provide the entry of controller in the [Link] file
Define the bean in the separate XML file
Create the other view components
Start the server and deploy the project
Directory Structure of Spring MVC
Spring MVC Multiple Controller
1. Add dependencies to [Link]
<!-- [Link] -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-webmvc</artifactId>
<version>[Link]</version>
</dependency>
[Link]
<html>
<body>
<a href="hello1">Spring MVC</a> ||
<a href="hello2">Spring Boot</a>
</body>
</html>
3. Create the controller class
Let's create two controller classes, where each returns the particular view page.
ADVERTISEMENT
[Link]
package [Link];
import [Link];
import [Link];
@Controller
public class HelloController1 {
@RequestMapping("/hello1")
public String display()
{
return "viewpage1";
}
}
[Link]
package [Link];
import [Link];
import [Link];
@Controller
public class HelloController2 {
@RequestMapping("/hello2")
public String display()
{
return "viewpage2";
}
}
4. Provide the entry of controller in the [Link] file
[Link]
<html>
<body>
<p>Welcome to Spring MVC Tutorial</p>
</body>
</html>
[Link]
ADVERTISEMENT
ADVERTISEMENT
<html>
<body>
<p>Welcome to Spring Boot Tutorial</p>
</body>
</html>
Output:
================================================================
Model Interface
===========================================================
n Spring MVC, the model works a container that contains the data of the application. Here, a
data can be in any form such as objects, strings, information from the database, etc.
It is required to place the Model interface in the controller part of the application. The object of
HttpServletRequest reads the information provided by the user and pass it to the Model
interface. Now, a view page easily accesses the data from the model part.
[Link]
<html>
<body>
<form action="hello">
UserName : <input type="text" name="name"/> <br><br>
Password : <input type="text" name="pass"/> <br><br>
<input type="submit" name="submit">
</form>
</body>
</html>
3. Create the controller class
In controller class:
The HttpServletRequest is used to read the HTML form data provided by the user.
The Model contains the request data and provides it to view page.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class HelloController {
@RequestMapping("/hello")
public String display(HttpServletRequest req,Model m)
{
//read the provided form data
String name=[Link]("name");
String pass=[Link]("pass");
if([Link]("admin"))
{
String msg="Hello "+ name;
//add a message to the model
[Link]("message", msg);
return "viewpage";
}
else
{
String msg="Sorry "+ name+". You entered an incorrect password";
[Link]("message", msg);
return "errorpage";
}
}
}
4. Provide the entry of controller in the [Link] file
[Link]
[Link]
<html>
<body>
${message}
</body>
</html>
[Link]
<html>
<body>
${message}
<br><br>
<jsp:include page="/[Link]"></jsp:include>
</body>
</html>
Output:
================================================================
RequestParam Annotation
===============================================================
In Spring MVC, the @RequestParam annotation is used to read the form data and bind it
automatically to the parameter present in the provided method. So, it ignores the requirement of
HttpServletRequest object to read the provided data.
Including form data, it also maps the request parameter to query parameter and parts in
multipart requests. If the method parameter type is Map and a request parameter name is
specified, then the request parameter value is converted to a Map else the map parameter is
populated with all request parameter names and values.
ADVERTISEMENT
[Link]
<html>
<body>
<form action="hello">
UserName : <input type="text" name="name"/> <br><br>
Password : <input type="text" name="pass"/> <br><br>
<input type="submit" name="submit">
</form>
</body>
</html>
3. Create the Controller Class
In controller class:
ADVERTISEMENT
ADVERTISEMENT
The @RequestParam is used to read the HTML form data provided by a user and bind it to the
request parameter.
The Model contains the request data and provides it to view page.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class HelloController {
@RequestMapping("/hello")
//read the provided form data
public String display(@RequestParam("name") String name,@RequestParam("pass") String
pass,Model m)
{
if([Link]("admin"))
{
String msg="Hello "+ name;
//add a message to the model
[Link]("message", msg);
return "viewpage";
}
else
{
String msg="Sorry "+ name+". You entered an incorrect password";
[Link]("message", msg);
return "errorpage";
}
}
}
4. Create the other view components
To run this example, the following view components must be located inside the WEB-INF/jsp
directory.
[Link]
<html>
<body>
${message}
</body>
</html>
[Link]
ADVERTISEMENT
<html>
<body>
${message}
<br><br>
<jsp:include page="/[Link]"></jsp:include>
</body>
</html>
</html>
Output:
Create a table
Here, we are using emp99 table present in the MySQL database. It has 4 fields: id, name,
salary, and designation. Here, id is auto incremented which is generated by the sequence.
[Link]
package [Link];
}
3. Create the controller class
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class EmpController {
@Autowired
EmpDao dao;//will inject dao from XML file
/*It displays a form to input data, here "command" is a reserved request attribute
*which is used to display object data into form
*/
@RequestMapping("/empform")
public String showform(Model m){
[Link]("command", new Emp());
return "empform";
}
/*It saves object into database. The @ModelAttribute puts request data
* into model object. You need to mention [Link] method
* because default request is GET*/
@RequestMapping(value="/save",method = [Link])
public String save(@ModelAttribute("emp") Emp emp){
[Link](emp);
return "redirect:/viewemp";//will redirect to viewemp request mapping
}
/* It provides list of employees in model object */
@RequestMapping("/viewemp")
public String viewemp(Model m){
List<Emp> list=[Link]();
[Link]("list",list);
return "viewemp";
}
/* It displays object data into form for the given id.
* The @PathVariable puts URL data into variable.*/
@RequestMapping(value="/editemp/{id}")
public String edit(@PathVariable int id, Model m){
Emp emp=[Link](id);
[Link]("command",emp);
return "empeditform";
}
/* It updates model object. */
@RequestMapping(value="/editsave",method = [Link])
public String editsave(@ModelAttribute("emp") Emp emp){
[Link](emp);
return "redirect:/viewemp";
}
/* It deletes record for the given id in URL and redirects to /viewemp */
@RequestMapping(value="/deleteemp/{id}",method = [Link])
public String delete(@PathVariable int id){
[Link](id);
return "redirect:/viewemp";
}
}
4. Create the DAO class
Let's create a DAO class to access the required data from the database.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
<bean class="[Link]">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
Here "/SpringMVCCRUDSimple" is the project name, change this if you have different project
name. For live application, you can provide full URL.
<h1>Edit Employee</h1>
<form:form method="POST" action="/SpringMVCCRUDSimple/editsave">
<table >
<tr>
<td></td>
<td><form:hidden path="id" /></td>
</tr>
<tr>
<td>Name : </td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td>Salary :</td>
<td><form:input path="salary" /></td>
</tr>
<tr>
<td>Designation :</td>
<td><form:input path="designation" /></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Edit Save" /></td>
</tr>
</table>
</form:form>
[Link]
<h1>Employees List</h1>
<table border="2" width="70%" cellpadding="2">
<tr><th>Id</th><th>Name</th><th>Salary</th><th>Designation</th><th>Edit</th><th>Delete</t
h></tr>
<c:forEach var="emp" items="${list}">
<tr>
<td>${[Link]}</td>
<td>${[Link]}</td>
<td>${[Link]}</td>
<td>${[Link]}</td>
<td><a href="editemp/${[Link]}">Edit</a></td>
<td><a href="deleteemp/${[Link]}">Delete</a></td>
</tr>
</c:forEach>
</table>
<br/>
<a href="empform">Add New Employee</a>
Output:
Now, click Edit Save to add the entry with changes into the database.
We can simply create pagination example in Spring MVC. In this pagination example, we are
using MySQL database to fetch records.
[Link]
package [Link];
}
3. Create the controller class
In Controller class, the @PathVariable annotation bounds the method parameter with a
temporary URL. For example:
@RequestMapping(value="/viewemp/{pageid}")
Here, {} bracket contains the temporary value.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class EmpController {
@Autowired
EmpDao dao;
@RequestMapping(value="/viewemp/{pageid}")
public String edit(@PathVariable int pageid,Model m){
int total=5;
if(pageid==1){}
else{
pageid=(pageid-1)*total+1;
}
[Link](pageid);
List<Emp> list=[Link](pageid,total);
[Link]("msg", list);
return "viewemp";
}
}
4. Create the DAO class
Let's create a DAO class to access the required data from the database.
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
<bean class="[Link]">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!DOCTYPE html>
<html>
<body>
<a href="viewemp/1">View Employees</a>
</body>
</html>
8. Create view component
[Link]
ADVERTISEMENT
2) Download [Link]
ADVERTISEMENT
3) Download [Link]
Spring MVC File Upload Steps (Extra than MVC)
1) Add commons-io and [Link] files
<bean id="multipartResolver"
class="[Link]"/>
3) Create form to submit file. Method name must be "post" and enctype "multiple/form-data".
@RequestMapping(value="/savefile",method=[Link])
public ModelAndView upload(@RequestParam CommonsMultipartFile file,HttpSession
session){
String path=[Link]().getRealPath("/");
String filename=[Link]();
[Link](path+" "+filename);
try{
byte barr[]=[Link]();
}catch(Exception e){[Link](e);}
return new ModelAndView("upload-success","filename",path+"/"+filename);
}
5) Display image in JSP.
<h1>Upload Success</h1>
<img src="${filename}"/>
[Link]
<a href="uploadform">Upload Image</a>
[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class HelloController {
private static final String UPLOAD_DIRECTORY ="/images";
@RequestMapping("uploadform")
public ModelAndView uploadForm(){
return new ModelAndView("uploadform");
}
@RequestMapping(value="savefile",method=[Link])
public ModelAndView saveimage( @RequestParam CommonsMultipartFile file,
HttpSession session) throws Exception{
[Link](path+" "+filename);
<context:component-scan base-package="[Link]"></context:component-scan>
<bean class="[Link]">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="multipartResolver"
class="[Link]"/>
</beans>
[Link]
Here form must be method="post" and enctype="multipart/form-data".
<!DOCTYPE html>
<html>
<head>
<title>Image File Upload</title>
</head>
<body>
<h1>File Upload Example - JavaTpoint</h1>
<h3 style="color:red">${filesuccess}</h3>
<form:form method="post" action="savefile" enctype="multipart/form-data">
<p><label for="image">Choose Image</label></p>
<p><input name="file" id="fileToUpload" type="file" /></p>
<p><input type="submit" value="Upload"></p>
</form:form>
</body>
</html>
Output
spring mvc file upload output1 spring mvc file upload output2 spring mvc file upload output3
Go to the path printed on the server console, to see the uploaded file.
It is a sub-project of Spring framework which was started in 2003 by Ben Alex. Later on, in
2004, It was released under the Apache License as Spring Security 2.0.0.
It overcomes all the problems that come during creating non spring security applications and
manage new server environment for the application.
This framework targets two major areas of application are authentication and authorization.
Authentication is the process of knowing and identifying the user that wants to access.
ADVERTISEMENT
We can apply authorization to authorize web request, methods and access to individual domain.
Spring Security framework supports wide range of authentication models. These models either
provided by third parties or framework itself. Spring Security supports integration with all of
these technologies.
ADVERTISEMENT
ADVERTISEMENT
HTTP BASIC authentication headers
HTTP Digest authentication headers
HTTP X.509 client certificate exchange
LDAP (Lighweight Directory Access Protocol)
Form-based authentication
OpenID authentication
Automatic remember-me authentication
Kerberos
JOSSO (Java Open Source Single Sign-On)
AppFuse
AndroMDA
Mule ESB
DWR(Direct Web Request)
The beauty of this framework is its flexible authentication nature to integrate with any software
solution. Sometimes, developers want to integrate it with a legacy system that does not follow
any security standard, there Spring Security works nicely.
Advantages
Spring Security has numerous advantages. Some of that are given below.
ADVERTISEMENT
ADVERTISEMENT
Initially, authentication module was not part of the project, around a year after, module was
added and complete project was reconfigure to support more technologies.
After some time this project became a subproject of Spring framework and released as 1.0.0 in
2006.
in 2007, project is renamed to Spring Security and widely accepted. Currently, it is recognized
and supported by developers open community world wide.
================================================================
Sp Security Features
================================================================
LDAP (Lightweight Directory Access Protocol)
Single sign-on
JAAS (Java Authentication and Authorization Service) LoginModule
Basic Access Authentication
Digest Access Authentication
Remember-me
Web Form Authentication
Authorization
Software Localization
HTTP Authorization
LDAP (Lightweight Directory Access Protocol)
It is an open application protocol for maintaining and accessing distributed directory information
services over an Internet Protocol.
Single sign-on
This feature allows a user to access multiple applications with the help of single account(user
name and password).
Remember-me
Spring Security supports this feature with the help of HTTP Cookies. It remember to the user
and avoid login again from the same machine until the user logout.
Authorization
Spring Security provides the this feature to authorize the user before accessing resources. It
allows developers to define access policies against the resources.
Software Localization
This feature allows us to make application user interface in any language.
HTTP Authorization
Spring provides this feature for HTTP authorization of web request URLs using Apache Ant
paths or regular expressions.
ADVERTISEMENT
Reactive Support
From version Spring Security 5.0, it provides reactive programming and reactive web runtime
support and even, we can integrate with Spring WebFlux.
================================================================
Security Project Modules
==========================================================
In Spring Security 3.0, the Security module is divided into separate jar files. The purpose was to
divide jar files based on their functionalities, so, the developer can integrate according to their
requirement.
It also helps to set required dependency into [Link] file of maven project.
The following are the jar files that are included into Spring Security module.
ADVERTISEMENT
ADVERTISEMENT
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
Core - [Link]
This is core jar file and required for every application that wants to use Spring Security. This jar
file includes core access-control and core authentication classes and interfaces. We can use it
in standalone applications or remote clients applications.
ADVERTISEMENT
It contains top level packages:
[Link]
[Link]
[Link]
[Link]
Remoting - [Link]
This jar is used to integrate security feature into the Spring remote application. We don't need it
until or unless we are creating remote application. All the classes and interfaces are located into
[Link] package.
Web - [Link]
This jar is useful for Spring Security web authentication and URL-based access control. It
includes filters and web-security infrastructure.
All the classes and interfaces are located into the [Link] package.
Config - [Link]
This jar file is required for Spring Security configuration using XML and Java both. It includes
Java configuration code and security namespace parsing code. All the classes and interfaces
are stored in [Link] package.
LDAP - [Link]
This jar file is required only if we want to use LDAP (Lighweight Directory Access Protocol). It
includes authentication and provisioning code. All the classes and interfaces are stored into
[Link] package.
ACL - [Link]
This jar is used to apply security to domain object in the application. We can access classes and
code from the [Link] package.
CAS - [Link]
It is required for Spring Security?s CAS client integration. We can use it to integrate Spring
Security web authentication with CAS single sign-on server. The source code is located into
[Link] package.
ADVERTISEMENT
OpenID - [Link]
This jar is used for OpenID web authentication support. We can use it to authenticate users
against an external OpenID server. It requires OpenID4Java and top level package is
[Link].
Test - [Link]
This jar provides support for testing Spring Security application.
================================================================
Sp Security XML Example
================================================================
Sp Security Java Example
================================================================
Sp Security Login Logout
================================================================
Sp Security Custom Login
================================================================
Form-Based Authentication
===============================================================
Sp Security Remember Me
================================================================
Security at Method Level
================================================================
Sp Security Tag Library
===============================================================
Spring boot
CRUD Example
File Upload Example
Login & Logout Example
Search Field Example
1) in hotel management project how you implement user registration using java spring boot
spring security hibernate jpa
2) in hotel management project how you implement user login using java spring boot spring
security hibernate jpa react
)Search & Booking Search hotels based on location, dates, and preferences -
View hotel details and room availability - Book rooms and manage bookings
5) Admin Panel - Manage users, hotels, bookings, and other administrative tasks
7)OTP User Validation- Developed OTP validation in Spring Boot using third party API services
12)User Reviews and Ratings - Developed module for users to leave reviews and
ratings for hotels
14) API Testing and Documentation- Thoroughly tested APIs using Postman -
Prepared comprehensive API documentation for frontend integration
5) Defect Fixing and Quality Assurance - Addressed and resolved defects
communicated by testers