Spring SpringBoot
Spring SpringBoot
By –
Dilip Singh
dilipsingh1306@gmail.com
dilipsingh1306
Shortly, it is a set of keywords and rules of their usage that allows a programmer to tell a
computer what to do. From a technical point of view, there are many ways to classify
languages - compiled and interpreted, functional and object-oriented, low-level and high-
level, etc..
➢ The server part. This is where all the "heavy" calculations take place, background API
interactions, Database write/read operations, etc.
Languages Used : Java, .net, python etc..
➢ The client part. For example, the interface of your website, mobile applications, desktop
apps, etc.
Languages Used : HTML, Java Script, Angular, React etc.
Obviously, there can be much more than two languages in the project, especially considering
such things as SQL used for database operations.
What is a Framework?
When choosing a technology stack for our project, we will surely come across such as
framework. A framework is a set of ready-made elements, rules, and components that
simplify the process and increase the development speed. Below are some popular
frameworks as an example:
➢ It will save time. Using premade components will allow you to avoid reinventing the logics
again and writing from scratch those parts of the application which already exist in the
framework itself.
➢ It will save you from making mistakes. Good frameworks are usually well written. Not
always perfect, but on average much better than the code your team will deliver from
scratch, especially when you're on a short timeline and tight budget.
➢ Opens up access to the infrastructure. There are many existing extensions for popular
frameworks, as well as convenient performance testing tools, CI/CD, ready-to-use
boilerplates for creating various types of applications.
Conclusion:
The framework provides a comprehensive programming and configuration model for modern
Java-based enterprise applications, with support for features such as dependency injection,
aspect-oriented programming, data access, and transaction management. Spring handles the
infrastructure so you can focus on your application. A key element of Spring is infrastructural
support at the application level: Spring focuses on the "plumbing" of enterprise applications
so that teams can focus on application-level business logic, without unnecessary ties to
specific deployment environments.
One of the key features of the Spring Framework is its ability to promote loose coupling
between components, making it easier to develop modular, maintainable, and scalable
applications. The framework also provides a wide range of extensions and modules that can
be used to integrate with other technologies and frameworks, such as Hibernate, Struts, and
JPA.
Overall, the Spring Framework is widely regarded as a powerful and flexible framework for
building enterprise-level applications in Java.
Overall, Spring Framework has become one of the most popular Java frameworks due to its
ease of use, modularity, and extensive features. It is widely used in enterprise applications,
web applications, and other types of Java-based projects.
Spring continues to innovate and to evolve. Beyond the Spring Framework, there are other
projects, such as Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch, among
others.
The Spring Framework includes several modules that provide a range of services:
• Spring Core Container: this is the base module of Spring and provides spring containers
(BeanFactory and ApplicationContext).
• Aspect-oriented programming: enables implementing cross-cutting concerns.
• Data access: working with relational database management systems on the Java platform
using Java Database Connectivity (JDBC) and object-relational mapping tools and
with NoSQL databases
• Authentication and authorization: configurable security processes that support a range
of standards, protocols, tools and practices via the Spring Security sub-project.
• Model–View–Controller: an HTTP- and servlet-based framework providing hooks for web
applications and RESTful (representational state transfer) Web services.
• Testing: support classes for writing unit tests and integration tests
1. Lightweight: Spring is a lightweight framework, which means it does not require a heavy
runtime environment to run. This makes it faster and more efficient than other
frameworks.
2. Inversion of Control (IOC): The Spring Framework uses IOC to manage dependencies
between different components in an application. This makes it easier to manage and
maintain complex applications.
3. Dependency Injection (DI): The Spring Framework also supports DI, which allows you to
inject dependencies into your code at runtime. This makes it easier to write testable and
modular code.
4. Modular: Spring is a modular framework, which means you can use only the components
that you need. This makes it easier to develop and maintain applications.
5. Loose Coupling: The Spring applications are loosely coupled because of dependency
injection.
6. Integration: The Spring Framework provides seamless integration with other frameworks
and technologies such as Hibernate, Struts, and JPA.
7. Aspect-Oriented Programming (AOP): The Spring Framework supports AOP, which allows
you to separate cross-cutting concerns from your business logic. This makes it easier to
develop and maintain complex applications.
8. Security: The Spring Framework provides robust security features such as authentication,
authorization, and secure communication.
9. Transaction Management: The Spring Framework provides robust transaction
management capabilities, which make it easier to manage transactions across different
components in an application.
10. Community Support: The Spring Framework has a large and active community, which
provides support and contributes to its development. This makes it easier to find help and
resources when you need them.
Overall, the Spring Framework provides a number of advantages that make it a popular choice
among developers. Its lightweight, modular, and flexible nature, along with its robust features
for managing dependencies, transactions, security, and integration, make it a powerful tool
for developing enterprise-level Java applications.
➢ Works on POJOs (Plain Old Java Object) which makes your application lightweight.
➢ Provides predefined templates for JDBC, Hibernate, JPA etc., thus reducing your effort
of writing too much code.
➢ Because of dependency injection feature, your code becomes loosely coupled.
➢ Using Spring Framework, the development of Java Enterprise
Edition (JEE) applications became faster.
➢ It also provides strong abstraction to Java Enterprise Edition (JEE) specifications.
➢ It provides declarative support for transactions, validation, caching and formatting.
The below table represents the differences between Java and Spring:
Java Spring
Java is one of the prominent programming Spring is a Java-based open-source
languages in the market. application framework.
Spring Framework comes with various
Java provides a full-highlighted Enterprise
modules like Spring MVC, Spring Boot, Spring
Application Framework stack called Java EE
Security which provides various ready to use
for web application development
features for web application development.
Java EE is built upon a 3-D Architectural Spring is based on a layered architecture that
Framework which are Logical Tiers, Client consists of various modules that are built on
Tiers and Presentation Tiers. top of its core container.
Since its origin till date, Spring has spread its popularity across various domains.
1. Spring Core: This module is the core of the Spring Framework. It provides an
implementation for features like IoC (Inversion of Control) and Dependency Injection with
a singleton design pattern.
2. Spring Bean: This module provides an implementation for the factory design pattern
through BeanFactory.
3. Spring Context: This module is built on the solid base provided by the Core and the Beans
modules and is a medium to access any object defined and configured.
Spring Bean:
Beans are java objects that are configured at run-time by Spring IoC Container. In
Spring, the objects of your application and that are managed by the Spring IoC container are
called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC
container. Otherwise, a bean is simply one of many objects in your application. Beans, and
the dependencies among them, are reflected in the configuration metadata used by Spring
container.
When we hear the term dependency, what comes on to our mind? Obviously, something
relying on something else for support right? Well, that’s the same, in the case of programming
also.
Dependency Injection in Spring can be done through constructors, setters or fields. Here's
how we would create an object dependency in traditional programming:
Employee.java
public class Employee {
private String ename;
private Address addr;
public Employee() {
this.addr = new Address();
}
// setter & getter methods
}
Address.java
By using DI, we can rewrite the example without specifying the implementation of
the Address that we want:
Inversion of Control:
The IoC container is responsible to instantiate, configure and assemble the objects. The IoC
container gets information’s from the XML file or Using annotations and works accordingly.
If I have to explain you in simpler terms, then consider an example, wherein you have the
ability to cook. According to the IoC principle, you can invert the control, so instead of you
cooking food, you can just directly order from outside, wherein you receive food at your
doorstep. Thus the process of food delivered to you at your doorstep is called the Inversion
of Control.
You do not have to cook yourself, instead, you can order the food and let a delivery executive,
deliver the food for you. In this way, you do not have to take care of the additional
responsibilities and just focus on the main work.
Spring – BeanFactory:
This is the simplest container providing the basic support for DI and defined by the
org.springframework.beans.factory.BeanFactory interface. BeanFactory interface is the
simplest container providing an advanced configuration mechanism to instantiate, configure
and manage the life cycle of beans. BeanFactory represents a basic IoC container which is a
parent interface of ApplicationContext. BeanFactory uses Beans and their dependencies
metadata i.e. what we configured in XML file to create and configure them at run-time.
BeanFactory loads the bean definitions and dependency amongst the beans based on a
configuration file(XML) or the beans can be directly returned when required using Java
Configuration.
Spring ApplicationContext:
The following diagram shows a high-level view of how Spring Container works. Your
application bean classes are combined with configuration metadata so that, after the
ApplicationContext is created and initialized, you have a fully configured and executable
system or application.
Configuration Metadata:
As diagram shows, the Spring IoC container consumes a form of configuration
metadata. This configuration metadata represents how you, as an application developer, tell
the Spring container to instantiate, configure, and assemble the objects in your application.
Configuration metadata is traditionally supplied in a simple and intuitive XML format, which
is what most of this chapter uses to convey key concepts and features of the Spring IoC
container. These days, many developers choose Java-based configuration for their Spring
applications.
Instantiating a Container:
The location path or paths supplied to an ApplicationContext constructor are resource
Strings that let the container load configuration metadata from a variety of external
resources, such as the local file system, the Java CLASSPATH, and so on. The Spring provides
ApplicationContext interface: ClassPathXmlApplicationContext and FileSystemXmlApplicatio
nContext for standalone applications, and WebApplicationContext for web applications.
In order to assemble beans, the container uses configuration metadata, which can be in the
form of XML configuration or annotations. Here's one way to manually instantiate a
container:
BeanFactory ApplicationContext
It is a fundamental container that provides It is an advanced container that extends the
the basic functionality for managing beans. BeanFactory that provides all basic
functionality and adds some advanced
features.
It is suitable to build standalone It is suitable to build Web applications,
applications. integration with AOP modules, ORM and
distributed applications.
It supports only Singleton and Prototype It supports all types of bean scopes such as
bean scopes. Singleton, Prototype, Request, Session etc.
It does not support Annotation based It supports Annotation based configuration in
configuration. Bean Autowiring.
This interface does not provide messaging ApplicationContext interface extends
(i18n or internationalization) functionality. MessageSource interface, thus it provides
messaging (i18n or internationalization)
functionality.
BeanFactory will create a bean object when ApplicationContext loads all the beans and
the getBean() method is called thus making creates objects at the time of startup only
it Lazy initialization. thus making it Eager initialization.
NOTE: Usually, if we are working on Spring MVC application and our application is configured
to use Spring Framework, Spring IoC container gets initialized when the application started or
deployed and when a bean is requested, the dependencies are injected automatically.
However, for a standalone application, you need to initialize the container somewhere in the
application and then use it to get the spring beans.
In Maven Project, JAR files are always configured with pom.xml file i.e. we should not
download manually JAR files in any Project. In First Approach we are downloading JAR files
manually from Internet into our computer and then setting class Path to those jar file, this is
not recommended in Real time projects.
1. Open Eclipse
File -> new -> Project -> Java Project
Enter Project Name
Un-Select Create Module-Info
Click Finish.
I have uploaded copy of all Spring JAR files uploaded in Google Drive. You can download
from below link directly.
https://drive.google.com/file/d/1FnbtP3yqjTN5arlEGeoUHCrIJcdcBgM7/view?usp=dri
ve_link
Right Click on Project -> Build Path -> Configure Build Path -> Libraries -> ClassPath
With This Our Java Project is Supporting Spring Core Module Functionalities. We can
Continue with Spring Core Module Functionalities.
Now Open pox.xml file, add Spring Core JAR Dependencies to project and save it.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hello_spring</groupId>
<artifactId>hello_spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.29</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.29</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
With This Our Java Project is Supporting Spring Core Module Functionalities. We can
Continue with Spring Core Module Functionalities.
NOTE: Below Steps are now common across our Spring Core Project created by either
Manual Jar files or Maven Configuration.
package com.naresh.hello;
5. Now create a xml file with any name in side our project root folder:
Ex: beans.xml
• Every class will be configured with <bean> tag, we can call it as Bean class.
• The id attribute is a string that identifies the individual bean name in Spring IOC Container
i.e. similar to Object Name or Reference.
• The class attribute is fully qualified class name our class i.e. class name with package
name.
Here we are getting the object of Student class from the Spring IOC container using
the getBean() method of BeanFactory. Let's see the code
package com.naresh.hello;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
FileSystemXmlApplicationContext("D:\\workspaces\\naresit\\hello_spring\\beans.xml");
In above example Student Object Created by Spring IOC container and we got it by using
getBean() method. If you observe, we are not written code for Student Object Creation i.e.
using new operator.
➢ We can create multiple Bean Objects for same Bean class with multiple bean
configurations in xml file.
So we can provide multiple configurations and create multiple Bean Objects for a class.
Bean Overview:
A Spring IoC container manages one or more beans. These beans are created with the
configuration metadata that you supply to the container (for example, in the form of XML
<bean/> definitions). Every bean has one or more identifiers. These identifiers must be unique
within the container that hosts the bean. A bean usually has only one identifier. However, if
it requires more than one, the extra ones can be considered aliases. In XML-based
configuration metadata, you use the id attribute, the name attribute, or both to specify bean
identifiers. The id attribute lets you specify exactly one id.
If you use XML-based configuration metadata, you specify the type (or class) of object that is
to be instantiated in the class attribute of the <bean/> element. This class attribute (which,
internally, is a Class property on a BeanDefinition instance) is usually mandatory.
1. Setter Injection
2. Constructor Injection
3. Filed Injection
There are many benefits to using dependency injection in Spring. Some of the benefits
include:
• Loose coupling: Dependency injection makes the classes in our application loosely
coupled. This means that the classes are not tightly coupled to the specific
implementations of their dependencies. This makes the classes more reusable and easier
to test.
• Increased testability: Dependency injection makes the classes in our application more
testable. This is because we can inject mock implementations of dependencies into the
classes during testing. This allows us to test the classes in isolation, without having to
worry about the dependencies.
• Increased flexibility: Dependency injection makes our applications more flexible. This is
because we can change the implementations of dependencies without having to change
the classes that depend on them. This makes it easier to change the underlying
technologies in our applications.
Dependency injection is a powerful design pattern that can be used to improve the design
and testability of our Spring applications. By using dependency injection, we can make our
applications more loosely coupled, increase their testability, and improve their flexibility.
Setter Injection:
Setter injection is another way to inject dependencies in Spring. In this approach, we specify
the dependencies in the class setter methods. The Spring container will then create an
instance of the class and then call the setter methods to inject the dependencies.
1. Create a class.
package com.naresh.first.core;
From above configuration, <property> tag referring to setter injection i.e. injecting value to a
variable or property of Bean Student class.
3. Now get the bean object from Spring Container and print properties values.
package com.naresh.first.core;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
1. From the Below Line execution, Spring will create Spring IOC container and Loads our
beans xml file in JVM memory and Creates Bean Objects inside Spring Container.
2. Now from below line, we are getting bean object of Student class configured with bean id
: s1
package com.naresh.hello;
• For primitive and String data type properties of bean class, we can use both name and
value attributes.
• Now let’s test values injected or not from above bean configuration.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
Output:
101
Dilip
2022
99.88
True
Now we are injecting/configuring Collection Data Types like List, Set and Map properties
into Spring Bean Object.
➢ For List data type property, Spring Provided <list> tag, sub tag of <property>.
<list>
<value> … </value>
<value>… </value>
<value> .. </value>
……………….
</list>
➢ For Set data type property, Spring Provided <list> tag, sub tag of <property>.
<set>
➢ For Map data type property, Spring Provided <list> tag, sub tag of <property>.
<map>
<entry key="…" value="…" />
<entry key="…" value="…" />
<entry key="…" value="…" />
……………….
</map>
package com.naresh.hello;
import java.util.List;
import java.util.Map;
import java.util.Set;
• Now let’s test values injected or not from above bean configuration.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
Output:
101
Dilip
2022
99.88
true
[dilip@gmail.com, laxmi@gmail.com, dilip@gmail.com]
[8826111377, +1234567890]
{maths=88, science=66, english=44}
Now we are injecting/configuring other Bean Objects into another Spring Bean Object.
package com.naresh.training.spring.core;
public Address() {
System.out.println("Address instance/constructed ");
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getPincode() {
return pincode;
}
public void setPincode(int pincode) {
this.pincode = pincode;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
package com.naresh.training.spring.core;
public Student() {
System.out.println("Student Constructor executed.");
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getStudentId() {
return studentId;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
➢ Now Configure Address and Student Bean classes. Here, Address Bean Object is
dependency of Student object i.e. Address should be referred inside Student. To achive
this collaboration, Spring provided ref element/attribute.
The ref element is the element inside a <property/> or <constructor-arg/> element. Here,
you set the value of the specified property of a bean to be a referenced to another bean (a
collaborator) managed by the container. Sometimes we can use ref attribute as part of
<property/> or <constructor-arg/>. We will provide bean Id for ref element which should be
<beans>
<bean id="universityAddress"
class="com.naresh.training.spring.core.Address">
<property name="city" value="Bangloore"></property>
<property name="country" value="India"></property>
<property name="pincode" value="400066"></property>
</bean>
<!-- Student Bean Objects -->
<bean id="student1" class="com.naresh.training.spring.core.Student">
<property name="studentName" value="Dilip Singh"></property>
<property name="studentId" value="100"></property>
<property name="address" ref="universityAddress"></property>
</bean>
<bean id="student2" class="com.naresh.training.spring.core.Student">
<property name="studentName" value="Naresh"></property>
<property name="studentId" value="101"></property>
<property name="address">
<ref bean="universityAddress"/>
</property>
</bean>
</beans>
➢ Now let’s test values and references injected or not from above bean configuration.
package com.naresh.training.spring.core;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class SpringSetterInjectionDemo {
Output:
Address instance/constructed
Student Contructor executed.
Student Contructor executed.
************ Student1 Data *********
100
Dilip Singh
Bangloore
India
400066
************ Student2 Data *********
101
Naresh
Bangloore
India
400066
From above output, same universityAddress bean Object is injected by Spring Container
internally inside both student1 and student2 Bean Objects.
Constructor Injection:
package com.naresh.hello;
import java.util.Set;
}
public Address getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(Address customerAddress) {
this.customerAddress = customerAddress;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
package com.naresh.hello;
<bean id="accountDeatils"
class="com.naresh.hello.AccountDetails">
<constructor-arg name="name" value="Dilip" />
<constructor-arg name="balance" value="500.00" />
<constructor-arg name="mobiles">
<set>
<value>8826111377</value>
<value>8826111377</value>
<value>+91-88888888</value>
<value>+232388888888</value>
</set>
</constructor-arg>
<constructor-arg name="customerAddress" ref="addr" />
</bean>
</beans>
package com.naresh.hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
System.out.println(details.getName());
System.out.println(details.getBalance());
System.out.println(details.getMobiles());
System.out.println(details.getCustomerAddress().getFlatNo());
System.out.println(details.getCustomerAddress().getHouseName());
Output:
Dilip
500.0
[8826111377, +91-88888888, +232388888888]
333
Lotus Homes
Setter injection and constructor injection are two common approaches for
implementing dependency injection. Here are the key differences between them:
1. Dependency Resolution: In setter injection, dependencies are resolved and injected into
the target object using setter methods. In contrast, constructor injection resolves
dependencies by passing them as arguments to the constructor.
2. Timing of Injection: Setter injection can be performed after the object is created, allowing
for the possibility of injecting dependencies at a later stage. Constructor injection, on the
other hand, requires all dependencies to be provided at the time of object creation.
3. Flexibility: Setter injection provides more flexibility because dependencies can be changed
or modified after the object is instantiated. With constructor injection, dependencies are
typically immutable once the object is created.
6. Testability: Constructor injection is generally favoured for unit testing because it allows for
easy mocking or substitution of dependencies. By providing dependencies through the
constructor, testing frameworks can easily inject mocks or stubs when creating objects for
testing. Setter injection can also be used for testing, but it may require additional setup or
manipulation of the object's state.
The choice between setter injection and constructor injection depends on the specific
requirements and design considerations of your application. In general, constructor injection
is recommended when dependencies are mandatory and should be set once during object
creation, while setter injection provides more flexibility and optional dependencies can be set
or changed after object instantiation.
Bean wiring, also known as bean configuration or bean wiring configuration, is the process of
defining the relationships and dependencies between beans in a container or application
context. In bean wiring, you specify how beans are connected to each other, how
dependencies are injected, and how the container should create and manage the beans. This
wiring process is typically done through configuration files or annotations.
package com.naresh.hello;
package com.naresh.hello;
package com.naresh.hello;
import java.util.Set;
}
public Address getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(Address customerAddress) {
this.customerAddress = customerAddress;
➢ Beans Configuration in spring xml file. With “ref” attribute we are configuring bean
object each other internally.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
AccountDetails
Address
AreaDeatils
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
}
}
Output:
Dilip
Autowiring feature of spring framework enables you to inject the objects dependency
implicitly. It internally uses setter or constructor injection. In Spring framework, the
“autowire” attribute is used in XML <bean> configuration files to enable automatic
dependency injection. It allows Spring to automatically wire dependencies between beans
without explicitly specifying them in the XML file.
To use autowiring in an XML bean configuration file, you need to define the
“autowire” attribute for a bean definition. The “autowire” attribute accepts different values
to determine how autowiring should be performed. There are many autowiring modes.
1. no : This is the default value. It means no autowiring will be performed, and you need to
explicitly specify dependencies using the appropriate XML configuration using property of
constructor tags.
2. byName : The byName mode injects the object dependency according to name of the
bean i.e. Bena ID. In such case, property name of class and bean ID must be same. It
internally calls setter method. If a match is found, the dependency will be injected.
3. byType: The byType mode injects the object dependency according to type i.e. Data Type
of Property. So property/variable name and bean name can be different int this case. It
internally calls setter method. If a match is found, the dependency will be injected. If
multiple beans are found, an exception will be thrown.
4. constructor: The constructor mode injects the dependency by calling the constructor of
the class. It calls the constructor having large number of parameters.
Here’s an examples of using the “autowire” attribute in an XML bean configuration file.
autowire=no:
public Product() {
System.out.println(“Product Object Created by IOC”);
Now Define Class Order which is having dependency of Product Object i.e. product bean
object should be injected to Order.
Package com.flipkart.orders;
import com.flipkart.product.Product;
public Order() {
System.out.println(“Order Object Created by IOC”);
}
Now let’s configure both Product and Order in side beans xml file.
<beans>
</beans>
Package com.flipkart.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.flipkart.orders.Order;
import com.flipkart.orders.OrdersManagement;
import com.flipkart.product.Product;
Means, Product and Order Object created by Spring but not injected product bean object
automatically in side Order Object by IOC Container with setter injection internally. Because
we used autowire mode as no. By Default autowire value is “no” i.e. Even if we are not given
autowire attribute internally Spring Considers it as autowire=”no”.
autowire=”byName”:
Now configure autowire=”byName” in side beans xml file for order Bean
configuration, because internally Product bean object should be injected to Order Bean
Object.In this autowire mode, We are expecting dependency injection of objects by Spring
instead of we are writing bean wiring with either using <property> and <constructor-arg> tags
by using ref attribute. Means, eliminating logic of reference configurations.
As per autowire=”byName”, Spring internally checks for a dependency bean objects which is
matched to property names of Object. As per our example, Product is dependency for Order
class.
Product class Bean ID = Property Name of Order class
Beans Configuration:
<beans>
<bean id="product" class="com.flipkart.product.Product">
<property name="productId" value="101"></property>
<property name="productName" value="Lenevo Laptop"></property>
</bean>
Question: If property name and Bean ID are different, then Spring will not inject Product
object inside Order Object. Now I made bean id as prod for Product class.
Test Our application and check Spring injected Product object or not inside Order.
autowire=”byType”:
Now configure autowire=”byType” in side beans xml file for Order Bean configuration,
because internally Product bean object should be injected to Order Bean Object. In this
autowire mode, We are expecting dependency injected by Spring instead of we are writing
bean wiring with either using <property> and <constructor-arg> tags by using ref attribute.
Means, eliminating logic of reference configurations.
As per autowire=”byType”, Spring internally checks for a dependency bean objects, which
are matched with Data Type of property and then that bean object will be injected. In this
case Bean ID and Property Names may be different. As per our example, Product is
dependency for Order class.
Bean Data Type i.e. class Name = Data type of property of Order class
Beans Configuration:
<beans>
<bean id="prod" class="com.flipkart.product.Product">
<property name="productId" value="101"></property>
<property name="productName" value="Lenevo Laptop"></property>
</bean>
<bean id="order" class="com.flipkart.orders.Order" autowire="byType">
Test Our Application Now: Injected Successfully, because only One Product Object available.
Question: If Product Bean configured more than one time inside beans configuration, then
which Product Bean Object will be injected in side Order ?
autowire=” constructor”:
Now configure autowire=”constructor” in side beans xml file for Order Bean
configuration, because internally Product bean object should be injected to Order Bean
Object. In this autowire mode, We are expecting dependency injected by Spring instead of we
are writing bean wiring with either using <property> or <constructor-arg> tags by using ref
attribute. Means, eliminating logic of reference configurations.
As per our example, Product is dependency for Order and Order class defined a constructor
with parameter contains Product type.
Beans Configuration:
when autowire =constructor, spring internally checks out of multiple bean ids dependency
object which is matching with property name of Order class. If matching found then that
specific bean object will be injected. If not found then we will get ambiguity exception as
following.
As per our below configuration, both bean ids of Product are not matching with Order class
property name of Product type.
Now if we configure one bean object of Product class with bean id which is matching with
property name of Order class. Then that Specific Object will be injected. From following
configuration Product object of bean id “product” will be injected.
Advantage of Autowiring:
• It requires less code because we don’t need to write the code to inject the dependency
explicitly.
Disadvantage of Autowiring:
• No control of the programmer.
• It can’t be used for primitive and string values.
The Latest Spring Framework supports 5 scopes, last four are available only if you use Web
aware of ApplicationContext i.e. inside Web applications.
1. singleton
In XML configuration, we will use an attribute “scope”, inside <bean> tag as shown below.
singleton:
This is default scope of a bean configuration i.e. even if we are not provided scope
attribute as part of any bean configuration, then spring container internally consideres as
scope=”singleton”.
If Bean scope=singleton, then Spring Container creates only one object in side Spring
container overall application level and Spring Container returns same instance reference
always for every IOC container call i.e. getBean().
Now create Bean class and call IOC container many time with same bean ID.
Product.java
public Product() {
System.out.println("Product Object Created by IOC");
}
Output:
NOTE: If we created another bean id configuration for same class, then previous configuration
behaviour will not applicable to current configuration i.e. every individual bean configuration
or Bean Object having it’s own behaviour and functionality in Spring Framework.
public Product() {
System.out.println("Product Object Created by IOC");
}
Testing :
session:
When we apply scope as session, then for every new HTTP session creation in server side
Spring will crates new instance of configured bean. Only valid in the context of a web-aware
Spring ApplicationContext i.e. in web/MVC applications.
application:
Once you have defined the application-scoped bean, Spring will create a single instance of the
bean per web application context. Any requests for this bean within the same web application
will receive the same instance.
It's important to note that the application scope is specific to web applications and relies on
the lifecycle of the web application context. Each web application running in a container will
have its own instance of the application-scoped bean.
You can use application-scoped beans to store and share application-wide state or resources
that need to be accessible across multiple components within the same web application.
websocket:
This is used as part of socket programming. We can’t use in our Servlet based MVC
application level.
In Java Spring, the @Configuration annotation is used to indicate that this class is a
configuration class of Beans. A configuration class is responsible for defining beans and their
dependencies in the Spring application context. Beans are objects that are managed by the
Spring IOC container. Annotating a class with the @Configuration indicates that the class can
be used by the Spring IOC container as a source of bean definitions.
Create a Java class and annotate it with @Configuration. This class will serve as our
configuration class.
@Bean:
NOTE: Added one extra jar file comparing with previous project setup. Because internally
Spring using AOP functionalities to process annotations and we can ignore it.
package com.amazon.users;
Now Create a Beans Configuration class. i.e. Class Marked with an annotation
@Configuration. In side this configuration class, we will define multiple bean configurations
with @Bean annotation methods.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeansConfiguration {
@Bean("userDetails")
UserDetails getUserDetails() {
}
}
The above code will be equivalent to the following XML bean configuration −
<beans>
<bean id = " userDetails " class = " com.amazon.users.UserDetails " />
</beans>
package com.amazon;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfiguration;
import com.amazon.users.UserDetails;
context.close();
}
com.amazon.users.UserDetails@34bde49d
AnnotationConfigApplicationContext:
Now we can configure multiple bean classes inside multiple configuration classes as well
as Same bean with multiple bean id’s.
package com.amazon.products;
Configuring above POJO class as Bean class inside Beans Configuration class.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import com.amazon.products.ProductDetails;
@Bean("productDetails")
ProductDetails productDetails() {
return new ProductDetails();
}
}
Testing Bean Object Created or not. Below Code loading Two Configuration classes.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfiguration;
import com.amazon.config.BeansConfigurationTwo;
import com.amazon.products.ProductDetails;
import com.amazon.users.UserDetails;
public class SpringBeanMainApp {
context.refresh();
context.close();
}
➢ Inside Configuration class: Two Bean configurations for ProductDetails Bean class.
import org.springframework.context.annotation.Bean;
import com.amazon.products.ProductDetails;
@Bean("productDetails")
ProductDetails productDetails() {
return new ProductDetails();
}
@Bean("productDetailsTwo")
ProductDetails productTwoDetails() {
return new ProductDetails();
}
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfiguration;
import com.amazon.config.BeansConfigurationTwo;
import com.amazon.products.ProductDetails;
import com.amazon.users.UserDetails;
context.register(BeansConfiguration.class);
context.register(BeansConfigurationTwo.class);
context.refresh();
context.close();
}
}
Output:
com.amazon.users.UserDetails@7d3e8655
com.amazon.products.ProductDetails@7dfb0c0f
com.amazon.products.ProductDetails@626abbd0
From above Output Two ProductDetails bean objects created by Spring Container.
@Component Annotation :
@Component: This annotation that allows Spring to detect our custom beans automatically.
In other words, without having to write any explicit code, Spring will:
We have other more specialized stereotype annotations like @Controller, @Service and
@Repository to serve this functionality derived , we will discuss then in MVC module level.
package com.tek.teacher;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
public class Product {
public Product(){
System.out.println(“Product Object Created.”);
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public double getPrice() {
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
context.scan("com.tek. teacher");
context.refresh();
}
}
From Above program, context.scan() method, Perform a scan for @Component classes to
instantiate Bean Objects within the specified base packages. We can pass many package
names wherever we have @Componet Classes. Note that, scan(basePackages) method will
scans @Confguraion classes as well from specified package names. Note that refresh() must
be called in order for the context to fully process the new classes.
Spring Provided One more way which used mostly in Real time applications is using
@ComponentScan annotation. To enable auto detection of Spring components, we shou use
another annotation @ComponentScan.
@ComponentScan:
Before we rely entirely on @Component, we must understand that it's only a plain
annotation. The annotation serves the purpose of differentiating beans from other objects,
such as domain objects. However, Spring uses the @ComponentScan annotation to gather all
component into its ApplicationContext.
Or If only one base package and it’s sub packages should be scanned, then we can directly
pass package name.
@ComponentScan("com.hello.spring.*")
@Configuration
// making sure scanning all packages starts with
com.tek.teacher
@ComponentScan("com.tek.teacher.*")
public class BeansConfiguration {
➢ Now Load/pass above configuration class to Application Context i.e. Spring Container.
package com.tek.teacher;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
context.register(BeansConfiguration.class);
context.refresh();
Output:
ProductDetails [pname=null, price=0.0]
From above, Spring Container detected @Component classes from all packages and
instantiated as Bean Objects.
package com.tek.teacher;
import org.springframework.stereotype.Component;
@Component
public class UserDetails {
public UserDetails(){
System.out.println(“UserDetails Object Created”);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
➢ Now get UserDetails from Spring Container and Test/Run our Main class.
package com.tek.teacher;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
context.register(BeansConfiguration.class);
context.refresh();
//UserDetails Component
UserDetails userDetails = context.getBean(UserDetails.class);
System.out.println(userDetails);
}
}
Output: com.tek.teacher.UserDetails@5e17553a
Yes, Similar to @Bean annotation level however we are assigning scope type , we can pass in
same way with @Component class level because Component is nothing but Bean finally.
Ex : From above example, requesting another Bean Object of type UserDetails without
configuring scope at component class level.
package com.tek.teacher;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
UserDetails userDetails = context.getBean(UserDetails.class);
System.out.println(userDetails);
}
}
Output:
com.tek.teacher.UserDetails@5e17553a
com.tek.teacher.UserDetails@5e17553a
So we can say by default component classes are instantiated as singleton bean object, when
there is no scope defined. Means, Internally Spring Container considering as singleton scope.
Yes, We can create Bean Configurations in side Spring Configuration classes. With That Bean
ID, we can request from Application Context, as usual.
package com.tek.teacher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.tek.*")
public class BeansConfiguration {
@Bean("user")
UserDetails getUserDetails() {
return new UserDetails();
}
package com.tek.teacher;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
UserDetails userThree = (UserDetails) context.getBean("user");
System.out.println(userThree);
}
}
Output:
com.tek.teacher.UserDetails@3eb91815
package com.tek.teacher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.tek.*")
public class BeansConfiguration {
@Bean("user")
UserDetails getUserDetails() {
UserDetails user = new UserDetails();
user.setEmailId("dilip@gmail.com");
user.setMobile(8826111377l);
return user;
}
}
Main App:
package com.tek.teacher;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
context.register(BeansConfiguration.class);
context.refresh();
// UserDetails Component
UserDetails userThree = (UserDetails) context.getBean("user");
System.out.println(userThree.getEmailId());
System.out.println(userThree.getMobile());
}
}
Output:
In XML configuration, we will use an attribute “scope”, inside <bean> tag as shown below.
@Scope: A bean’s scope is set using the @Scope annotation. By default, the Spring
framework creates exactly one instance for each bean declared in the IoC container. This
instance is shared in the scope of the entire IoC container and is returned for all subsequent
getBean() calls and bean references.
package com.amazon.products;
Singleton Scope:
A single Bean object instance created and returns same Bean instance for each Spring IoC
container call i.e. getBean(). In side Configuration class, scope value defined as singleton.
NOTE: If we are not defined any scope value for any Bean Configuration, then Spring
Container by default considers scope as singleton.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.amazon.products.ProductDetails;
@Configuration
public class BeansConfigurationThree {
@Scope("singleton")
@Bean("productDetails")
ProductDetails getProductDetails() {
return new ProductDetails();
}
➢ Now Test Bean ProdcutDetails Object is singleton or not. Request multiple times
ProductDetails Object from Spring Container by passing bean id productDetails.
package com.amazon;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfigurationThree;
import com.amazon.products.ProductDetails;
context.register(BeansConfigurationThree.class);
context.refresh();
context.close();
}
}
Output:
com.amazon.products.ProductDetails@58e1d9d
com.amazon.products.ProductDetails@58e1d9d
From above output, we can see same hash code printed for both getBean() calls on Spring
Container. Means, Container created singleton instance for bean id “productDetails”.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.amazon.products.ProductDetails;
@Configuration
public class BeansConfigurationThree {
@Scope("singleton")
@Bean("productDetails")
ProductDetails getProductDetails() {
return new ProductDetails();
}
@Scope("prototype")
@Bean("productTwoDetails")
ProductDetails getProductTwoDetails() {
return new ProductDetails();
}
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfigurationThree;
import com.amazon.products.ProductDetails;
context.register(BeansConfigurationThree.class);
context.refresh();
//Prototype Beans:
ProductDetails productThree = (ProductDetails)
context.getBean("productTwoDetails");
System.out.println(productThree);
context.close();
Output:
com.amazon.products.ProductDetails@12591ac8
com.amazon.products.ProductDetails@5a7fe64f
From above output, we can see different hash codes printed for both getBean() calls on Spring
Container. Means, Container created new instance every time when we requested for
instance of bean id “productTwoDetails”.
@Scope("prototype")
@Component
public class UserDetails {
//Properties
//Setter & Getters
// Methods
}
Now test from Main application class, whether we are getting new Instance or not for every
request of Bena Object UserDetails from Spring Container.
package com.tek.teacher.products;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
context.register(BeansConfiguration.class);
context.scan("com.tek.*");
context.refresh();
// UserDetails Component
UserDetails userDetails = context.getBean(UserDetails.class);
System.out.println(userDetails);
}
}
Output:
com.tek.teacher.UserDetails@74f6c5d8
com.tek.teacher.UserDetails@27912e3
NOTE: Below four are available only if you use a web-aware ApplicationContext i.e. inside
Web applications.
➢ no
➢ byName
➢ byType
➢ constructor
In XML configuration, we will enable auto wring between Beans as shown below.
1. On properties
2. On setter
3. On constructor
@Autowired on Properties:
Let’s see how we can annotate a property using @Autowired. This eliminates the need
for getters and setters.
package com.dilip.account;
import org.springframework.stereotype.Component;
@Component
public class Address {
Now Define, Another component class Account and define Address type property inside as a
Dependency property.
package com.dilip.account;
@Component
public class Account {
// Field/Property Level
@Autowired
private Address addr;
➢ Create a configuration class, and define Component Scan packages to scan all packages.
package com.dilip.account;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.dilip.*")
public class BeansConfiguration {
➢ Now Define, Main class and try to get Account Bean object and check really Address
Bean Object Injected or Not.
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
Account account = (Account) context.getBean(Account.class);
//Getting Injected Object of Address
Address address = account.getAddr();
address.setPincode(500072);
System.out.println(address);
}
}
Output:
Address [streetName=null, pincode=500072]
So, Dependency Object Address injected in Account Bean Object implicitly, with @Autowired
on property level.
package com.hello.spring.boot.employees;
import org.springframework.stereotype.Component;
@Component("home")
public class Addresss {
➢ For above Address class create a Bean configuration in Side Configuration class.
package com.hello.spring.boot.employees;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.hello.spring.boot.*")
public class BeansConfig {
@Bean("hyd")
Addresss createAddress() {
Addresss a = new Addresss();
a.setPincode(500067);
a.setStreetName("Gachibowli");
return a;
}
package com.hello.spring.boot.employees;
@Component("emp")
public class Employee {
@Autowired
private Addresss add;
➢ Now Test which Address Object Injected by Container i.e. either home or hyd bean
object.
package com.hello.spring.boot.employees;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
}
}
We got an exception now as,
i.e. Spring Container unable to inject Address Bean Object into Employee Object because of
Ambiguity/Confusion like in between home or hyd bean Objects of Address type.
@Qualifier:
By using the @Qualifier annotation, we can eliminate the issue of which bean needs to be
injected. There may be a situation when you create more than one bean of the same
type and want to wire only one of them with a property. In such cases, you can use
the @Qualifier annotation along with @Autowired to remove the confusion by specifying
which exact bean will be wired.
We need to take into consideration that the qualifier name to be used is the one declared in
the @Component or @Bean annotation.
package com.hello.spring.boot.employees;
@Component("emp")
public class Employee {
@Qualifier("hyd")
@Autowired
private Addresss add;
➢ Now Test which Address Bean Object with bean Id “hyd” Injected by Container.
package com.hello.spring.boot.employees;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output:
500067
Gachibowli
i.e. Address Bean Object Injected with Bean Id called as hyd into Employee Bean Object.
@Primary:
There's another annotation called @Primary that we can use to decide which bean to
inject when ambiguity is present regarding dependency injection. This annotation defines a
preference when multiple beans of the same type are present. The bean associated with
the @Primary annotation will be used unless otherwise indicated.
Now add One more @Bean config for Address class inside Configuration class.
package com.hello.spring.boot.employees;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
@ComponentScan("com.hello.spring.boot.*")
public class BeansConfig {
@Bean("hyd")
Addresss createAddress() {
Addresss a = new Addresss();
a.setPincode(500067);
a.setStreetName("Gachibowli");
return a;
}
package com.hello.spring.boot.employees;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("emp")
public class Employee {
I.e. Address Bean Object with “banglore" injected in Employee object level.
NOTE: if both the @Qualifier and @Primary annotations are present, then
the @Qualifier annotation will have precedence/priority. Basically, @Primary defines a
default, while @Qualifier is very specific to Bean ID.
In Java, Interface reference can hold Implemented class Object. With this rule, We can
Autowire Interface references to inject implemented component classes.
package com.dilip.auto.wiring;
package com.dilip.auto.wiring;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal {
@Override
public void printNameOfAnimal() {
System.out.println("I am a Tiger ");
}
}
package com.dilip.auto.wiring;
import org.springframework.context.annotation.ComponentScan;
@Configuration
@ComponentScan("com.dilip.*")
public class BeansConfig {
➢ Now Autowire Animal type property in any other Component class i.e. Dependency of
Animal Interface implemented class Object Tiger should be injected.
package com.dilip.auto.wiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AnimalManagement {
@Autowired
//Interface Type Property
Animal animal;
Now Test, Animal type property injected with what type of Object.
package com.dilip.auto.wiring;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
animalMgmt.animal.printNameOfAnimal();
Output:
I am a Tiger
So, implicitly Spring Container Injected one and only implanted class Tiger of Animal Interface
inside Animal Type reference property of AnimalManagement Object.
If we have multiple Implemented classes for same Interface i.e. Animal interface, How
Spring Container deciding which implanted Bean object should Injected?
package com.dilip.auto.wiring;
import org.springframework.stereotype.Component;
@Component("lion")
public class Lion implements Animal {
@Override
public void printNameOfAnimal() {
System.out.println("I am a Lion ");
}
}
Now Test, Animal type property injected with what type of Object either Tiger or Lion.
package com.dilip.auto.wiring;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
So to avoid again this ambiguity between multiple implementation of single interface, again
we can use @Qualifier with Bean Id or Component Id.
package com.dilip.auto.wiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
Now it will inject only Lion Object inside AnimalManagement Object as per Qualifier
annotation value out of lion and tiger bean objects.
Output :
I am a Lion.
Can we inject Default implemented class Object out of multiple implementation classes
into Animal reference if not provided any Qualifier value?
Yes, we can inject default Implementation bean Object of Interface. We should mark one class
as @Primary. Now I marked Tiger class as @Primary and removed @Qualifier from
AnimalManagement.
package com.dilip.auto.wiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AnimalManagement {
@Autowired
Animal animal;
}
Output :
I am a Tiger
Filed Injection:
As the name says, the dependency is injected directly in the field, with no constructor
or setter needed. This is done by annotating the class member with the @Autowired
annotation. If we define @Autowired on property/field name level, then Spring Injects
Dependency Object directly into filed.
package com.dilip.spring;
import org.springframework.stereotype.Component;
@Component
public class Address {
public Address() {
System.out.println("Address Object Created.");
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getPincode() {
return pincode;
}
public void setPincode(int pincode) {
this.pincode = pincode;
package com.dilip.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Employee {
//Field Injection
@Autowired
private Address address;
package com.dilip.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
}
}
Output:
Address Object Created.
Employee Object Created
Address Object Created.
com.dilip.spring.Employee@791f145a
com.dilip.spring.Address@38cee291
Setter injection uses the setter method to inject dependency on any Spring-
managed bean. Well, the Spring IOC container uses a setter method to inject dependency
on any Spring-managed bean. We have to annotate the setter method with the
@Autowired annotation.
Interface : MessageService.java
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component("emailService")
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component("smsService")
public class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
We have annotated SMSService class with @Component annotation so the Spring container
automatically creates a Spring bean and manages its life cycle.
MessageSender.java
In setter injection, Spring will find the @Autowired annotation and call the setter to
inject the dependency.
package com.dilip.setter.injection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MessageSender {
➢ Now create a Test class to validate, dependency injection with setter Injection.
package com.dilip.setter.injection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output:
setter based dependency injection
Hi, good morning have a nice day!.
Let's see how to inject multiple dependencies using Setter injection. To inject multiple
dependencies, we have to create multiple fields and their respective setter methods. In the
below example, the MessageSender class has multiple setter methods to inject multiple
dependencies using setter injection:
package com.dilip.setter.injection;
@Component
public class MessageSender {
@Autowired
public void setMessageService(@Qualifier("emailService") MessageService
messageService) {
this.messageService = messageService;
System.out.println("setter based dependency injection");
}
@Autowired
public void setSmsService(MessageService smsService) {
this.smsService = smsService;
System.out.println("setter based dependency injection 2");
}
➢ Now Run Client.java, One more time to see both Bean Objects injected or not.
Output:
setter based dependency injection 2
setter based dependency injection
Hi, good morning have a nice day!.
Hi, good morning have a nice day!.
package com.dilip.setter.injection;
EmailService.java
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
We have annotated EmailService class with @Component annotation so the Spring container
automatically creates a Spring bean and manages its life cycle.
SMSService.java
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component("smsService")
public class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
We have annotated SMSService class with @Component annotation so the Spring container
automatically creates a Spring bean and manages its life cycle.
MessageSender.java
package com.dilip.setter.injection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MessageSender {
package com.dilip.setter.injection;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.dilip.*")
public class AppConfig {
➢ Now create a Test class to validate, dependency injection with setter Injection.
package com.dilip.setter.injection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output:
constructor based dependency injection
Hi, good morning have a nice day!.
When we discussed of autowiring with beans XML configurations, Spring Provided 4 types
autowiring configuration values for autowire attribute of bean tag.
1. no
2. byName
3. byType
4. constructor
But with annotation Bean configurations, we are not using these values directly because we
are achieving same functionality with @Autowired and @Qualifier annotations directly or
indirectly.
constructor : when we are using @Autowired and @Qulaifier along with constructor, then
Spring IOC container will inject Dependency Object via constructor.
So explicitly we no need to define any autowiring type with annotation based Configurations
like in XML configuration.
Spring bean is a Java object managed by the Spring IoC container. These objects can
be anything, from simple data holders to complex business logic components. The magic lies
in Spring’s ability to manage the creation, configuration, and lifecycle of these beans.
Bean life cycle is managed by the spring container. When we run the program then,
first of all, the spring container gets started. After that, the container creates the instance of
a bean as per configuration, and then dependencies are injected. After utilization of Bean
Object and then finally, the bean is destroyed when the spring container is closed.
Therefore, if we want to execute some code on the bean instantiation and just after
closing the spring container, then we can write that code inside the custom init() method and
the destroy() methods.
➢ Resource Management: As you traverse the life cycle stages of Bean Object, you’re in
control of resources. This translates to efficient memory utilization and prevents resource
leaks, ensuring your application runs like a well configured machine.
➢ Debugging: With a firm grasp of the life cycle, troubleshooting becomes very easy. By
tracing a bean’s journey through each stage, you can pinpoint issues and enhance the
overall stability of your application.
Spring allows us to attach custom actions to bean creation and destruction. We can
do it by implementing the InitializingBean and DisposableBean interfaces.
InitializingBean:
When the Spring container initializes the Bean instance, it will first set any properties
configured, and then it will call the afterPropertiesSet() method automatically. This allows
you to perform any custom initialization tasks within that method.
DisposableBean:
The DisposableBean interface defines a single method, destroy(), which a bean class
must implement to carry out any cleanup logic.
When the Spring container is shutting down or removing the bean, it will call the destroy()
method automatically, allowing you to perform any necessary cleanup tasks.
package com.dilip;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
@Component
public class Customer implements InitializingBean, DisposableBean {
public Customer() {
System.out.println("Customer Object is Created");
}
The following image shows the process flow of the Bean Object life cycle.
➢ Now create Spring IOC container instance and try to get Bean Object and then close the
container Instance.
➢ Creating Beans Configuration class.
package com.dilip;
@ComponentScan("com.dilip")
@Configuration
public class BeansConfiguration {
package com.dilip;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output:
➢ Adding a Bean Method inside Configuration class for another Customer Object and then
we will see same process followed for new Bean Object as usually.
BeansConfiguration.java
package com.dilip;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.dilip")
@Configuration
public class BeansConfiguration {
@Bean(name="customer2")
Customer getCustomer() {
return new Customer();
}
}
➢ Now Execute container creation and closing Lofigc again and observe initialization and
destroy methods executed 2 times for 2 Customer Bean Objects creation.
package com.dilip;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output : For Every bean Object, executed both actions of initialization and destroy.
This is how we can define lifecycle methods explicitly to provide instantiation logic and
destruction logic for a bean Object.
Note: Same above approach of writing Bean class with InitializingBean and DisposableBean,
can be followed in Spring Beans XML configuration for a Bean class and Objects.
Question: Do we have any other ways to define life cycle methods apart from
InitializingBean and DisposableBean?
Note: Both @PostConstruct and @PreDestroy annotations are part of Java EE. Since Java EE
was deprecated in Java 9, and removed in Java 11, we have to add an additional dependency
in pom.xml to use these annotations.
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
Define these annotations on custom methods of Bean instantiation and destroying logic with
out using any Predefined Interfaces from Spring FW.
@PreDestroy:
Spring calls the methods annotated with @PreDestroy runs only once, just before
Spring removes our bean from the application context.
Note: @PostConstruct and @PreDestroy annotated methods can have any access level, but
can’t be static.
package com.dilip;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class Customer {
public Customer() {
System.out.println("Customer Object is Created");
}
@PostConstruct
public void init() {
System.out.println("This is Init logic from init()");
}
@PreDestroy
public void destroy() {
System.out.println("This is destroying logic from destroy()");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
package com.dilip;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.dilip")
@Configuration
public class BeansConfiguration {
@Bean(name="customer2")
Customer getCustomer() {
return new Customer();
}
}
➢ Now Execute container creation and closing Lofigc again and observe initialization and
destroy methods executed 2 times for 2 Customer Bean Objects creation.
package com.dilip;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output : For Every bean Object, executed both actions of initialization and destroy.
Yes, We can Define custom methods with user defined names of methods of both initialization
and destroying actions.
package com.dilip;
public Student() {
System.out.println("Student Constructor : Object Created");
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
// For Initialization
public void beanInitialization() {
System.out.println("Bean Initialization Started... ");
}
// For Destruction
public void beanDestruction() {
System.out.println("Bean Destruction Started..... ");
}
}
In XML Configuration :
<beans>
<bean id="student" class="com.dilip.Student"
init-method="beanInitialization"
destroy-method="beanDestruction">
</bean>
</beans>
➢ Now Instantiate and close Spring Container and then container will execute life cycle
methods as per our configuration of a bean Object.
Understanding the life cycle of Spring beans is like having a backstage pass to the inner
workings of your Spring application. A solid grasp of the bean life cycle empowers you to
effectively manage resources, configure beans, and ensure proper initialization and cleanup.
With this knowledge, you can optimize your application’s performance, prevent memory
leaks, and implement custom logic at various stages of a bean’s existence.
• Choose Maven and the language Java, Spring Boot Version we want.
• Click Dependencies and select required modules.
• Now fill all details of Project Metadata like project name and package details.
• Click Generate.
• Download the resulting ZIP file, which is an archive i.e. zip file of application that is
configured with your choices.
• Now you can import project inside Eclipse IDE or any other IDE’s.
STS stands for "Spring Tool Suite." It is an integrated development environment (IDE)
based on Eclipse and is specifically designed for developing applications using the Spring
Framework, including Spring Boot projects. STS provides a range of tools and features that
streamline the development process and enhance productivity for Spring developers.
➢ It will download STS as a jar file. Double click on jar, it will extract STS software.
➢ Open STS, Now create Project. File -> New -> Spring Starter Project.
If we observe, we are not added any jar files manually or externally to project like
however we did in Spring Framework to work with Core Module. This is mot biggest
advantage of Spring Boot Framework because in future when we are working with other
modules specifically, we no need to find out jar files information and no need to add manually.
Now It’s all about writing logic in project instead of thinking about configuration and project
setup.
While Project creation, By default Spring Boot will generates a main method class as shown
in below.
We will discuss about this Generated class in future, but not this point because we should
understand other topics before going internally.
package com.dilip.beans;
public Student() {
System.out.println("Student Object Created");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public long getMobile() {
return mobile;
}
public void setMobile(long mobile) {
this.mobile = mobile;
}
}
package com.dilip.beans;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
So Please Practice all examples of Spring framework what we discussed previously w.r.to
XML and Java Based configuration.
@Value Annotation:
This @Value annotation can be used for injecting values into fields in Spring-managed
beans, and it can be applied at the field or constructor/method parameter level. We can read
spring environment variables as well as system variables using @Value annotation.
Package: org.springframework.beans.factory.annotation.Value;
@Value("Dilip Singh")
private String defaultName;
@Value annotation argument can be a string only, but spring tries to convert it to the
specified type. Below code will work fine and assign the boolean and int values to the variable.
@Value("true")
private boolean isJoined;
@Value("10")
private int count;
As part of @Value we should pass property name as shown in below signature along with
Variables.
Syntax: @Value("${propertyName}")
We will define properties in side properties/yml file, we can access them with @Value
annotation.
application.properties:
bank.name=CITI BANK
bank.main.location=USA
bank.total.emplyees=40000
citi.db.userName=localDatabaseName
package com.bank.city;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class CitiBank {
@Value("${citi.db.userName}")
String dbName;
@Value("${bank.total.emplyees}")
int totalEmplyeCount;
package com.bank.city.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@ComponentScan("com.*")
@Configuration
@PropertySource("application.properties")
public class BeansConfiguration {
Testing :
Sometimes, we need to inject List of values for one property. It would be convenient
to define them as comma-separated values for the single property in the properties file and
to inject into an array.
@Value(“${trainingCourses}”)
List<String> courses;
Map property : We can also use the @Value annotation to inject a Map property.
First, we'll need to define the property in the {key: ‘value' } form in our properties file:
@Value("#{${course.fees}}")
Map<String, Integer> prices;
@Value is defined at method level, If the method has multiple arguments, then every
argument value is mapped from the method annotation.
@Value("Test")
public void printValues(String value1, String value2){
If we want different values for different arguments then we can use @Value annotation
directly with the argument.
@Value("Test")
public void printValues(String value1, @Value("Data") String value2){
// value1=Test, value2=Data
@Order Annotation:
In Spring Boot, the @Order annotation is used to specify the order in which Spring
beans should be instantiated and initialized. It's often used when you have multiple
components that implement the same interface or extend the same class, and you want to
control the order in which they are injected by Spring Container as part of Collection
Instances. The @Order annotation in Spring defines the sorting order of beans or
components.
Many times we face situations where we require the beans or dependencies to be injected in
a particular order. Some of the common use-cases are:
Package: org.springframework.core.annotation.Order;
@Component
@Order(1)
public class MyFirstComponent {
// ...
}
@Component
@Order(2)
public class MySecondComponent {
//...
}
@Component
@Order(-1)
public class MyHighPriorityComponent {
//….
}
Components with a lower order value are processed before those with a higher order value.
We can also use negative values if you want to indicate a higher precedence. For example, if
we want a component to have the highest precedence, you can use a negative values like -1.
If you have multiple beans with the same order value, the initialization order among them is
not guaranteed.
Example: For this, I’m taking a very simple example. Here, Let’s have a Notification interface.
This interface has one method send(). We also have different implementations of this
interface. Basically, each implementation represents a different channel or medium to send
notifications.
package com.dilip.notifications;
/*
* A Simple interface having just one method send()
*/
public interface Notification{
void send();
}
package com.dilip.notifications;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(1)
public class SmsNotification implements Notification {
public SmsNotification() {
System.out.println("SmsNotification Service created.");
}
@Override
public void send() {
System.out.println("Sending SMS Notification Handler");
}
}
➢ EmailNotification.java
package com.dilip.notifications;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(2)
public class EmailNotification implements Notification {
public EmailNotification() {
System.out.println("EmailNotification Service Created.");
}
➢ TwitterNotification.java
package com.dilip.notifications;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(3)
public class TwitterNotification implements Notification {
public TwitterNotification() {
System.out.println("TwitterNotification Service created.");
}
@Override
public void send() {
System.out.println("Sending Twitter Notification Handler");
}
}
So, let’s now try sending a notification to all possible channels i.e. through all available
implementations of Notification. To do so, we will need List<Notification> to be injected.
In our ordering, we have given the highest priority to SmsNotification by giving @Order(1) as
compared to others. So, that should be the first in the output. Also, we have given no 3 to
TwitterNotification so this should come in the last always. In Below Same List Objects of
Notifications component order will be followed as we defined via @Order.
package com.dilip.notifications;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AllNotifications {
@Autowired
Testing:
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.notifications.AllNotifications;
@SpringBootApplication
public class OrderComponentsApplication {
public static void main(String[] args) {
ApplicationContext context
= SpringApplication.run(OrderComponentsApplication.class, args);
Output: And here you go. It printed in the exact order we mentioned.
So, Spring Sorted the Notification Bean Objects while adding to List instance internally by
following @Order value.
Since we have annotated with @Order you believe that their instantiation will also follow the
same order, right?
However, that’s not the case. Though the concept of @Order looks very simple, sometimes
people get confused about its behaviour. The ordering works only at the time of injecting the
beans/services, not at the time of their creation.
So, clearly we can see that the order of creation is different that order of injection from above
execution.
We can also order Injecting Objects of Collections in Spring by putting @Order annotation on
the @Bean methods.
Consider, there are three @Bean methods and each of them returns a String.
@Bean
@Order(2)
public String getString1() {
return "one";
}
@Bean
@Order(3)
String getString2() {
return "two";
}
@Bean
@Order(1)
String getString3() {
return "three";
}
@Autowired
public FileProcessor(List<String> stringList) {
this.stringList = stringList;
}
Spring sorts the beans in the specified order. Thus, printing the list we get:
Similarly, when we are injecting a multiple beans of same type as a collection we can set a
custom sort order on the individual bean classes.
Ordered Interface:
In Spring Framework & Spring Boot, the Ordered interface is used to provide a way to
specify the order in which objects should be processed. This interface defines a single method,
getOrder(), which returns an integer value representing the order of the object. Objects with
lower order values are processed before objects with higher order values. This is similar to
@Order Annotation functionality.
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class MyOrderedComponent implements Ordered {
@Override
public int getOrder() {
// Specify the order of this component
// Lower values mean higher precedence
return 1;
}
In this example, the MyOrderedComponent class implements the Ordered interface and
specifies an order value of 1.
2. When Spring Boot initializes the beans, it will take into account the getOrder() method to
determine the processing order of your component.
3. Components that implement Ordered interface can be used in various contexts where
order matters, such as event listeners, filters, and other processing tasks.
4. To change the processing order, simply modify the return value of the getOrder() method.
Lower values indicate higher precedence.
Runners in SpringBoot :
Runners in Spring Boot are beans that are executed after the Spring Boot application has been
started. They can be used to perform any one-time initialization tasks, such as loading data,
configuring components, or starting background processes.
1. ApplicationRunner : This runner is executed after the Spring context has been loaded, but
before the application has started. This means that you can use it to access any beans that
have been defined in the Spring context.
2. CommandLineRunner : This runner is executed after the Spring context has been loaded,
and after the command-line arguments have been parsed. This means that you can use it
to access the command-line arguments that were passed to the application.
To implement a runner, you need to create a class that implements the appropriate interface.
The run() method of the interface is where you will put your code that you want to execute.
CommandLineRunner:
1. Create a Java class that implements the CommandLineRunner interface. This class should
override the run() method, where you can define the code you want to execute.
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// Your code to be executed after the application starts
System.out.println("Hi from CommandLineRunner!");
// You can put any initialization logic or tasks here.
}
}
2. When we run our Spring Boot application, the run() method of your CommandLineRunner
implementation will be executed automatically after the Spring context has been initialized.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestingApplication {
public static void main(String[] args) {
SpringApplication.run(TestingApplication.class, args);
}
}
When we run this Spring Boot application, the run() method of your MyCommandLineRunner
class (or any other CommandLineRunner implementations) will be executed after the
application has started.
This is a useful mechanism for tasks like database initialization, data loading, or any other
setup code that should be executed once your Spring Boot application is up and running.
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Order(2)
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// Your code to be executed after the application starts
System.out.println("Hi from CommandLineRunner!");
// You can put any initialization logic or tasks here.
}
}
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunnerTwo implements CommandLineRunner, Ordered {
@Override
public void run(String... args) throws Exception {
System.out.println("Hi from MyCommandLineRunnerTwo!");
// You can put any initialization logic or tasks here.
}
@Override
public int getOrder() {
return 1;
}
}
In Spring Boot, both CommandLineRunner and ApplicationRunner are interfaces that allow
you to execute code after the Spring application context has been fully initialized. They serve
a similar purpose but differ slightly in the way they accept and handle command-line
arguments.
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class MyRunners implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Using ApplicationRunner");
System.out.println("Non-option args: " + args.getNonOptionArgs());
System.out.println("Option names: " + args.getOptionNames());
System.out.println("Option values: " + args.getOptionValues("myOption"));
}
}
Argument Handling:
CommandLineRunner: The run() method of CommandLineRunner receives an array of String
arguments (String... args). These arguments are the command-line arguments passed to the
application when it starts.
Use Cases:
CommandLineRunner: It is suitable for simple cases where you need access to raw command-
line arguments as plain strings. For example, if you want to extract specific values or flags
from command-line arguments.
ApplicationRunner: It is more versatile and powerful when dealing with complex command-
line argument scenarios. It provides features like option values, non-option arguments, option
names, and support for argument validation. This makes it well-suited for applications with
more advanced command-line parsing requirements.
RowMapper: A RowMapper is an interface used to map rows from a database result set to
Java objects. It defines a method to convert a row into an object of a specific class.
Here are some of the basic steps involved in using Spring Boot JDBC:
• Create a JdbcTemplate.
• Execute a JDBC query.
Similarly Spring / Spring Boot JDBC module provided many predefined classes and methods
to perform all database operations whatever we can do with JDBC API.
NOTE: Please be ready with Database table before writing JDBC logic.
Steps for Spring Boot JDBC Project:
Note: I am using Oracle Database for all examples. If you are using another database other
than Oracle, We just need to replace URL, User Name and Password of other database.
➢ Open STS and Create Project with Spring Boot Data JDBC dependency.
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
➢ Create a Component class for doing Database operations. Inside class, we have to
autowire JdbcTemplate to utilize pre-defined functionalities.
package com.dilip;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class DataBaseOperations {
@Autowired
JdbcTemplate jdbcTemplate;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringBootJdbcDemoApplication {
This is how Spring boot JDBC module simplified Database operations will very less amount of
code.
Let’s perform other database operations.
Requirement: Load all Product Details from Database as List of Product Objects.
➢ Here we have to create a POJO class of Product with properties.
package com.dilip;
import lombok.Data;
@Data
public class Product {
int id;
String name;
int price;
}
package com.dilip;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
@Autowired
JdbcTemplate jdbcTemplate;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringBootJdbcDemoApplication {
ApplicationContext context =
SpringApplication.run(SpringBootJdbcDemoApplication.class, args);
}
}
➢ Now verify in Console Output. All Records are loaded and converted as Lis of Product
Objects.
package com.dilip;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class DataBaseOperations {
@Autowired
JdbcTemplate jdbcTemplate;
//delete product by id
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringBootJdbcDemoApplication {
package com.dilip;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class DataBaseOperations {
@Autowired
JdbcTemplate jdbcTemplate;
Testing:
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
Table Creation : create table student(sid number(10), name varchar2(50), age number(3));
Please add Specific jar files which are required for JDBC module, as followed.
Project Structure : for jar files reference
• Please Create Configuration class for Configuring JdbcTemplate Bean Object with
DataSource Properties. So Let's start with some simple configuration of the data source.
• We are using Oracle database:
• The DriverManagerDataSource is used to contain the information about the database
such as driver class name, connection URL, username and password.
package com.tek.teacher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
@Configuration
@ComponentScan("com.tek.teacher")
public class SpringJdbcConfig {
@Bean
public JdbcTemplate getJdbcTemplate() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");
dataSource.setUsername("c##dilip");
dataSource.setPassword("dilip");
return new JdbcTemplate(dataSource);
}
}
• Create a POJO class of Student which should be aligned to database table columns and
data types.
Table : Student
package com.tek.teacher;
Another very useful feature is the ability to map query results to Java objects by
implementing the RowMapper interface i.e. when we execute select query’s, we will get
ResultSet Object with many records of database table. So if we want to convert every row as
a single Object then this row mapper will be used. For every row returned by the query, Spring
uses the row mapper to populate the java bean object.
A RowMapper is an interface in Spring JDBC that is used to map a row from a ResultSet
to an object. The RowMapper interface has a single method, mapRow(), which takes a
ResultSet and a row number as input and returns an object.
The mapRow() method is called for each row in the ResultSet. The RowMapper
implementation is responsible for extracting the data from the ResultSet and creating the
corresponding object. The object can be any type of object, but it is typically a POJO (Plain Old
Java Object).
StudentMapper.java
package com.tek.teacher;
@Override
public Student mapRow(ResultSet rs, int arg1) throws SQLException {
return student;
}
}
• Write a class to perform all DB operation i.e. execution of Database Queries based on
our requirement. As part of this class we will use Spring JdbcTemplate Object, and
methods to execute database queries.
StudentJDBCTemp.java
package com.tek.teacher;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class StudentJDBCTemp {
@Autowired
private JdbcTemplate jdbcTemplateObject;
//@Override
public int addStudent(Student student) {
System.out.println(query);
return jdbcTemplateObject.update(query);
}
}
NOTE: Instead of implementing mapper from RowMapper Interface, we can use class
BeanPropertyRowMapper to convert Result Set as List of Objects. Same being used in
previous Spring Boot example.
package com.tek.teacher;
import java.util.List;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
//Insertion of Data
Student s = new Student();
s.setAge(30);
s.setName("tek");
s.setSid(2);
• Spring Data JPA is not a JPA provider. It is a library/framework that adds an extra layer of
abstraction on top of our JPA provider (like Hibernate).
• Spring Data JPA uses Hibernate as a default JPA provider.
The spring-boot-starter-data-jpa POM provides a quick way to get started. It provides the
following key dependencies.
o Hibernate: One of the most popular JPA implementations.
o Spring Data JPA: Helps you to implement JPA-based repositories.
o Spring ORM: Core ORM support from the Spring Framework.
Java/Jakarta Persistence API (JPA) :
The Java/Jakarta Persistence API (JPA) is a specification of Java. It is used to persist data
between Java object and relational database. JPA acts as a bridge between object-oriented
domain models and relational database systems. As JPA is just a specification, it doesn't
perform any operation by itself. It requires an implementation. So, ORM tools like Hibernate,
TopLink and iBatis implements JPA specifications for data persistence. JPA represents how to
define POJO (Plain Old Java Object) as an entity and manage it with relations using some meta
configurations. They are defined either by annotations or by XML files.
Features:
• Idiomatic persistence : It enables you to write the persistence classes using object
oriented classes.
• High Performance : It has many fetching techniques and hopeful locking techniques.
• Reliable : It is highly stable and eminent. Used by many industrial programmers.
Entities in JPA are nothing but POJOs representing data that can be persisted in the
database. a class of type Entity indicates a class that, at an abstract level, is correlated with a
table in the database. An entity represents a table stored in a database. Every instance of an
entity represents a row in the table.
We will define POJOs with JPA annotations aligned to DB tables. We will see all annotations
with an example.
O
Relational Database Tables
R
JAVA column column
Objects M column
column
column
column
(Object
Relational
Mapping)
➢ @Table, @Id, @Column Annotations are used in @Entity class to represent database
table details, name is an attribute.
➢ Inside @Table, name value should be Database table name.
➢ Inside @Column, name value should be table column name.
@Entity
public class Product {
//Properties
}
Entity classes in JPA represent the structure of your database tables and serve as the
foundation for database operations using JPA. You can create, retrieve, update, and delete
instances of these entity classes, and the changes will be reflected in the corresponding
database tables, making it a powerful tool for working with relational databases in Java
applications.
@Table Annotation: In Java Persistence API (JPA), the @Table annotation is used to specify
the details of the database table that corresponds to an @Entity class. When we create an
entity class, we want to map it to a specific table in the database. The @Table annotation
allows you to define various attributes related to the database table.
@Entity
@Table(name = "products")
public class Product {
//properties
}
We can also use other attributes of the `@Table` annotation to specify additional information
about the table, such as the schema, unique constraints, indexes, and more, depending on
your database and application requirements.
@Id Annotation: In Java Persistence API (JPA), `@Id` is an annotation used to declare a field
or property as the primary key of an entity class. JPA is a Java specification for object-
relational mapping (ORM), which allows you to map Java objects to database tables. The @Id
annotation is an essential part of defining the structure of your entity classes when working
with JPA. Here's how you use @Id in JPA.
@Entity
@Table(name = "products")
public class Product {
private Long id;
@Id
public Long getId() {
return id;
}
}
The @Id annotation marks the specified field or property as the primary key for the associated
entity. This means that the value of this field uniquely identifies each row in the corresponding
database table. Additionally, you may need to specify how the primary key is generated, such
as using database-generated values or providing your own. JPA provides various strategies for
generating primary keys, and you can use annotations like @GeneratedValue in conjunction
with @Id to define the strategy for generating primary key values.
@Id, The field or property to which the Id annotation is applied should be one of the following
types: any Java primitive type; any primitive wrapper type; String; java.util.Date;
java.sql.Date; java.math.BigDecimal; java.math.BigInteger. The mapped column for the
primary key of the entity is assumed to be the primary key of the primary table.
@Column Annotation: In Java Persistence API (JPA), the @Column annotation is used to
specify the details of a database column that corresponds to a field or property of an entity
class. When you create an entity class, you often want to map its fields or properties to
specific columns in the associated database table. The @Column annotation allows you to
define various attributes related to the database column.
@Entity
@Table(name = "products")
public class Product {
@Id
@Column
private Long id;
• name: Specifies the name of the database column. If you don't provide the `name`
attribute, JPA will use the field or property name as the default column name.
• length: Specifies the maximum length of the column's value.
• nullable: Indicates whether the column can contain null values. Setting it to false means
the column is mandatory (cannot be null).
The @Column annotation provides a way to customize the mapping between your entity class
fields or properties and database columns. You can use it to specify various attributes like
column name, data type, length, and more, depending on your database and application
requirements.
➢ Create Spring Boot application with JPA dependency and respective Database Driver.
application.properties:
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
First we should have Database table details with us, Based on Table Details we are
creating a POJO class i.e. configuring Table and column details along with POJO class
Properties. I have a table in my database as following. Then I will create POJO class by creating
Properties aligned to DB table datatypes and column names with help of JPA annotations.
package com.flipkart.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
@Entity
@Table(name = "FLIPKART_ORDERS")
public class FlipakartOrder {
@Id
@Column(name = "ORDERID")
private long orderID;
@Column(name = "PRODUCTNAME")
private String productName;
@Column(name = "TOTALAMOUNT")
private float totalAmount;
Note: When Database Table column name and Entity class property name are equal, it’s not
mandatory to use @Column annotation i.e. It’s an Optional in such case. If both are different
then we should use @Column annotation along with value.
For Example : Assume, we written property and column as below in an Entity class.
@Column(name="pincode")
private int pincode;
In this case we can define only property name i.e. internally JPA considers pincode is aligned
with pincode column in table
Spring Data JPA repositories are interfaces that you can define to access data. JPA
queries are created automatically from your method names. In Spring Data JPA, a repository
is an abstraction that provides an interface to interact with a database using Java Persistence
API (JPA). Spring Data JPA repositories offer a set of common methods for performing CRUD
(Create, Read, Update, Delete) operations on database entities without requiring you to write
boilerplate code. These repositories also allow you to define custom queries using method
names, saving you from writing complex SQL queries manually.
package com.flipkart.dao;
import org.springframework.data.jpa.repository.JpaRepository;
This repository is for a FlipakartOrder entity. The Long parameter in the extends
JpaRepository statement specifies the type of the entity's identifier representing primary key
column in Table.
We can also extend the FlipakartOrderRepository interface to add your own custom
methods. For example, you could add a method to find all FlipakartOrder entities that based
on a Product name.
➢ Define an Entity Class: An entity class is a Java class that represents a database table. It is
annotated with @Entity and contains fields that map to table columns.
➢ Create a Repository Interface: Create an interface that extends the JpaRepository
interface provided by Spring Data JPA. This interface will be used to perform database
operations on the associated entity. You can also extend other repository interfaces such
as PagingAndSortingRepository, CrudRepository, etc., based on your needs.
➢ Method Naming Conventions: Spring Data JPA automatically generates queries based on
the method names defined in the repository interface. For example, a method named
findByFirstName will generate a query to retrieve records based on the first name.
➢ Custom Queries: You can define custom query methods by using specific keywords in the
method name, such as find...By..., read...By..., query...By..., or get...By.... Additionally, you
can use @Query annotations to write JPQL (Java Persistence Query Language) or native
SQL queries.
➢ Dependency Injection: Inject the repository interface into your service or controller
classes using Spring's dependency injection.
➢ Use Repository Methods: You can now use the methods defined in the repository
interface to perform database operations.
Spring Data JPA handles the underlying database interactions, such as generating SQL queries,
executing them, and mapping the results back to Java objects.
Now create a Component class For Performing Database operations as per Requirements
Requirement: Add One Order Details to our database table "FLIPKART_ORDERS"
The save() method of Spring JPA Repository, can be used to both insert a new entity or update
an existing one if an ID is provided.
package com.flipkart.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
// To Execute/Perform DB operations
@Component
public class OrderDbOperations {
@Autowired
FlipakartOrderRepository flipakartOrderRepository;
package com.flipkart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.flipkart.dao.FlipakartOrder;
import com.flipkart.dao.OrderDbOperations;
@SpringBootApplication
public class SpringBootJpaDemoApplication {
public static void main(String[] args) {
ApplicationContext context
= SpringApplication.run(SpringBootJpaDemoApplication.class, args);
Project Structure:
Testing: Now Execute The Programme. If No errors/exceptions verify Inside Database table,
Data inserted or not.
NOTE: In our example, we are nowhere written any SQL query to do Database operation.
We learned how to configure the persistence layer of a Spring application that uses Spring
Data JPA and Hibernate. Let’s create few more examples to do CRUD operations on
Database tables.
Internally, Spring JPA/Hibernate Generates SQL query based on repository methods which we
are using in our logic i.e. Spring JPA Internally generates implementation for our Repository
Interface like FlipakartOrderRepository and injects instance of that implementation inside
Repository.
The default value for this property is false. This means that Hibernate will not log any SQL
statements by default. If you want to see the SQL statements that Hibernate is generating,
you will need to set this property to true.
Logging SQL statements can be useful for debugging purposes. If you are having problems
with your application, you can enable logging and see what SQL statements Hibernate is
generating. This can help you to identify the source of the problem.
spring.jpa.show-sql=true
➢ saveAll(): This method will be used for persisting all objects into table.
package com.flipkart.dao;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
// To Execute/Perform DB operations
@Component
public class OrderDbOperations {
@Autowired
FlipakartOrderRepository flipakartOrderRepository;
orders.add(order1);
orders.add(order2);
orders.add(order3);
flipakartOrderRepository.saveAll(orders);
}
}
package com.flipkart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.flipkart.dao.OrderDbOperations;
@SpringBootApplication
public class SpringBootJpaDemoApplication {
public static void main(String[] args) {
ApplicationContext context =
SpringApplication.run(SpringBootJpaDemoApplication.class, args);
Now in application console logs, we can see SQL Queries are executed internally by JPA.
findAll(): This method will load all records of a table and converts all records as Entity Objects
and all Objects added to ArrayList i.e. finally returns List object of FlipakartOrder entity
objects.
#database details
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
#DDL property
spring.jpa.hibernate.ddl-auto=update
package com.dilip.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
@Column
private String name;
@Column
private int age;
@Column
private String gender;
@Column
private String contact;
}
package com.dilip.dao;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
@Component
public interface PatientRepository extends CrudRepository<Patient, String> {
package com.dilip.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
public class PatientApplication {
ops.addPatient(p);
}
}
Now Execute It. Table also created by Spring Boot JPA module and One Record is inserted.
In Spring Data JPA, the save() method is commonly used for both insert and update
operations. When you call the save() method on a repository, Spring Data JPA checks whether
the entity you're trying to save already exists in the database. If it does, it updates the existing
entity; otherwise, it inserts a new entity.
So that is the reason we are seeing a select query execution before inserting data in
previous example. After select query execution with primary key column JPA checks row
count and if it is 1, then JPA will convert entity as insert operation. If count is 0 , then Spring
JPA will convert entity as update operation specific to Primary key.
Using the save() method for updates is a common and convenient approach, especially when
we want to leverage Spring Data JPA's automatic change tracking and transaction
management.
Requirement: Please update name as Dilip Singh for email id: one@gmail.com
Now Test it from Main class: In below if we observe, first select query executed by JPA as per
our entity Object, JPA found data so JPA decided for update Query execution. We have to
send updated data as part of Entity Object.
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
public class PatientApplication {
Verify In DB :
Spring JPA provided a predefined method deleteById() for primary key columns delete
operations.
deleteById(): The deleteById() method in Spring Data JPA is used to remove an entity from
the database based on its primary key (ID). It's provided by the JpaRepository interface and
allows you to delete a single entity by its unique identifier.
Here's how you can use the deleteById() method in a Spring Data JPA repository:
package com.dilip.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
public class PatientApplication {
Before Execution/Deletion:
After Execution/Deletion:
Here Email Id is Primary key Column in table. Finding Details based on Primary key
column name Spring JPA provided a method findById().
findById(): The findById() method is used to retrieve an entity by its primary key or ID from
a relational database. Here's how you can use the findById() method in JPA.
package com.dilip.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
public class PatientApplication {
Output in Console:
Similarly Spring JPA provided many useful and predefined methods inside JPA
repositories to perform CRUD Operations.
For example :
findAll() : for retrieve all Records From Table
Spring Data JPA allows you to define custom repository methods by simply declaring
method signature with entity class property Name which is aligned with Database column.
The method name must start with findBy, getBy, queryBy, countBy, or readBy. The findBy is
mostly used by the developer.
For Example: Below query methods are valid and gives same result like Patient name
matching data from Database.
Rule: After findBy, The first character of Entity class field name should Upper case letter.
Although if we write the first character of the field in lower case then it will work but we
should use camelCase for the method names. Equal Number of Method Parameters should
be defined in abstract method.
package com.dilip.repository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
@Component
public interface PatientRepository extends CrudRepository<Patient, String> {
List<Patient> findByAge(int age);
}
package com.dilip.operations;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
import com.dilip.repository.PatientRepository;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
public class PatientApplication {
public static void main(String[] args) {
Output: In Below, Query generated by JPA and Executed. Got Two Entity Objects In Side List .
Method should have 2 parameters age and gender in this case because we are getting data
with 2 properties.
package com.dilip.repository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
@Component
public interface PatientRepository extends CrudRepository<Patient, String> {
List<Patient> findByAgeAndGender(int age, String gender);
}
Step 2: Now call Above Method inside Db operations to pass Age and gender values.
package com.dilip.operations;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
import com.dilip.repository.PatientRepository;
@Component
public class PatientOperations {
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import java.util.List;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
public class PatientApplication {
public static void main(String[] args) {
ApplicationContext context
= SpringApplication.run(PatientApplication.class, args);
PatientOperations ops = context.getBean(PatientOperations.class);
Table Data:
We can write the query method if we want to restrict the number of records by directly
providing the number as the digit in method name. We need to add the First or the Top
keywords before the By and after find.
Similar to these examples and operations we can perform multiple Database operations
however we will do in SQL operations.
In Java Persistence API (JPA), the @GeneratedValue annotation is used to specify how
primary key values for database entities should be generated. This annotation is typically used
in conjunction with the @Id annotation, which marks a field or property as the primary key of
an entity class. The @GeneratedValue annotation provides options for automatically
generating primary key values when inserting records into a database table.
When you annotate a field with @GeneratedValue, you’re telling Spring Boot to automatically
generate unique values for that field.
strategy:
This attribute specifies the generation strategy for primary key values. This is used to
specify how to auto-generate the field values. There are five possible values for the strategy
element on the GeneratedValue annotation: IDENTITY, AUTO, TABLE, SEQUENCE and UUID.
These five values are available in the enum, GeneratorType.
1. GenerationType.AUTO: This is the default strategy. The JPA provider selects the most
appropriate strategy based on the database and its capabilities. Assign the field a
generated value, leaving the details to the JPA vendor. Tells JPA to pick the strategy that
is preferred by the used database platform.
The preferred strategies are IDENTITY for MySQL, SQLite and MsSQL and SEQUENCE for
Oracle and PostgreSQL. This strategy provides full portability.
In JPA, the GenerationType.AUTO strategy is the default strategy for generating primary
key values. It instructs the persistence provider to choose the most appropriate strategy for
generating primary key values based on the underlying database and configuration. This
typically maps to either GenerationType.IDENTITY or GenerationType.SEQUENCE,
depending on database capabilities.
However, there are some cases where we may want to explicitly specify a generation
strategy. For example, if you need to ensure that primary key values are generated
sequentially, you should use the GenerationType.SEQUENCE strategy. Or, if you need to use
a custom generator, you should specify the name of the generator using the generator
attribute of the @GeneratedValue annotation.
Benefits of GenerationType.AUTO
➢ Convenience: It eliminates the need to explicitly specify a generation strategy.
➢ Automatic selection: It selects the most appropriate strategy for the underlying database.
➢ Compatibility: It is compatible with a wide range of databases.
Limitations of GenerationType.AUTO
➢ Lack of control: It may not be the most efficient strategy for all databases.
➢ Potential for performance issues: If the persistence provider selects the wrong
strategy, it could lead to performance issues.
#database details
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
#DDL property
spring.jpa.hibernate.ddl-auto=update
package com.tek.teacher.data;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Id
@Column(name = "patient_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private long pateintId;
@Column(name = "patient_name")
private String name;
@Column(name = "patient_age")
private int age;
➢ Now Try to Persist Data with above entity class. Create a Repository.
package com.tek.teacher.data;
import org.springframework.data.jpa.repository.JpaRepository;
package com.tek.teacher.data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
package com.tek.teacher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.tek.teacher.data.PatientOperations;
@SpringBootApplication
public class SpringBootJpaGeneartedvalueApplication {
i.e. Spring JPA created by a new sequence for the column PATIENT_ID values.
Table Result :
This strategy will help us to generate the primary key value by the database itself using the
auto-increment or identity of column option. It relies on the database’s native support for
generating unique values.
package com.tek.teacher.data;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "patient_details")
public class Patient {
@Id
@Column(name = "patient_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long pateintId;
@Column(name = "patient_name")
private String name;
@Column(name = "patient_age")
private int age;
Execute Again :
GenerationType.SEQUENCE:
package com.tek.teacher.data;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "patient_details")
public class Patient {
@Id
@Column(name = "patient_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long pateintId;
@Column(name = "patient_name")
private String name;
@Column(name = "patient_age")
private int age;
➢ JPA created a Sequence to generate unique values. By executing this sequence, values
are inserted into Patient table for primary key column.
➢ Now when we are persisting data inside Patient table by Entity Object, always same
sequence will be used for next value.
Table Data :
Table Data:
Question: In case, if we want to generate a custom sequence for entity primary key column
instead of default sequence created by JPA, do we have any solution?
Yes, JPA provided generator with annotation @SequenceGenerator, for creating a custom
Sequence should be created by JPA instead of default one like before example.
generator:
This is used to specify the name of the named generator. Named generators are
defined using SequenceGenerator, TableGenerator. When GenerationType.SEQUENCE and
GenerationType.TABLE are used as a strategy then we must specify the generators. Value for
this generator field should be the name of SequenceGenerator, TableGenerator.
@SequenceGenerator Annotation:
Most databases allow you to create native sequences. These are database structures that
generate sequential values. The @SequenceGenerator annotation is used to represent a
named database sequence. This annotation can be kept on class level, member
level. @SequenceGenerator annotation has the following properties:
package com.tek.teacher.data;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;
@Entity
@Table(name = "patient_details")
public class Patient {
@Id
@Column(name = "patient_id")
@SequenceGenerator(name = "pat_id_seq", sequenceName = "patient_id_seq",
initialValue = 1000, allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "pat_id_seq")
private long pateintId;
@Column(name = "patient_name")
private String name;
@Column(name = "patient_age")
private int age;
package com.tek.teacher.data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
➢ Now JPA created a custom sequence with details provided as part of annotation
@SequenceGenerator inside Entity class Id column.
➢ Same Sequence will be executed every time for new Primary key values of column.
Table Result :
➢ Execute Logic again for Persisting Data. In Below we can see patient ID column value
started with 1000 and every time incremented with 1 value continuously.
This is how we can generate a sequence by providing details with annotation inside Entity
class.
➢ Now use above created Sequence with JPA entity class to generate values automatically.
Attributes:
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
package com.dilip.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@Table(name = "amazon_orders")
public class AmazonOrders {
@Id
@Column(name="order_id")
private int orderId;
@Column(name = "amount")
private double amount;
@Column(name="email" )
private String email;
@Column(name="pincode")
private int pincode;
@Column(name="city")
private String city;
@Column(name="gender")
private String gender;
}
package com.dilip.dao;
import org.springframework.data.jpa.repository.JpaRepository;
➢ Now Create a Component Class for Database Operations and Add a Method for Sorting
Data
To achieve this requirement, Spring Boot JPA provided few methods in side JpaRepository.
Inside JpaRepository, JPA provided a method findAll(…) with different Arguments.
Sort: In Spring Data JPA, you can use the Sort class to specify sorting criteria for your query
results. The Sort class allows you to define sorting orders for one or more attributes of our
entity class. we can use it when working with repository methods to sort query results.
package com.dilip.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
@Component
public class OrdersOperations {
@Autowired
AmazonOrderRepository repository;
Note: we have to pass Entity class Property name as part of by(..) method, which is related to
database table column.
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.OrdersOperations;
@SpringBootApplication
public class SpringBootJpaSortingPaginationApplication {
ApplicationContext context
= SpringApplication.run(SpringBootJpaSortingPaginationApplication.class, args);
In Spring Data JPA, you can specify the direction (ascending or descending) for sorting when
using the Sort class. The Sort class allows you to create sorting orders for one or more
attributes of our entity class. To specify the direction, you can use the Direction enum.
Here's how you can use the Direction enum in Spring Data JPA:
package com.dilip.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Component;
@Component
public class OrdersOperations {
@Autowired
AmazonOrderRepository repository;
[
AmazonOrders(orderId=8888, noOfItems=10, amount=10000.0, email=suresh@gmail.com,
pincode=600099, city=Chennai, gender=MALE),
AmazonOrders(orderId=5566, noOfItems=8, amount=6000.0, email=naresh@gmail.com,
pincode=500070, city=Hyderbad, gender=MALE),
AmazonOrders(orderId=3232, noOfItems=4, amount=63643.0, email=laxmi@gmail.com,
pincode=500070, city=Hyderbad, gender=FEMALE),
AmazonOrders(orderId=3323, noOfItems=4, amount=63643.0, email=laxmi@gmail.com,
pincode=500070, city=Hyderbad, gender=FEMALE),
AmazonOrders(orderId=3344, noOfItems=4, amount=3000.0, email=dilip@gmail.com,
pincode=500072, city=Hyderbad, gender=MALE),
AmazonOrders(orderId=3636, noOfItems=3, amount=44444.0, email=ramesh@gmail.com,
pincode=600088, city=Chennai, gender=MALE),
AmazonOrders(orderId=9988, noOfItems=3, amount=44444.0, email=ramesh@gmail.com,
pincode=600088, city=Chennai, gender=MALE),
AmazonOrders(orderId=1234, noOfItems=2, amount=4000.0, email=naresh@gmail.com,
pincode=500072, city=Hyderbad, gender=MALE)
]
Similarly we can get table Data with Sorting Order based on any table column by using Spring
Boot JPA. We can sort data with multiple columns as well.
Example: repository.findAll(Sort.by("email","noOfItems"));
Pagination:
Page Size: The number of items or records displayed on each page is referred to as the "page
size" or "items per page." Common page sizes might be 10, 20, 50, or 100 items per page. The
choice of page size depends on usability considerations and the nature of the data.
Page Number: Pagination is typically associated with a page number, starting from 1 and
incrementing as users navigate through the data. Users can move forward or backward to view
different segments of the dataset.
Navigation Controls: Pagination is usually accompanied by navigation controls, such as
"Previous" and "Next" buttons or links. These controls allow users to move between pages
easily.
Total Number of Pages: The total number of pages in the dataset is determined by dividing
the total number of items by the page size. For example, if there are 100 items and the page
size is 10, there will be 10 pages.
➢ Assume a scenario, where we have 200 Records. Each page should get 25 Records, then
page number and records are divided as shown below.
Page 1 1 - 25
Page 2 26 - 50
Page 3 51 - 75
Page 4 76 - 100
Page 5 101 - 125
Page 6 126 - 150
Page 7 151 - 175
Page 8 176 - 200
Requirement: Get first set of Records by default with some size from below Table data.
package com.dilip.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
@Component
public class OrdersOperations {
@Autowired
AmazonOrderRepository repository;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootJpaTablesAutoCreationApplication {
public static void main(String[] args) {
ApplicationContext context
= SpringApplication.run(SpringBootJpaTablesAutoCreationApplication.class, args);
OrdersOperations ops = context.getBean(OrdersOperations.class);
ops.getFirstPageData();
}
}
[
AmazonOrders(orderId=3323, noOfItems=4, amount=63643.0, email=laxmi@gmail.com,
pincode=500070, city=Hyderbad, gender=FEMALE),
Requirement: Get 2nd page of Records with some size of records i.e. 3 Records.
Here we will use PageRequest class which provides pre-defined methods, where we can
provide page Numbers and number of records.
package com.dilip.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
@Component
public class OrdersOperations {
@Autowired
AmazonOrderRepository repository;
}
}
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.OrdersOperations;
@SpringBootApplication
public class SpringBootJpaTablesAutoCreationApplication {
public static void main(String[] args) {
ApplicationContext context
= SpringApplication.run(SpringBootJpaTablesAutoCreationApplication.class, args);
OrdersOperations ops = context.getBean(OrdersOperations.class);
ops.getRecordsByPageIdAndNoOfRecords(1,3);
}
}
[
AmazonOrders(orderId=3344, noOfItems=4, amount=3000.0, email=dilip@gmail.com,
pincode=500072, city=Hyderbad, gender=MALE),
Get 2nd page of Records with some size of records i.e. 3 Records along with Sorting by
noOfItems column in Descending Order.
package com.dilip.dao;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Component;
@Component
public class OrdersOperations {
@Autowired
AmazonOrderRepository repository;
List<AmazonOrders> allOrders =
repository.findAll(PageRequest.of(pageId, noOFReorcds,
Sort.by(Direction.DESC, "noOfItems"))).getContent();
System.out.println(allOrders);
}
}
package com.dilip;
@SpringBootApplication
public class SpringBootJpaTablesAutoCreationApplication {
public static void main(String[] args) {
ApplicationContext context
= SpringApplication.run(SpringBootJpaTablesAutoCreationApplication.class, args);
OrdersOperations ops = context.getBean(OrdersOperations.class);
ops.getDataByPaginationAndSorting(1,3);
}
}
Output: We got Entity Objects with Sorting by noOfItems column, and we got 2nd page set
of records.
[
AmazonOrders(orderId=3344, noOfItems=4, amount=3000.0, email=dilip@gmail.com,
pincode=500072, city=Hyderbad, gender=MALE),
AmazonOrders(orderId=3232, noOfItems=4, amount=63643.0, email=laxmi@gmail.com,
pincode=500070, city=Hyderbad, gender=FEMALE),
AmazonOrders(orderId=9988, noOfItems=3, amount=44444.0, email=ramesh@gmail.com,
pincode=600088, city=Chennai, gender=MALE)
]
Native Query is Custom SQL query. In order to define SQL Query to execute for a Spring
Data repository method, we have to annotate the method with the @Query annotation. This
annotation value attribute contains the SQL or JPQL to execute in Database. We will define
@Query above the method inside the repository.
Spring Data JPA allows you to execute native SQL queries by using the @Query annotation
with the nativeQuery attribute set to true. For example, the following method uses the
@Query annotation to execute a native SQL query that selects all customers from the
database.
The @Query annotation allows you to specify the SQL query that will be executed. The
nativeQuery attribute tells Spring Data JPA to execute the query as a native SQL query, rather
than considering it to JPQL.
JPQL Query:
By default, the query definition uses JPQL in Spring JPA. Let's look at a simple
repository method that returns Users entities based on city value from the database:
We can use @Query to define our Native Database SQL query. All we have to do is set
the value of the nativeQuery attribute to true and define the native SQL query in
the value attribute of the annotation.
Example, Below Repository Method representing Native SQL Query to get all records.
For passing values to Positional parameters of SQL Query from method parameters, JPA
provides 2 possible ways.
If SQL query contains positional parameters and we have to pass values to those, we should
use Indexed Params i.e. index count of parameters. For indexed parameters, Spring JPA Data
Now below method declaration in repository will return List of Entity Objects with city
parameter.
Example with more indexed parameters: users from either city or pincode matches.
Example: Get All Records Of Table where city or pincode is matching
Examples:
Requirement:
1. Get All Patient Details
2. Get All Patient with Email Id
3. Get All Patients with Age and Gender
package com.dilip.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.dilip.entity.Patient;
package com.dilip.operations;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
import com.dilip.repository.PatientRepository;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
import java.util.List;
@SpringBootApplication
public class PatientApplication {
public static void main(String[] args) {
ApplicationContext context =
SpringApplication.run(PatientApplication.class, args);
//All Patients
List<Patient> allPatients = ops.getPatientDetails();
System.out.println(allPatients);
//By email Id
System.out.println("******** with email Id **************");
Patient patient = ops.getPatientDetailsbyEmailId("laxmi@gmail.com");
System.out.println(patient);
Output:
We can also pass values of method parameters to the query using named parameters i.e. we
are providing We define these using the @Param annotation inside our repository method
declaration. Each parameter annotated with @Param must have a value string matching the
corresponding JPQL or SQL query parameter name. A query with named parameters is easier
to read and is less error-prone in case the query needs to be refactored.
NOTE: In JPQL also, we can use index and named Query parameters.
Requirement:
1. Insert Patient Data
package com.dilip.dao;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.dilip.entity.Patient;
package com.dilip.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
import com.dilip.repository.PatientRepository;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
//add Pateint
public void addPAtient(String name, String email, int age, String mobile, String gender) {
repository.addPAtient(name, email, age, mobile, gender);
}
}
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
@SpringBootApplication
public class PatientApplication {
public static void main(String[] args) {
ApplicationContext context =
SpringApplication.run(PatientApplication.class, args);
PatientOperations ops = context.getBean(PatientOperations.class);
//add Pateint
System.out.println("*** Adding Patient ************");
ops.addPAtient("Rakhi", "Rakhi@gmail.com", 44, "+91372372", "MALE");
}
}
Output:
In above We executed DML Query, So it means some Modification will happen finally in
Database Tables data. In Spring JPA, for DML Queries like insert, update and delete provided
mandatory annotations @Transactional and @Modifying. We should declare these
annotations while executing DML Queries.
@Transactional:
Package : org.springframework.transaction.annotation.Transactional
@Modifying:
The @Modifying annotation in Spring JPA is used to indicate that a method is a modifying
query, which means that it will update, delete, or insert data in the database. This annotation
is used in conjunction with the @Query annotation to specify the query that the method will
If you are developing an application that needs to update, delete, or insert data in the
database, I highly recommend using the @Modifying annotation. It is a powerful tool that
can help you to improve the performance and reliability of your application.
Examples for executing JPQL Query’s. Here We will not use nativeQuery attribute means by
default false value. Then Spring JPA considers @Query Value as JPQL Query.
Requirement:
• Fetch All Patients
• Fetch All Patients Names
• Fetch All Male Patients Names
package com.dilip.repository;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
@Component
public interface PatientRepository extends CrudRepository<Patient, String> {
//JPQL Queries
//Fetch All Patients
@Query(value="Select p from Patient p")
public List<Patient> getAllPAtients();
package com.dilip.operations;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.dilip.entity.Patient;
import com.dilip.repository.PatientRepository;
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
// All Patients
public List<Patient> getAllpatients() {
return repository.getAllPAtients();
}
// All Patients Names
public List<String> getAllpatientsNames() {
return repository.getAllPatientsNames();
}
// All Patients Names
public List<Patient> getAllpatientsByGender(String gender) {
return repository.getPatientsByGender(gender);
}
}
package com.dilip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import com.dilip.dao.Patient;
import com.dilip.dao.PatientOperations;
@SpringBootApplication
Output:
Internally JPA Translates JPQL queries to Actual Database SQL Queries and finally those
queries will be executed. We can see those queries in Console Messages.
JPQL queries follow a set of rules that define how they are parsed and executed. These rules
are defined in the JPA specification. Here are some of the key rules of JPQL:
• The SELECT clause: The SELECT clause specifies the entities that will be returned by the
query.
• The FROM clause: The FROM clause specifies the entities that the query will be executed
against.
• The WHERE clause: The WHERE clause specifies the conditions that the entities must meet
in order to be included in the results of the query.
• JPQL queries are case-insensitive. This means that you can use the names of entities and
columns in either upper or lower case.
• JPQL queries can use parameters. Parameters are variables that can be used in the query
to represent values that are not known at the time the query is written.
• Configure the database connection. We need to set the name of the the JDBC url, the
username of database user, and the password of the database user.
Configuring the Entity Manager Factory Bean:
We can configure the entity manager factory bean by following steps:
• Create a new LocalContainerEntityManagerFactoryBean object. We need to create this
object because it creates the JPA EntityManagerFactory.
• Configure the Created DataSource in Previous Step.
• Configure the Hibernate specific implementation of the HibernateJpaVendorAdapter . It will
initialize our configuration with the default settings that are compatible with Hibernate.
• Configure the packages that are scanned for entity classes.
• Configure the JPA/Hibernate properties that are used to provide additional configuration
to the used JPA provider.
package flipkart.entity;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
@Configuration
@EnableJpaRepositories("flipkart.*")
public class SpringJpaConfiguration {
//DB Details
@Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");
dataSource.setUsername("c##dilip");
dataSource.setPassword("dilip");
return dataSource;
}
@Bean("entityManagerFactory")
LocalContainerEntityManagerFactoryBean createEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory
= new LocalContainerEntityManagerFactoryBean();
return factory;
}
@Bean("transactionManager")
public PlatformTransactionManager createTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(createEntityManagerFactory()
.getObject());
return transactionManager;
}
Now create another Component class For Performing DB operations as per our
Requirement:
package flipkart.entity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
// To Execute/Perform DB operations
@Component
public class OrderDbOperations {
@Autowired
FlipakartOrderRepository flipakartOrderRepository;
package flipkart.entity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.scan("flipkart.*");
context.refresh();
In Eclipse Console Logs, Printed internally generated SQL Quries to perform insert operation.
NOTE: In our example, we are nowhere written any SQL query to do Database operation.
We learned to configure the persistence layer of a Spring application that uses Spring Data
JPA and Hibernate. Let’s create few more examples to do CRUD operations on Db table.
From Spring JPA Configuration class, we have used two properties related to Hibernate FW.
The default value for this property is false. This means that Hibernate will not log any SQL
statements by default. If you want to see the SQL statements that Hibernate is generating,
you will need to set this property to true.
• Name
• Age
• Gender
• Contact Number
• Email Id
Requirements:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
package com.dilip;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
@Configuration
@EnableJpaRepositories("com.*")
public class SpringJpaConfiguration {
//DB Details
@Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");
dataSource.setUsername("c##dilip");
dataSource.setPassword("dilip");
return dataSource;
}
@Bean("entityManagerFactory")
LocalContainerEntityManagerFactoryBean createEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
return factory;
}
Note: Until this Step/Configuration in Spring Framework, we have written manually of JPA
configuration. From here onwards, Rest of functionalities implementations are as it is like how
we implemented in Spring Boot.
Means, The above 2 Steps are automated/ auto configured in Spring Boot internally. We just
need to provide database details and JPA properties inside application.properties.
package com.dilip.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table
public class Patient {
@Id
@Column
private String emailId;
@Column
private String name;
@Column
private int age;
@Column
private String gender;
@Column
private String contact;
public Patient() {
super();
// TODO Auto-generated constructor stub
public Patient(String name, int age, String gender, String contact, String emailId) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.contact = contact;
this.emailId = emailId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
@Override
public String toString() {
return "Patient [name=" + name + ", age=" + age + ", gender=" + gender + ",
contact=" + contact + ", emailId="
+ emailId + "]";
}
}
@Component
public class PatientOperations {
@Autowired
PatientRepository repository;
}
Spring JPA Repositories Provided many predefined abstract methods for all DB CURD
operations. We should recognize those as per our DB operation.
package com.dilip.operations;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.dilip.entity.Patient;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.scan("com.*");
context.refresh();
ops.addPatient(p);
}
}
Now Execute It. Table also created by JPA module and One Record is inserted.
Here, we are adding Multiple Patient details means at Database level this is also insert Query
Operation.
saveAll() : This is for adding List of Objects at a time. We should pass List Object of Patient
Type.
package com.dilip.operations;
import java.util.ArrayList;
import java.util.List;
Execution Output:
In Spring Data JPA, the save() method is commonly used for both insert and update
operations. When you call the save() method on a repository, Spring Data JPA checks whether
the entity you're trying to save already exists in the database. If it does, it updates the existing
entity; otherwise, it inserts a new entity.
So that is the reason we are seeing a select query execution before inserting data in
previous example. After select query execution with primary key column JPA checks row
count and if it is 1, then JPA will convert entity as insert operation. If count is 0 , then Spring
JPA will convert entity as update operation specific to Primary key.
Using the save() method for updates is a common and convenient approach, especially when
we want to leverage Spring Data JPA's automatic change tracking and transaction
management.
Requirement: Please update name as Dilip Singh for email id: one@gmail.com
Now Test it from Main class: In below if we observe, first select query executed by JPA as
per our entity Object, JPA found data so JPA decided for update Query execution.
Verify In DB :
Spring JPA provided a predefined method deleteById() for primary key columns delete
operations.
deleteById():
Here's how you can use the deleteById() method in a Spring Data JPA repository:
package com.dilip.operations;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.scan("com.*");
context.refresh();
Before Execution/Deletion:
After Execution/Deletion:
Here Email Id is Primary key Column. Finding Details based on Primary key column
name Spring JPA provide a method findById().
package com.dilip.operations;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.dilip.entity.Patient;
Output:
Spring/SpringBoot
Web/MVC
Modules
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.
Spring Boot is well suited for web application development. You can create a self-contained
HTTP server by using embedded Tomcat, Jetty, Undertow, or Netty. Most web applications
use the SpringBoot-starter-web module to get up and running quickly.
What is MVC?
MVC stands for Model-View-Controller, and it is a widely used architectural pattern in
software development, particularly for building user interfaces and web applications. MVC is
designed to separate an application into three interconnected components, each with a
specific responsibility:
MVC Architecture becomes so popular that now most of the popular frameworks
follow the MVC design pattern to develop the applications. Some of the popular Frameworks
that follow the MVC Design pattern are:
View:
The View component is used for all the UI logic of the application. For example, the
Customer view will include all the UI components such as text boxes, dropdowns, etc. that
the final user interacts with.
Controller:
Controllers act as an interface between Model and View components to process all
the business logic and incoming requests, manipulate data using the Model component and
interact with the Views to render the final output. For example, the Customer controller will
handle all the interactions and inputs from the Customer View and update the database using
the Customer Model. The same controller will be used to view the Customer data.
1. A user interacts with the View (e.g., clicks a button or submits a form).
2. The View forwards the user input to the Controller.
3. The Controller processes the input, potentially querying or updating the Model.
4. The Model is updated if necessary, and the Controller retrieves data from the Model.
5. The Controller sends the updated data to the View.
6. The View renders the data and presents it to the user.
• Separate roles - The Spring MVC separates each role, where the model object, controller,
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.
In Next Page, Add Spring Boot Modules/Starters as shown below and click on finish.
Now Run your Application as Spring Boot App / java application from Main Method
Class.
➢ Integrated Server Started with Default Port : 8080 with context path ' '. i.e., if we won’t
give any port number then default port number will be 8080. If we want to change default
port number then, we should add a property and its value in application.properties.
➢ By Default Spring Boot application will be deployed with empty context path ' '. If we
want to change default context path then, we should add a property and its value in
application.properties.
Controller Class:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloWorldController {
@GetMapping("/world")
@ResponseBody
public String printHelloWrold() {
return "Hello world! Welcome to Spring Boot MVC";
}
}
Execute/Call above Endpoint: We will access Endpoints/URLs from Http Clients like Browsers.
Now open application. Properties file and add below predefined properties and provide
required values.
server.port=8899
server.servlet.context-path= /hello
➢ Restart our application again, application started on port(s): 8899 (http) with context
path '/hello'
Front Controller:
A front controller is defined as a controller that handles all requests for a Web
Application. DispatcherServlet servlet is the front controller in Spring MVC that intercepts
every request and then dispatches requests to an appropriate controller. The
DispatcherServlet is a Front Controller and one of the most significant components of the
Spring MVC web framework. A Front Controller is a typical structure in web applications that
receives requests and delegates their processing to other components in the application. The
DispatcherServlet acts as a single entry point for client requests to the Spring MVC web
application, forwarding them to the appropriate Spring MVC controllers for processing.
DispatcherServlet is a front controller that also helps with view resolution, error handling,
locale resolution, theme resolution, and other things.
Request: The first step in the MVC flow is when a request is received by the Dispatcher Servlet.
The aim of the request is to access a resource on the server.
Response: Response is made by a server to a client. The aim of the response is to provide the
client with the resource it requested, or inform the client that the action it requested has been
carried out; or else to inform the client that an error occurred in processing its request.
Dispatcher Servlet: Now, the DispatcherServlet with the help of Handler Mappings
understands the Controller class name associated with the received request. Once the
DispatcherServlet knows which Controller will be able to handle the request, it will transfer
the request to it. DispatcherServlet expects a WebApplicationContext (an extension of a
plain ApplicationContext) for its own configuration. WebApplicationContext has a link to the
ServletContext and the Servlet with which it is associated.
HandlerMapping:
In Spring MVC, the DispatcherServlet acts as front controller – receiving all incoming HTTP
requests and processing them. Simply put, the processing occurs by passing the requests to
the relevant component with the help of handler mappings.
Now Define Controller classes inside our Spring Boot MVC application:
package com.apple.iphone.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class IphoneCotroller {
@GetMapping("/message")
@ResponseBody
public String printIphoneMessage() {
//Logic of Method
return " Welcome to Iphone World.";
}
@GetMapping("/cost")
@ResponseBody
public String printIphone14Cost() {
return " Price is INR : 150000";
}
}
package com.apple.iphone.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class IpadControlller {
@GetMapping("/ipad/cost")
@ResponseBody
public String printIPadCost() {
return " Ipad Price is INR : 200000";
}
}
Now when we start our project as Spring Boot Application, Internally Project deployed to
tomcat server and below steps will be executed.
• When we are started/deployed out application, Spring MVC internally creates
WebApplcationContext i.e. Spring Container to instantiate and manage all Spring Beans
associated to our project.
• Spring instantiates Pre-Defined Front Controller class called as DispatcherServlet as well
as WebApplicationContext scans all our packages for @Component, @Controller etc..
and other Bean Configurations.
After Starting our Spring Boot Application, when we are sending a request, Following
is the sequence of events happens corresponding to an incoming HTTP request
to DispatcherServlet:
For example, we sent a request to our endpoint from browser:
http://localhost:6655/apple/message
➢ After receiving an HTTP request, DispatcherServlet consults the HandlerMappings by
passing URI (/message) and HTTP Method type GET.
➢ Then HandlerMappings will checks all mappings information with above Details, If details
are mapped then HandlerMapping will returns Controller Class Name and Method Name.
➢ If Details are not mapped/found in mappings, then HandlerMappings will provide an error
message to DispatcherServlet with Error Details.
➢ After DispatcherServlet Receiving appropriate Controller and its associated method of
endpoint URI, then DispatcherServlet forwards all request body and parameters to
controller method and executes same.
➢ The Controller takes the request from DispatcherServlet and calls the appropriate service
methods.
➢ The service method will set model data based on defined business logic and returns result
or response data to Controller and from Controller to DispatcherServlet.
➢ If We configured ViewResolver, The DispatcherServlet will take help
from ViewResolver to pick up the defined view i.e. JSP files to render response of for that
specific request.
NOTE: As per REST API/Services, we are not integrating Frontend/View layer with our
controller layer i.e. We are implementing individual backend services and shared with
Frontend Development team to integrate with Our services. Same Services we can also share
with multiple third party applications to interact with our services to accomplish the task. So
We are continuing our training with REST services implantation point of view because in
Microservices Architecture communication between multiple services happens via REST APIS
integration across multiple Services.
Controller Class:
In Spring Boot, the controller class is responsible for processing incoming HTTP web
requests, preparing a model, and returning the view to be rendered as a response on client.
The controller classes in Spring are annotated either by the @Controller or the
@RestController annotation.
@Controller: org.springframework.stereotype.Controller
@ResponseBody:
Package: org.springframework.web.bind.annotation.ResponseBody:
@RequestMapping:
Package: org.springframework.web.bind.annotation.RequestMapping
This Annotation for mapping web requests onto methods in request-handling classes i.e.
controller classes with flexible method signatures. @RequestMapping is Spring MVC's most
common and widely used annotation.
consumes = "text/plain"
consumes = {"text/plain", "application/*"}
consumes = MediaType.TEXT_PLAIN_VALUE
produces String[] mapping by media types that can be produced by the mapped
handler. Consists of one or more media types one of which
must be chosen via content negotiation against the
"acceptable" media types of the request.
produces = "text/plain"
produces = {"text/plain", "application/*"}
produces = MediaType.TEXT_PLAIN_VALUE
produces = "text/plain;charset=UTF-8"
Note: This annotation can be used both at the class and at the method level. In most cases, at
the method level, applications will prefer to use one of the HTTP method specific variants
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping.
package com.apple.iphone.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class IphoneCotroller {
@RequestMapping("/message")
@ResponseBody
public String printIphoneMessage() {
return " Welcome to Ihpne World.";
}
}
@RequestMapping("/message"):
1. If we are not defined in method type attribute and value, then same handler method will
be executed for all HTTP methods along with endpoint.
2. @RequestMapping("/message") is equivalent to @RequestMapping(value="/message")
or @RequestMapping(path="/message")
i.e. value and path are same type attributes to configure URI path of handler method. We
can use either of them i.e. value is an alias for path.
Now above handler method will work only for HTTP GET request call. If we try to request with
any HTTP methods other than GET, we will get error response as
"status": 405,
"error": "Method Not Allowed",
@RequestMapping(value="/message",
method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String printIphoneMessage() {
return " Welcome to Iphone World.";
}
Now above handler method will work only for HTTP GET and POST requests calls. If we try to
request with any HTTP methods other than GET, POST we will get error response as:
"status": 405,
"error": "Method Not Allowed",
i.e. we can configure one URL handler method with multiple HTTP
methods request.
Above handler method will support both GET and POST requests of URI’s mappings
"/message", "/msg/iphone".
RequestMethod:
RequestMethod is Enumeration(Enum) of HTTP request methods. Intended for use
with the RequestMapping.method() attribute of the RequestMapping annotation.
ENUM Constant Values : GET, POST, PUT, DELETE, HEAD, OPTIONS, PATCH, TRACE
We can Define Same URI with multiple different handler/controller methods for different
HTTP methods. Depends on incoming HTTP method request type specific handler method will
be executed.
We can use @RequestMapping with class definition level to create the base URI of
that specific controller i.e. All URI mappings of that controller will be preceded with class level
URI value always.
For example:
package com.apple.iphone.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/ipad")
public class IpadControlller {
@GetMapping("/cost")
@ResponseBody
public String printIPadCost() {
return " Ipad Price is INR : 200000";
}
@GetMapping("/model")
@ResponseBody
public String printIPadModel() {
From above example, class level Request mapping value ("/ipad") will be base URI for all
handler method URI values. Means All URIs starts with /ipad of the controller URI’s as shown
below.
http://localhost:6655/apple/ipad/model
http://localhost:6655/apple/ipad/cost
@GetMapping:
Package: org.springframework.web.bind.annotation.GetMapping
This Annotation used for mapping HTTP GET requests onto specific handler methods.
The @GetMapping annotation is a composed version of @RequestMapping annotation that
acts as a shortcut for @RequestMapping(method = RequestMethod.GET).
The @GetMapping annotated methods handle the HTTP GET requests matched with the
given URI value.
Similar to this annotation, we have other Composed Annotations to handle different HTTP
methods.
@PostMapping:
This Annotation used for mapping HTTP POST requests onto specific handler methods.
@PostMapping is a composed annotation that acts as a shortcut for
@RequestMapping(method = RequestMethod.POST).
@PutMapping:
This Annotation used for mapping HTTP PUT requests onto specific handler methods.
@PutMapping is a composed annotation that acts as a shortcut for
@RequestMapping(method = RequestMethod.PUT).
@DeleteMapping:
This Annotation used for mapping HTTP DELETE requests onto specific handler
methods. @DeleteMapping is a composed annotation that acts as a shortcut for
@RequestMapping(method = RequestMethod.DELETE).
➢ By default embedded tomcat server will not support JSP functionalities inside a Spring
Boot MVC application. So, In order to work with JSP, we need to add below dependency in
Spring boot MVC.
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
What is ViewResolver?
In Spring MVC, a ViewResolver is an essential component responsible for resolving
logical view names returned by controller methods into actual view implementations that can
be rendered and returned to the client. It plays a crucial role in the web application's flow by
mapping logical view names to views, which can be JSP pages, HTML templates, or any other
type of view technology supported by Spring.
InternalResourceViewResolver:
1. Controller Returns a Logical View Name: In a Spring web application, when a controller
method processes an HTTP request and returns a logical view name (e.g., "home" or
"dashboard"), this logical view name is returned to the Spring MVC framework.
3. JSP Is Rendered: Once the view path is resolved, the JSP file at that path is executed. Any
dynamic data is processed, and the JSP generates HTML content that is sent as a response to
the client's browser.
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
➢ Based on above configuration of property prefix value, we have to create folders inside
our Spring Boot MVC application.
➢ Create a folder webapp inside src -> main
➢ Inside webapp, create another folder WEB-INF
➢ Inside WEB-INF, create another folder view
➢ Inside view Folder, We will create our JSP files.
➢ Now create a JSP file inside view folder and invoke it from Controller Method.
<html>
<head>
<title>Spring Boot MVC</title>
</head>
<body>
<h1>Welcome to Spring Boot MVC with JSP</h1>
</body>
</html>
package com.facebook.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class UserController {
@GetMapping("/welcome")
public String sayHello() {
return "hello";
}
}
Internally, DispatcherServlet will forwards the request to jsp file as per our Internal
Resource View Resolver configuration data, i.e. inside folder /WEB-INF/view/ with suffix
.jsp by including jsp file name “hello”.
We are going annotate with @Service is annotated on class to say spring, this is my Service
Layer.
Create An Example with Service Layer:
Controller Class:
@Controller
@RequestMapping("/admission")
public class UniversityAdmissionsController {
//Logic
Service Class:
@Service
public class UniversityAdmissionsService {
//Logic
Now integrate Service Layer class with Controller Layer i.e. injecting Service class Object into
Controller class Object. So we will use @Autowired annotation to inject service in side
controller.
//Logic
}
From above, We are integrated controller with service layer. Now inside Service class, we will
write Business Logic and then data should be passed to persistence layer.
Now return values of service class methods are passed to Controller class level. This is how
we are using service layer with controller layer. Now we should integrate Service layer with
DAO Layer to Perform DB operations. We will have multiple examples together of all three
layer.
Repository Layer:
Repository Layer is mainly used for managing the data with database in a Spring
Application. A huge amount of code is required for working with the databases, which can be
easily reduced by Spring Data modules. It consists of JPA and JDBC modules. There are many
Spring applications that use JPA technology, so these development procedures can be easily
simplified by Spring Data JPA. As we discussed earlier in JPA functionalities, Now we have to
integrate JPA Module to our existing application.
Repository Interface:
@Respository
public interface AdmissionsRepository extends JpaRepository {
//JPA Methods
}
@Service
public class UniversityAdmissionsService {
@Autowired
AdmissionsRepository repository;
//Logic
Requirement: Create a Project and implement User Registration and Login Flows.
server.port=9999
server.servlet.context-path=/tekteacher
#DB Properties.
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
server.port=9999
server.servlet.context-path=/tekteacher
#DB Properties.
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
#JSP
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
<html>
<head>
<title> User Register</title>
</head>
<body>
<form action="user/register" method="POST">
Name : <input type="text" name="name" /> <br />
Email Id : <input type="text" name="email" /> <br />
Contact Number : <input type="text" name="contact" /> <br />
Password : <input type="password" name="pwd" /> <br />
<input type="submit" value="Register" /> <br />
</form>
</body>
</html>
Create another JSP file for User Registration Result Message, whether User Account
Created or Not : result.jsp
<html>
<head>
<title> Result</title>
</head>
<body>
${message}
</body>
</html>
Create a DTO class for retrieving details from HttpServeletRequest Object in side
Controller method.
package com.tek.teacher.dto;
Create Controller class and Methods for loading User Registration Page and reading data
from Registration page. Once Receiving Data at controller we should store it inside
database.
package com.tek.teacher.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import com.tek.teacher.dto.UserReigtserDto;
import com.tek.teacher.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
@Controller
public class UserController {
@Autowired
UserService userService;
return modelAndView;
}
}
Now Create Service Layer class and respective method for storing User Information inside
database.
package com.tek.teacher.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.tek.teacher.dto.UserReigtserDto;
import com.tek.teacher.entity.UsersInfo;
import com.tek.teacher.repository.UserRepository;
@Service
public class UserService {
@Autowired
UserRepository repository;
Now create JPA Entity class for Database Operations, with columns related to User Details.
package com.tek.teacher.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table
public class UsersInfo{
@Id
@Column
private String emailId;
@Column
private String name;
@Column
private String contact;
@Column
private String password;
package com.tek.teacher.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.tek.teacher.entity.UsersInfo;
@Repository
public interface UserRepository extends JpaRepository<UsersInfo, String>{
Response :
<html>
<head>
<title>Login User</title>
</head>
<body>
<form action="loginCheck" method="POST">
Email : <input type="text" name="email" /> <br />
Password : <input type="password" name="pwd" /> <br />
<input type="submit" value="Login" /> <br />
</form>
</body>
</html>
@GetMapping("login")
public ModelAndView loadLoginPage() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("login");
return modelAndView;
}
Now Create Controller Method For Receiving Login Form Data and validation of User
Details.
@PostMapping("/loginCheck")
public ModelAndView validateUser(HttpServletRequest request) {
package com.facebook.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.facebook.entity.FacebookUsers;
@Repository
public interface UserRepository extends JpaRepository<FacebookUsers, String>{
Response :
Response :
Generally we will choose HTTP method depends on Data Base Operations of the
requirement i.e. When we are implementing Handler methods finally as part of implantation
which database query is executed as explained as follows.
Create, Read, Update, and Delete — or CRUD — are the four major functions used to
interact with database applications. The acronym is popular among programmers, as it
provides a quick reminder of what data manipulation functions are needed for an application
to feel complete. Many programming languages and protocols have their own equivalent
of CRUD, often with slight variations in how the functions are named and what they do. For
example, SQL — a popular language for interacting with databases — calls the four functions
Insert, Select, Update, and Delete. CRUD also maps to the major HTTP methods.
Although there are numerous definitions for each of the CRUD functions, the basic idea is that
they accomplish the following in a collection of data:
Read Retrieves entries that match certain criteria (if there are any) Select
Generally most of the time we will choose HTTP methods of an endpoint based on
Requirement Functionality performing which operation out of CRUD operations. This is a best
practice of creating REST API’s.
CRUD HTTP
CREATE POST
READ GET
UPDATE PUT
DELETE DELETE
Web services are used to integrate different applications and systems, regardless of their
platform or programming language. They can be used to provide a variety of services, such
as:
• Information retrieval
• Transaction processing
• Data exchange
• Business process automation
SOAP is a protocol for exchanging structured information using XML. It provides a way
for applications to communicate by sending messages in a predefined format. SOAP web
services offer a well-defined contract for communication and are often used in enterprise-
level applications due to their security features and support for more complex scenarios.
REST is an architectural style that uses HTTP methods (GET, POST, PUT, DELETE) to
interact with resources in a stateless manner. RESTful services are simple, lightweight, and
widely used due to their compatibility with the HTTP protocol. They are commonly used for
building APIs that can be consumed by various clients, such as web and mobile applications.
The choice of web service type depends on factors such as the nature of the application, the
level of security required, the complexity of communication, and the preferred data format.
REST API:
RESTful API is an interface that two computer systems use to exchange information
securely over the internet. Most business applications have to communicate with other
internal and third-party applications to perform various tasks.
API: An API is a set of definitions and protocols for building and integrating application
software. It’s sometimes referred to as a contract between an information provider and an
information consumer. An application programming interface (API) defines the rules that you
must follow to communicate with other software systems. Developers expose or create APIs
so that other applications can communicate with their applications programmatically. For
example, the ICICI application exposes an API that asks for banking users, Card Details , Name,
REST is a set of architectural style but not a protocol or a standard. API developers
can implement REST in a variety of ways. When a client request is made via a RESTful API, it
transfers a representation of the state of the resource to the requester or endpoint. This
information or representation is delivered in one of several formats like JSON or XML via HTTP
Protocol.
JSON is the most generally popular format to use because, despite its name, it’s language-
agnostic, as well as readable by both humans and machines.
REST API architecture that imposes conditions on how an API should work. REST was
initially created as a guideline to manage communication on a complex network like the
internet. You can use REST-based architecture to support high-performing and reliable
communication at scale. You can easily implement and modify it, bringing visibility and cross-
platform portability to any API system.
Clients: Clients are users who want to access information from the web. The client can
be a person or a software system that uses the API. For example, developers can write
programs that access weather data from a weather system. Or you can access the same data
from your browser when you visit the weather website directly.
Resources: Resources are the information that different applications provide to their
clients/users. Resources can be images, videos, text, numbers, or any type of data. The
machine that gives the resource to the client is also called the server. Organizations use APIs
to share resources and provide web services while maintaining security, control, and
authentication. In addition, APIs help them to determine which clients get access to specific
internal resources.
API developers can design APIs using several different architectures. APIs that follow the REST
architectural style are called REST APIs. Web services that implement REST architecture are
called RESTful web services. The term RESTful API generally refers to RESTful web APIs.
However, you can use the terms REST API and RESTful API interchangeably.
The following are some of the principles of the REST architectural style:
Uniform Interface: The uniform interface is fundamental to the design of any RESTful
webservice. It indicates that the server transfers information in a standard format. The
formatted resource is called a representation in REST. This format can be different from the
internal representation of the resource on the server application. For example, the server can
store data as text but send it in an HTML representation format.
Layered system: In a layered system architecture, the client can connect to other authorized
intermediate services between the client and server, and it will still receive responses from
the server. Sometimes servers can also pass on requests to other servers. You can design your
RESTful web service to run on several servers with multiple layers such as security,
application, and business logic, working together to fulfil client requests. These layers remain
invisible to the client. We can achieve this as part of Micro Services Design.
Scalability: Systems that implement REST APIs can scale efficiently because REST optimizes
client-server interactions. Statelessness removes server load because the server does not
have to store past client request information.
Platform and Language Independence: REST APIs are platform and language independent,
meaning they can be consumed by a wide range of clients, including web browsers, mobile
devices, and other applications. As long as the client can send HTTP requests and understand
the response, it can interact with a REST API regardless of the technology stack used on the
server side. You can write both client and server applications in various programming
languages without affecting the API design. We can also change the technology on both sides
without affecting the communication.
Overall, REST APIs provide a simple, scalable, and widely supported approach to building web
services. These advantages in terms of simplicity, platform independence, scalability,
flexibility, and compatibility make REST as a popular choice for developing APIs in various
domains, from web applications to mobile apps and beyond.
The basic function of a RESTful API is the same as browsing the internet. The client contacts
the server by using the API when it requires a resource. API developers explain how the client
should use the REST API in the server application with API documentation. These are the
general steps for any REST API call integration:
1. The client sends a request to the server. The client follows the API documentation to
format the request in a way that the server understands.
2. The server authenticates the client and Request and confirms that the client has the right
to make that request.
3. The server receives the request and processes it internally.
The REST API request and response details are vary slightly depending on how the API
developers implemented the API.
URI (Unique Resource Identifier) : The server identifies each resource with unique
resource identifiers. For REST services, the server typically performs resource identification
by using a Uniform Resource Locator (URL). The URL specifies the path to the resource. A URL
is similar to the website address that you enter into your browser to visit any webpage. The
URL is also called the request endpoint and clearly specifies to the server what the client
requires.
HTTP Method: Developers often implements RESTful APIs by using the Hypertext Transfer
Protocol (HTTP). An HTTP method tells the server what it needs to do with the resource. The
following are four common HTTP methods:
• GET: Clients use GET to access resources that are located at the specified URL on
the server.
• POST: Clients use POST to send data to the server. They include the data
representation with the request body. Sending the same POST request multiple times
has the side effect of creating the same resource multiple times.
HTTP Headers: Request headers are the metadata exchanged between the client and server.
Data: REST API requests might include data for the POST, PUT, and other HTTP methods to
work successfully.
Parameters: RESTful API requests can include parameters that give the server more details
about what needs to be done. The following are some different types of parameters:
• Path parameters that specify URL details.
• Query/Request parameters that request more information about the resource.
• Cookie parameters that authenticate clients quickly.
REST principles require the server response to contain the following main components:
Status line: The status line contains a three-digit status code that communicates request
success or failure.
2XX codes indicate success
4XX and 5XX codes indicate errors
3XX codes indicate URL redirection.
Message body: The response body contains the resource representation. The server selects
an appropriate representation format based on what the request headers contain i.e. like
JSON/XML formats. Clients can request information in XML or JSON formats, which define
how the data is written in plain text. For example, if the client requests the name and age of
a person named John, the server returns a JSON representation as follows:
{
"name":"John",
"age":30
}
Headers: The response also contains headers or metadata about the response. They
give more context about the response and include information such as the server, encoding,
date, and content type.
Spring MVC is a popular framework for creating web applications in Java. Implementing
RESTful web services in Spring MVC involves using the Spring framework to create endpoints
that follow the principles of the REST architectural style. It can be used to create RESTful web
services, which are web services that use the REST architectural style.
RESTful services allow different software systems to communicate over the internet using
standard HTTP methods, like GET, POST, PUT, and DELETE. These services are based on a set
of principles that emphasize simplicity, scalability, and statelessness.
In REST Services implementation, Data will be represented as JOSN/XML type most of the
times. Now a days JSON is most popular data representational format to create and produce
REST Services.
JSON:
JSON stands for JavaScript Object Notation. JSON is a text format for storing and
transporting data. JSON is "self-describing" and easy to understand.
JSON is a lightweight data-interchange format. JSON is plain text written in JavaScript object
notation. JSON is used to exchange data between multiple applications/services. JSON is
language independent.
o a string
o a number
o an object
o an array
o a Boolean
o null
JSON vs XML:
Both JSON and XML can be used to receive data from a web server. The following JSON and
XML examples both define an employee’s object, with an array of 3 employees:
JSON Example
{
"employees": [
{
"firstName": "John",
"lastName": "Doe"
},
{
"firstName": "Anna",
"lastName": "Smith"
},
{
"firstName": "Peter",
"lastName": "Jones"
}
]
}
XML Example:
<employees>
<employee>
<firstName>John</firstName>
<lastName>Doe</lastName>
</employee>
<employee>
<firstName>Anna</firstName>
When A Request Body Contains JSON/XML data Format, then how Spring MVC/JAVA
language handling Request data?
Here, We should Convert JSON/XML data to JAVA Object while Request landing on Controller
method, after that we are using JAVA Objects in further process. Similarly, Sometimes we have
to send Response back as either JSON or XML format i.e. JAVA Objects to JSON/XML Format.
For these conversions, we have few pre-defined solutions in Market like Jackson API, GSON
API, JAXB etc..
Note: we should carte Java POJO classes specific to JSON payload structure, to enable auto
conversion between JAVA and JSON.
JSON Payload: Below Json contains ARRY of String Data Type values
{
"student":[
"Dilip",
"Naresh",
"Mohan",
"Laxmi"
]
}
Java Class: JSON Array of String will be takes as List<String> with JSON key name.
import java.util.List;
{
"nareshIt": {
"students": [
{
"no": "1",
"name": "Dilip",
"mobile": 8826111377
},
{
"no": "2",
"name": "Naresh",
"mobile": 8125262702
}
]
}
}
Below picture showing how are creating JAVA classes from above payload.
Student.java
import java.util.ArrayList;
public class NareshIt {
private ArrayList<Student> students;
StudentsData.java
{
"student": [
{
"firstName": "Dilip",
"lastName": "Singh",
"mobile": 88888,
"pwd": "Dilip",
"emailID": "Dilip@Gmail.com"
},
{
"firstName": "Naresh",
"lastName": "It",
"mobile": 232323,
"pwd": "Naresh",
"emailID": "Naresh@Gmail.com"
}
]
import com.fasterxml.jackson.annotation.JsonProperty;
Another class To Wrap above class Object as List with property name student as per JSON.
import java.util.List;
List<StudentInfo> student;
From the above JSON payload and JAVA POJO class, we can see a difference for one JSON
property called as emailID i.e. in JAVA POJO class property name we taken as email instead
of emailID. In Such case to map JSON to JAVA properties with different names, we use an
annotation called as @JsonProperty("jsonPropertyName").
@JsonProperty:
The @JsonProperty annotation is used to specify the property name in a JSON object
when serializing or deserializing a Java object using the Jackson API library. It is often used
when the JSON property name is different from the field name in the Java object, or when
the JSON property name is not in camelCase.
As a developer, we should always create POJO classes aligned to JSON payload to bind JOSN
data to Java Object with @RequestBody annotation.
To implement REST services in Spring MVC, you can use the @RestController annotation. This
annotation marks a class as a controller that returns data to the client in a RESTful way.
@RestController:
@Controller
public class MAcBookController {
@GetMapping(path = "/mac/details")
@ResponseBody
@GetMapping(path = "/iphone/details")
@ResponseBody
public String getIphoneDetail() {
return "Iphone Details : Price 150000. Model 15 Pro";
}
}
@RestController
public class MAcBookController {
@GetMapping(path = "/mac/details")
public String getMacBookDetail() {
return "MAC Book Details : Price 200000. Model 2022";
}
@GetMapping(path = "/iphone/details")
public String getIphoneDetail() {
return "Iphone Details : Price 150000. Model 15 Pro";
}
}
@RequestBody Annotation:
The @RequestBody annotation in Spring is used to bind the HTTP request body to a
method parameter. This means that Spring will automatically deserialize the request body
into a Java object and that object is then passed to the method as a parameter. The
@RequestBody annotation can be used on controller methods.
For example, the following controller method accepts a User object as a parameter:
@PostMapping("/users")
public User createUser(@RequestBody User user) {
// ...
➢ When you send a POST request to the /users endpoint with a JSON body containing the
user data, Spring will automatically deserialize the JSON into a User object and pass it to
the createUser() method.
➢ The @RequestBody annotation is a powerful tool that makes it easy to work with HTTP
request bodies in Spring. It is especially useful for developing REST APIs.
Here are some additional things to keep in mind about the @RequestBody annotation:
• The request body must be in a supported media type, such as JSON, XML.
• Spring will use an appropriate HTTP message converter to deserialize the request body.
• If the request body cannot be deserialized, Spring will throw
a HttpMessageNotReadableException.
Postman is a popular and widely used API (Application Programming Interface) testing
and development tool. It provides a user-friendly interface for sending HTTP requests to APIs
and inspecting the responses. Postman offers a range of features that make it valuable for
developers, testers, and anyone working with APIs:
• API client: Postman provides a powerful API client that allows you to send HTTP requests
to any API and inspect the responses. The API client supports a wide range of
authentication protocols and response formats.
• API testing: Postman provides a powerful API testing framework that allows you to create
and execute tests for your APIs. Postman tests can be used to validate the functionality,
performance, and security of your APIs.
• API design: Postman can be used to design your API specifications in OpenAPI, RAML,
GraphQL, or SOAP formats. Postman's schema editor makes it easy to work with
specification files of any size, and it validates specifications with a built-in linting engine.
Here are some examples of how Postman API Tools can be used:
• A developer can use Postman to explore a new API and learn how to use it.
• A QA engineer can use Postman to create and execute tests for an API.
• A DevOps engineer can use Postman to monitor an API for performance and availability
issues.
• A product manager can use Postman to generate documentation for an API.
• A sales engineer can use Postman to demonstrate an API to a customer.
Project Setup:
Requirement: Write a Rest Service for User Registration. User Details Should Be :
• User Name
• Email Id
• Mobile
• Password
{
"name" : "Dilip",
"email" : "dilip@gmail.com",
"mobile" : "+91 73777373",
"password" : "Dilip123"
}
package com.swiggy.user.request;
4. Now Create A controller and inside an endpoint for User Register Request Handling.
package com.swiggy.user.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.swiggy.user.request.UserRegisterRequest;
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/register")
public String getUserDetails(@RequestBody UserRegisterRequest request) {
System.out.println(request.getEmail());
System.out.println(request.getName());
System.out.println(request.getPassword());
return "User Created Successfully";
}
}
5. Deploy Your Application in Server Now. After Deployment we have to Test now weather it
Service is working or not.
o Open Postman
o Now Click on Add request
o Select Your Service HTTP method
o And Enter URL of Service
o Select Body
o Select raw
o Select JSON
o Enter JSON Body as shown in Below.
In Below, We can See in Server Console, Request Data is printed what we Received
from Client/Postman level as JSON data.
Examples:
URI with Template Path variables : /location/{locationName}/pincode/{pincode}
URI with Data replaced : /location/Hyderabad/pincode/500072
@GetMapping("/api/employees/{empId}")
public String getEmployeesById(@PathVariable(“empId”) String empId) {
In these kind of requirements, like getting Data with Resource ID’s. We can Use Path Variable
as part of URI instead of JSON mapping and equivalent Request Body classes. So Create a
REST endpoint with a Path Variable of Email ID.
➢ Now Add Method in Service Class for interacting with Repository Layer.
NOTE: We no need to define value inside @PathVariable when we are taking method
parameter name as it is URI template/Path variable.
Syntax : /{pathvar1}/{pathvar2}
Example: /pharmacy/{location}/pincode/{pincode}
After adding Orders, Please Get Order Details based on Email Id and Order Status.
In this case, we are passing values of Email ID and Order Status to find out Order Details. Now
we can take Path variables here to fulfil this requirement.
➢ Create an endpoints for adding Order Details and Getting Order Details with Email ID
and Order Status.
OrderRequest.java
package com.swiggy.order.request;
➢ OrderResponse.java
package com.swiggy.order.response;
public OrderResponse() {
}
public OrderResponse(String orderID, String orderstatus, double amount,
String emailId, String city) {
this.orderID = orderID;
this.orderstatus = orderstatus;
this.amount = amount;
this.emailId = emailId;
this.city = city;
}
public String getOrderID() {
package com.swiggy.order.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "swiggy_orders")
public class SwiggyOrders {
@Id
@Column
private String orderID;
package com.swiggy.order.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
OrderService orderService;
@PostMapping(value = "/create")
public String createOrder(@RequestBody OrderRequest request) {
return orderService.createOrder(request);
}
@GetMapping("/email/{emailId}/status/{status}")
public List<OrderResponse> getOrdersByemaailIDAndStaus(@PathVariable String
emailId, @PathVariable("status") String orderStaus ){
List<OrderResponse> orders =
orderService.getOrdersByemaailIDAndStaus(emailId, orderStaus);
return orders;
}
}
package com.swiggy.order.service;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.swiggy.order.entity.SwiggyOrders;
import com.swiggy.order.repository.OrderRepository;
import com.swiggy.order.request.OrderRequest;
import com.swiggy.order.response.OrderResponse;
@Service
public class OrderService {
return allOrders;
}
}
Add JPA Derived Query findBy() Method for Email Id and Order Status.
package com.swiggy.order.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.swiggy.order.entity.SwiggyOrders;
@Repository
public interface OrderRepository extends JpaRepository<SwiggyOrders, String>{
List<SwiggyOrders> findByEmailIdAndOrderstatus(String emailId, String orderStaus);
From Postman Test end point: URL formation, replacing Path variables with real values
➢ We can also handle more than one Path Variables of URI by using a method parameter
of type java.util.Map<String, String>.
@GetMapping("/pharmacy/{location}/pincode/{pincode}")
public String getPharmacyByLocationAndPincode(@PathVariable Map<String, String>
values) {
String location = values.get("location"); // Key is Path variable
String pincode = values.get("pincode");
return "Location Name : " + location + ", Pin code: " + pincode;
}
Query string is a part of a uniform resource locator (URL) that assigns values to
specified parameters. A query string commonly includes fields added to a base URL by a Web
browser or other client application. Let’s understand this statement in a simple way by an
example. Suppose we have filled out a form on websites and if we have noticed the URL
something like as shown below as follows:
So in the above URL, the query string is whatever follows the question mark sign (“?”) i.e
(number1=23&number2=12) this part. And “number1=23”, “number2=12” are Query
Parameters which are joined by a connector “&”.
So in the above URL, the query string is “title=Query_string&action=edit” this part. And
“title=Query_string”, “action=edit” are Query Parameters which are joined by a connector
“&”.
Now we are discussing the concept of the query string and query parameter from the Spring
MVC point of view. Developing Spring MVC application and will understand how query strings
and query parameters are generated.
@RequestParam:
In Spring, we use @RequestParam annotation to extract the id of query parameters. Assume
we have Users Data, and we should get data based on email Id.
@GetMapping("/details")
public String getUserDetails(@RequestParam String email) {
//Now we can pass Email Id to service layer to fetch user details
return "Email Id of User : " + email;
}
Requirement: Please Get User Details by using either email or mobile number
Method in controller:
@GetMapping("/details")
public List<Users> getUsersByEmailOrMobile(@RequestParam String email,
@RequestParam String mobileNumber) {
//Now we can pass Email Id and Mobile Number to service layer to fetch user details
List<Users> response = service.getUsersByEmailOrMobile(email, mobileNumber);
return response;
}
@GetMapping("/details")
public List<Users> getUsersByEmailOrMobile(@RequestParam String email,
@RequestParam(required = false) String mobileNumber) {
Testing Endpoint: Now mobileNumber Request Parameter is missing in URI, but still our
endpoint is working only with one Request parameter email.
@GetMapping("/api")
@ResponseBody
public String getUsers(@RequestParam List<String> id) {
return "IDs are " + id;
}
URI: /api?id=1,2,3
URI : /api?id=1&id=2
We can also have multiple parameters without defining their names or count by just using
a Map:
@GetMapping("/api")
public String getUsers(@RequestParam Map<String,String> allParams) {
return "Parameters are " + allParams.entrySet();
}
Now we can read all Request Params from Map Object as Key and Value Pairs and we will
utilize as per requirement.
As a best practice, almost of developers are recommending following way. If you want
to identify a resource, you should use Path Variable. But if you want to sort or filter items on
data, then you should use query parameters. So, for example you can define like this:
“Swagger is a set of rules, specifications and tools that help us document our APIs.”
“By using Swagger UI to expose our API’s documentation, we can save significant
time.”
Swagger UI allows anyone — be it your development team or your end consumers — to
visualize and interact with the API’s resources without having any of the implementation logic in place.
It’s automatically generated from your OpenAPI (formerly known as Swagger) Specification, with the
visual documentation making it easy for back end implementation and client side consumption.
Swagger UI is one of the platform’s attractive tools. In order for documentation to be useful,
we will need it to be browsable and to be perfectly organized for easy access. It is for this reason that
writing good documentation may be tedious and use a lot of the developers’ time.
4. After Project Creation, Open pox.xml file and add below dependency starter in side
dependencies section and save.
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
server.port=5566
server.servlet.context-path=/user
7. Enter URL in Browser for OpenAPI Swagger Documentation of Web services. Then you can
Swagger UI page with empty Services List. Because Our application not contained any web
services.
package com.tek.teacher.user.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
return response;
}
}
package com.tek.teacher.user.controller;
CreateUserResponse.java
package com.tek.teacher.user.controller;
Now Start Your Spring Boot App. After application started, Now please enter swagger URL in
browser. You can see all endpoints/services API request and response format Data.
We can Test API calls from Swagger UI, Please click on Try it Out button then it will you
pass values to parameters/properties. In Below, I am passing userId value in GET API
service and then click on Execute.
This is how we can integrate and use swagger UI API Documentation Tool with our
applications to share all REST API data in UI format.
In Spring Boot, whenever we create a new Spring Boot Application in spring starter, or inside
an IDE (Eclipse or STS) a file is located inside the src/main/resources folder named
as application.properties file.
In place of properties file, we can use YAML/YML based configuration files to achieve same
behaviour.
What is this YAML/YML file?
YAML stands for Yet Another Markup Language. YAML is a data serialization language
that is often used for writing configuration files. So YAML configuration file in Spring Boot
provides a very convenient syntax for storing logging configurations in a hierarchical format.
The application.properties file is not that readable. So most of the time developers choose
application.yml file over application.properties file. YAML is a superset of JSON, and as such
is a very convenient format for specifying hierarchical configuration data. YAML is more
readable and it is good for the developers to read/write configuration files.
• Comments can be identified with a pound or hash symbol (#). YAML does not support
multi-line comment, each line needs to be suffixed with the pound character.
• YAML files use a .yml or .yaml extension, and follow specific syntax rules.
server.port=4343
server.servlet.context-path=/gmail
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=c##dilip
spring.datasource.password=dilip
spring.jpa.show-sql=true
Similarly, we can add all other Properties in same format always as per YAML scriprt rules
and regulations.
Now we can start our Spring Boot application as usual and continue development and
testing activities.
HTTP status codes are three-digit numbers that are returned by a web server in response to a
client's request made to a web page or resource. These codes indicate the outcome of the
request and provide information about the status of the communication between the client
(usually a web browser) and the server. They are an essential part of the HTTP (Hypertext
Transfer Protocol) protocol, which is used for transferring data over the internet. HTTP defines
these standard status codes that can be used to convey the results of a client’s request.
Some of HTTP status codes summary being used mostly in REST API creation
1xx Informational:
This series of status codes indicates informational content. This means that the
request is received and processing is going on. Here are the frequently used informational
status codes:
100 Continue:
This code indicates that the server has received the request header and the client can
now send the body content. In this case, the client first makes a request (with the Expect:
100-continue header) to check whether it can start with a partial request. The server can then
respond either with 100 Continue (OK) or 417 Expectation Failed (No) along with an
appropriate reason.
2xx Success:
This series of status codes indicates the successful processing of requests. Some of the
frequently used status codes in this class are as follows.
200 OK:
This code indicates that the request is successful and the response content is returned
to the client as appropriate.
201 Created:
This code indicates that the request is successful and a new resource is created.
204 No Content:
This code indicates that the request is processed successfully, but there's no return
value for this request. For instance, you may find such status codes in response to the deletion
of a resource.
3xx Redirection:
This series of status codes indicates that the client needs to perform further actions
to logically end the request. A frequently used status code in this class is as follows.
403 Forbidden:
This code indicates that the server is refusing to respond to the request even if the
request is valid. The reason will be listed in the body content if the request is not a HEAD
method.
409 Conflict:
This code indicates that the request cannot be completed because it conflicts with
some rules established on resources, such as validation failure.
Generally we will have likewise below scenarios and respective status codes in REST API
services. For Example,
To bind response data and relevant HTTP status code with endpoint in side controller class,
we will use predefined Spring provided class ResponseEntity.
ResponseEntity:
ResponseEntity represents the whole HTTP response: status code, headers, and body.
As a result, we can use it to fully configure the HTTP response. If we want to use it, we have
to return it from the endpoint, Spring takes care of the rest. ResponseEntity is a generic type.
Consequently, we can use any type as the response body. This will be used in Controller
methods as well as in RestTemplate.
@RequestMapping("/handle")
public ResponseEntity<T> handle() {
// Logic
return new ResponseEntity<T>(ResponseData, ResponseHeaders, StatusCode);
}
Points to be noted:
@RestController
public class NetBankingController {
@PostMapping("/create")
@ResponseStatus(value = HttpStatus.CREATED) //Using Annotation
public String createAccount(@Valid @RequestBody AccountDetails accountDetails) {
@RestController
public class OrdersController {
@GetMapping("/orders")
public ResponseEntity<Order> getOrders(@RequestParam("orderID") String orderID) {
Order response = service.getOrders(orderID);
return new ResponseEntity<Order>( response, HttpStatus.OK);
}
}
This is how can write any Response Status code in REST API Service implementation.
Please refer RET API Guidelines for more information at what time which HTTP status code
should be returned to client.
HTTP headers can be classified into two main categories: request headers and response
headers.
Request Headers:
Request headers are included in an HTTP request sent by a client to a server. They provide
information about the client's preferences, the type of data being sent, authentication
credentials, and more. Some common request headers include:
• User-Agent: Contains information about the user agent (usually a web browser)
making the request.
• Accept: Specifies the media types (content types) that the client can process.
Response Headers:
Response headers are included in an HTTP response sent by the server to the client. They
convey information about the server's response, the content being sent, caching directives,
and more. Some common response headers include:
• Content-Type: Specifies the format of the data in the response body.
• Content-Length: Specifies the size of the response body in bytes.
• Set-Cookie: Sets a cookie in the client's browser for managing state.
HTTP headers are important for various purposes, including negotiating content types,
enabling authentication, handling caching, managing sessions, and more. They allow both
clients and servers to exchange additional information beyond the basic request and response
data. Proper understanding and usage of HTTP headers are essential for building efficient and
secure web applications.
Spring MVC provides mechanisms to work with HTTP headers both in requests and responses.
Here's how you can work with HTTP headers in Spring MVC.
Accessing Request Headers: Spring provides the @RequestHeader annotation that allows
you to access specific request headers in your controller methods. You can use this annotation
as a method parameter to extract header values.
@GetMapping("/endpoint")
public ResponseEntity<String> handleRequest(@RequestHeader("Header-Name") String
headerValue) {
// Do something with the header and other values
➢ Header and its Value should come from Client while they are triggering this endpoint.
package com.flipkart.controller;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
@RestController
public class OrderController {
//Header is Part of Request, i.e. Should be Come from Client Side.
@GetMapping("/data")
public String testHeaders(@RequestHeader("user-name") String userName) {
return "Connected User : " + userName;
}
}
Testing: Without Sending Header and Value from Client, Sending Request to Service.
Result : We Got Bad request like Header is Missing i.e. Header is Mandatory by default if
we defined in Controller method.
package com.flipkart.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
Testing:
➢ No header Added, So Header value is null.
package com.flipkart.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
Testing: Without adding Header and its value, triggering Service. Default Value of Header
user-name is flipkart is considered by Server as per implementation.
In Spring MVC, response headers can be set using the HttpServletResponse object or
the ResponseEntity class.
Here are some of the commonly used response headers in Spring MVC:
For example:
The ResponseEntity class is a more recent addition to Spring MVC. It provides a more concise
way to set headers, as well as other features such as status codes and body content. To set a
header using the ResponseEntity class, you can use the headers() method.
For example:
HttpHeaders:
In Spring MVC, the HttpHeaders class is provided by the framework as a convenient
way to manage HTTP headers in both request and response contexts. HttpHeaders is part of
the org.springframework.http package, and it provides methods to add, retrieve, and
manipulate HTTP headers. Here's how you can use the HttpHeaders class in Spring MVC:
In a Response:
You can use HttpHeaders to set custom headers in the HTTP response. This is often
done when you want to include specific headers in the response to provide additional
information to the client.
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
Testing: Trigger endpoint from Client: Got Token and its value from Service in Headers.
If we are not handled exceptions then we will see Exception stack trace as shown in below at
HTTP client level as a response. As a Best Practice we should show meaningful Error Response
messages.
ControllerAdvice is an annotation in Spring and, as the name suggests, is “advice” for all
controllers. It enables the application of a single ExceptionHandler to multiple controllers.
With this annotation, we can define how to treat an exception in a single place, and the
system will call this exception handler method for thrown exceptions on classes covered by
this ControllerAdvice.
By using @ExceptionHandler and @ControllerAdvice, we’ll be able to define a central point
for treating exceptions and wrapping them in an Error object with the default Spring Boot
error-handling mechanism.
The first solution works at the @Controller level. We will define a method to handle
exceptions and annotate that with @ExceptionHandler i.e. We can define Exception Handler
Methods in side controller classes. This approach has a major drawback: The
@ExceptionHandler annotated method is only active for that particular Controller, not
globally for the entire application. But better practice is writing a separate controller advice
classes dedicatedly handle different exception at one place.
@RestController
public class FooController{
// Endpoint Methods
• It gives us full control over the body of the response as well as the status code.
• It provides mapping of several exceptions to the same method, to be handled together.
• It makes good use of the newer RESTful ResposeEntity response.
One thing to keep in our mind here is to match the exceptions declared
with @ExceptionHandler to the exception used as the argument of the method.
Example of Controller Advice class : Controller Advice With Exception Handler methods
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import jakarta.servlet.http.HttpServletRequest;
@ControllerAdvice
public class OrderControllerExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?>
handleMethodArgumentException(MethodArgumentNotValidException ex,
HttpServletRequest rq) {
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<?> handleNullpointerException(NullPointerException ex,
HttpServletRequest request) {
@ExceptionHandler(ArithmeticException.class)
public ResponseEntity<?> handleArithmeticException(ArithmeticException ex,
HttpServletRequest request) {
// Below Exception handler method will work for all child exceptions when we are not
//handled those specifically.
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleException(Exception ex, HttpServletRequest
request) {
• Now see How we are getting Error response with meaningful messages when Request
Body validation failed instead of complete Exception stack trace.
How it is working?
Whenever an exception occurred at controller layer due to any reason, immediately
controller will check for relevant exceptions handled as part of Exception Handler or not. If
handled, then that specific exception handler method will be executed and response will be
forwarded to clients. If not handled, then entire exception error stack trace will be forwarded
to client an it’s not suggestable.
Which Exception takes Priority if we defined Child and Parent Exceptions Handlers?
consumes:
Using a consumes attribute to narrow the mapping by the content type. You can
declare a shared consumes attribute at the class level i.e. applicable to all controller
methods. Unlike most other request-mapping attributes, however, when used at the class
level, a method-level consumes attribute overrides rather than extends the class-level
declaration.
The consumes attribute also supports negation expressions — for example, !text/plain means
any content type other than text/plain.
MediaType class provides constants for commonly used media/content types, such as
APPLICATION_JSON_VALUE and APPLICATION_XML_VALUE etc..
Now let’s have an example, as below shown. Created an endpoint method, which accepts
only JSON data Request by providing consumes ="application/json".
To support XML request Body, we should follow below configurations/steps. Spring boot, by
default, configures Jackson for parsing Java objects to JSON and converting JSON to Java
objects as part of REST API request-response handling. To accept XML requests and send XML
responses, there are two common approaches.
▪ Using Jackson XML Module
▪ Using JAXB Module
Start with adding Jackson’s XML module by including the jackson-dataformat-xml
dependency. Spring boot manages the library versions, so the following declaration is enough.
Add below both dependencies in POM.xml file of application.
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Now we can define and access REST API Services with XML data format.
➢ Creating a service which accepts only XML Request Body i.e. endpoint accepts now only
XML request body but not JSON.
Create endpoint which supports both JSON and XML Request Body.
Below URI Request Mapping will support both XML and JSON Requests. We can pass multiple
data types consumes attribute with array of values.
Spring Provided a class MediaType with Constant values of different Medi Types. We will use
MediaType in consumes and produces attributes values.
consumes ={"application/json","application/xml"}
is equals to
consumes ={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}
Above endpoint generates only XML response for every incoming request.
Request for XML response: Add Header Accept and value as application/xml as shown.
Request for JSON response: Add Header Accept and value as application/json as shown.
Consuming REST services is nothing but integrating/calling other application REST API
services from our application logic.
For Example,
ICICI bank will produce API services to enable banking functionalities. Now Amazon
application integrated with ICICI REST services for performing Payment Options.
In This case:
Producer is : ICICI
Consumer is : Amazon
In Spring MVC, Spring Provided an HTTP or REST client class called as RestTemplate from
package org.springframework.web.client. RestTemplate class provided multiple utility
methods to consume REST API services from one application to another application.
From above swagger snap, we should understand below points for that API call.
1. URL : http://localhost:6677/pharmacy/add/store/location
2. HTPP method: POST
3. Request Body Should contain below payload structure
Now based on above data, we are going to write logic of RestTemplate to consume in our
application flipkart.
Now assume we are receiving data from UI/Frontend to Flipkart application and that data we
are transferring to Pharmacy API with help of RestTemplate.
@RestController
@RequestMapping("/pharmacy")
public class PharmacyController {
@Autowired
PharmacyService pharmacyService;
@PostMapping("/add/location")
public String addPharmacyDetails(@RequestBody PharmacyLocation request) {
return pharmacyService.addPharmacyDetails(request);
}
}
➢ Now in Service class, we should write logic of integrating Pharmacy endpoint for adding
store details as per swagger notes.
HttpEntity:
HttpEntity class is used to represent an HTTP request or response entity. It
encapsulates/binds the HTTP message's headers and body. You can use HttpEntity to
customize the headers and body of the HTTP request before sending it using RestTemplate. It
provides more control and flexibility over the request or response compared to simpler
methods like getForEntity(), postForObject(), etc.
➢ Now In service layer, Please map data from controller layer to API request body class.
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.flipkart.dto.PharmacyData;
import com.flipkart.pharmacy.request.PharmacyLocation;
@Service
public class PharmacyService {
➢ Now Test it from Postman and check pharmacy API call triggered or not i.e. check data is
inserted in DB or not from pharmacy application.
➢ Now create Request body as per our controller request body class.
{
"location": "pune",
"contact": "+918125262702",
"pincode": 500088
}
➢ Before executing from post man, please check DB data. In my table I have below data right
now.
➢ Request executed successfully and you got response from Pharmacy API of post REST API
call what we integrated. Verify In Database record inserted or not. It’s inserted.
When we are sending data to flipkart app, now flipkart app forwarded data to pharmacy
application via REST API call.
Now Let’s integrate Path variable and Query Parameters REST API Services:
Consuming API Services with Query Parameters:
Example1 : Consume below Service which contains Query String i.e. Query Parameters.
PharmacyResponse.java:
➢ Consume Below REST Service which contains Query Parameters From our Application.
package com.flipkart.service;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
Output:
{
"userName":"Suresh Singh",
"accountBalance":4040000.0,
"accountNumber":"122"
}
return respone;
}
➢ Example 3: We are Integrating one Real time API service from Online.
Above API call, Producing JSON Response, as shown in below Postman. Depends on Response
we should create JAVA POJO classes to serialize data from JAVA to JSON and vice versa.
➢ Based on API call Response, we should create Response POJO classes aligned to JSON
Payload.
Country.java
public class Country {
private String name;
private String iso2;
private int lat;
System.out.println(respone);
return respone;
}
In Spring's RestTemplate, we can work with HTTP headers by using the HttpHeaders
class. You can add, retrieve, and manipulate headers in both requests and responses. Here's
how we can work with headers in RestTemplate:
In this example, we create an HttpHeaders object and set custom headers. We can add
headers to your HTTP request before sending it using RestTemplate. Here's an example of how
to add headers to a request:
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
We can access response headers when you receive a response from the server. Here's
an example:
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
In this example, we use responseEntity.getHeaders() to access the response headers and then
retrieve specific header values using responseHeaders.getFirst("Header-Name").
Working with headers allows you to customize your requests and process responses more
effectively in your RestTemplate interactions.