Api&m Unit 2 JSVGK
Api&m Unit 2 JSVGK
Spring Boot
1: Creating a Spring Boot Application:
How to Create a Spring Boot Project?
Spring Boot is built on the top of the spring and contains all the features of spring. And is
becoming a favorite of developers these days because of its rapid production-ready environment
which enables the developers to directly focus on the logic instead of struggling with the
configuration and setup. Spring Boot is a microservice-based framework and making a
production-ready application in it takes very little time.
Following are some of the features of Spring Boot:
It allows avoiding heavy configuration of XML which is present in spring
It provides easy maintenance and creation of REST endpoints
It includes embedded Tomcat-server
Deployment is very easy, war and jar files can be easily deployed in the tomcat server
For more information please refer to this article: Introduction to Spring Boot Generally, to
develop a Spring Boot Application we choose Eclipse, Spring Tool Suite, and IntelliJ IDEA
IDE. So in this article, we are going to create our spring boot project in these 3 IDEs.
Create a Spring Boot Project in Eclipse IDE
The Eclipse IDE is famous for the Java Integrated Development Environment (IDE), but it
has a number of pretty cool IDEs, including the C/C++ IDE, JavaScript/TypeScript IDE, PHP
IDE, and more.
Procedure:
1. Install Eclipse IDE for Enterprise Java and Web Developer
2. Create a Spring Boot Project in Spring Initializr
3. Import Spring Boot Project in Eclipse IDE
4. Search “maven” and choose Existing Maven Project
5. Choose Next
6. Click on the Browse button and select the extracted zip
7. Click on the Finish button and we are done creating the Spring Boot project Let us
discuss these steps in detail alongside visual aids
Step 1: Install Eclipse IDE for Enterprise Java and Web Developer
Please refer to this article How to Install Eclipse IDE for Enterprise Java and Web Development
and install the Eclipse IDE.
2 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
Step 2: Create a Spring Boot Project in Spring Initializr
Go to this link and create a Spring Boot project. Please fill in all the details accordingly and at
last click on the GENERATE button below. This will download your Spring Boot project in zip
format. Now extract the folder into your local machine. For more details in Spring Initializr refer
to this article: Spring Initializr
Step 4: Search “maven” and choose Existing Maven Project and click on the Next
button as shown in the below image.
4 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
Step 5: Now click on the Browse button and select the extracted zip file that has been generated.
Step 6. And at last click on the Finish button and we are done creating the Spring Boot project
5 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
By now, Spring Boot project has been created as depicted in the below media
Step 3: In this pop-up window fill the detail below as follows and further click on the Next
button as shown in the below image.
Step 4: Choose your required Spring Boot Version and select your dependencies as per your
project requirement. And at last click on the Next button.
8 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
Below is the Welcome screen after you have successfully Created and Setup Spring Boot Project
in Spring Tool Suite
10 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
Create a Spring Boot Project in IntelliJ IDEA
IntelliJ is an integrated development environment(IDE) written in Java. It is used for developing
computer software. This IDE is developed by Jetbrains and is available as an Apache 2 Licensed
community edition and a commercial edition.
Procedure:
1. Install IntelliJ IDEA on the local machine.
2. Create a Spring Boot Project in Spring Initializr
3. Import Spring Boot Project in IntelliJ IDEA
4. Choose the project that you have created in above step 2.
Step 1: Install IntelliJ IDEA on the local machine for that do go through pre-requisite for
installing Intellij Idea on the system.
Step 2: Create a Spring Boot Project in Spring Initializr
Create a Spring Boot project and do fill in all the details accordingly and at last click on the
GENERATE button below. This will download your Spring Boot project in zip format. Now
extract the folder into your local machine and do go through the introduction to Spring Initializr
before proceeding further.
The springbootapplication annotation helps the developers to mark configuration classes. The
main three features of a springbootapplication annotation are as follows:
13 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
1. @EnablAutoConfiguration: Because of this feature, the application automatically produces
and registers bean methods depending on both the jar files on the included classpath and the beans
we define.
Example:
@Configuration
@EnableAutoConfiguration
//Main method
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
2. @Configuration: It tries to configure your Spring application automatically based on the jar
dependencies you provided. You can use properties files, YAML files, environment variables, and
command-line arguments to externalise configuration.
Example:
@Configuration
//Main method
@bean
// bean method's name or id
public CN cnBean() { // Returning the CN object
//Main method
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
To use the SpringApplication class, we need to create an instance of it and call the run() method.
The run() method takes a list of arguments as input, which is used to configure the application.
The following code example shows how to bootstrap and launch a simple Spring Boot application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
// works same as @EnableAutoConfiguration, @Configuration, and @ComponentScan.
15 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
The above code simply calls the SpringApplication.run() method. This launches the embedded
beans and launches the Spring application as separate applications. One can place this code in the
root package. It will help in component scanning and searching for beans in every sub-package.
Optional Parameters:
The @SpringBootApplication annotation accepts the following parameters:
Class<?>[] exclude: Make certain auto-configuration classes irrelevant by excluding them.
String[] scanBasePackages: This parameter is used to search for annotated components using
scanBasePackages.
Optional Features:
The @SpringBootApplication annotation offers aliases to modify the @EnableAutoConfiguration
@Configuration and @ComponentScan's attributes. We can replace the springbootapplication
annotation with any of these annotations, but none of these features is required. For example, you
can use the springbootapplication annotation without the @ComponentScan method.
Here is the code for implementing the springbootapplication annotation without the
@ComponentScan method.
package example;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
@Configuration
@EnableAutoConfiguration
//Not using the @ComponentScan
16 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
@Import({ FirstConfig.class, AnotherConfig.class })
//User-defined annotations are imported explicitly
public class Main{
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
3. What is Autowiring:
Autowiring in the Spring framework can inject dependencies automatically. The Spring
container detects those dependencies specified in the configuration file and the relationship
between the beans. This is referred to as Autowiring in Spring. To enable Autowiring in the
Spring application we should use @Autowired annotation. Autowiring in Spring internally uses
constructor injection. An autowired application requires fewer lines of code comparatively but at
the same time, it provides very little flexibility to the programmer.
Modes of Autowiring:
Modes Description
1. No:
This mode tells the framework that autowiring is not supposed to be done. It is the default mode
used by Spring.
<bean id="state" class="sample.State">
<property name="name" value="UP" />
</bean>
<bean id="city" class="sample.City"></bean>
2. byname:
It uses the name of the bean for injecting dependencies. However, it requires that the name of the
property and bean must be the same. It invokes the setter method internally for autowiring.
<bean id="state" class="sample.State">
<property name="name" value="UP" />
</bean>
<bean id="city" class="sample.City" autowire="byName"></bean>
3. byType:
It injects the dependency according to the type of the bean. It looks up in the configuration file
for the class type of the property. If it finds a bean that matches, it injects the property. If not, the
program throws an error. The names of the property and bean can be different in this case. It
invokes the setter method internally for autowiring.
4. constructor:
It injects the required dependencies by invoking the constructor. It works similar to the “byType”
mode but it looks for the class type of the constructor arguments. If none or more than one bean
are detected, then it throws an error, otherwise, it autowires the “byType” on all constructor
arguments.
18 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
<bean id="state" class="sample.State">
<property name="name" value="UP" />
</bean>
<bean id="city" class="sample.City" autowire="constructor"></bean>
5. autodetect:
The autodetect mode uses two other modes for autowiring – constructor and byType. It first tries
to autowire via the constructor mode and if it fails, it uses the byType mode for autowiring. It
works in Spring 2.0 and 2.5 but is deprecated from Spring 3.0 onwards.
Example of Autowiring:
State.java
Java
City.java
Java
class City {
private int id;
private String name;
private State s;
public int getID() { return id; }
public void setId(int eid) { this.id = eid; }
public String getName() { return name; }
public void setName(String st) { this.name = st; }
public State getState() { return s; }
19 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
XML
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args)
{
SpringApplication.run(DemoApplication.class, args);
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
City cty = context.getBean("city", City.class);
cty.setId(01);
cty.setName("Varanasi");
State st = context.getBean("state", State.class);
st.setName("UP");
20 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
cty.setState(st);
cty.showCityDetails();
}
}
Output:
City ID : 01
City Name : Varanasi
State : UP
4. Scope of a bean:
n Spring, a bean’s scope defines the lifecycle and visibility of the bean instance within the
application context. It determines how long the bean remains in memory and how it is accessed by
different parts of the application. Spring offers several built-in bean scopes, each serving specific
use cases and scenarios.
1. Singleton Scope: One Bean to Rule Them All
The Singleton scope is the default scope for Spring Beans if no explicit scope is defined.
When a bean is defined with the Singleton scope, the Spring IoC container creates and manages
Every time the bean is requested, the same instance is returned, and subsequent requests for the
This means that all parts of the application that use the bean will share the same instance,
Singleton beans are generally used for stateless services and managing shared resources across the
application.
Example:
In this example, we have a Spring Bean named SingletonBeanwith a Singleton scope. This means
that Spring will only create a single instance of this bean for the entire application context.
When we access the SingletonBean using the Spring context, we always get the same instance, and
any changes made to that instance are visible across all the references. In the given code snippet,
the SingletonBean contains a counter that increments each time we call
the getCounter()method.
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
21 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
// Explicitly stating that a particular bean is of type singleton. Two ways to
define the scope.
// @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
// @Scope("Singleton")
@Component
public class SingletonBean {
private int counter = 0;
Output:
22 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
This demonstrates that each time we access the getCounter() method, the same SingletonBean
instance is used, and the counter increments accordingly.
Unlike Singleton, Prototype beans do not maintain a single shared instance; instead, each request for the
This makes Prototype beans ideal for stateful components as each client requesting the bean gets a fresh
instance.
In this example, we have a Spring Bean named PrototypeBeanwith a Prototype scope. This
means that every time we request a bean of this type from the Spring context, a new instance is
created.
When we access the PrototypeBean using the Spring context, we get a new instance of the bean
each time, and any changes made to that instance are isolated to that particular instance only. In the
given code snippet, the PrototypeBean contains a counter that increments each time we call
the getCounter()method.
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
class PrototypeBean {
private int counter = 0;
@SpringBootApplication
public class HelloWorldApplication {
Output:
This demonstrates that each time we access the getCounter() method, a new PrototypeBean
instance is created, and the counter starts from zero for each instance independently.
ApplicationContext.
When a bean is defined with the Request scope, a new instance of the bean is created for each HTTP
request.
This is particularly useful for handling request-specific data, as each user’s request gets its own isolated
Request-scoped beans are thread-safe within the context of a single HTTP request.
Example:
In this example, we have a special bean (RequestBean) that keeps track of the number of times it’s
accessed within a single web request. The REST Controller ( HelloWorldController) uses this
bean to show how the count resets with each new HTTP request, ensuring a fresh count for every
user interaction.
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestBean {
private int counter = 0;
@RestController
public class CounterController {
@Autowired
private RequestBean requestBean;
@GetMapping("/get-counter-value")
public String counterValue() {
25 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
int currentCounterValue = requestBean.getCounter();
System.out.println("Counter value: " + currentCounterValue);
currentCounterValue = requestBean.getCounter();
System.out.println("Counter value post increment: " +
currentCounterValue);
Each time you access the /get-counter-value endpoint, a new instance of RequestBean is
created for that specific request, and the counter increments independently. This demonstrates the
request scope behavior, and the proxy ensures that each request gets its own instance of
the RequestBean.
ApplicationContext.
When a bean is defined with the Session scope, a new instance of the bean is created for each user session.
This ensures that each user interacting with the application gets a separate instance of the bean, maintaining
session-specific data.
Session-scoped beans are useful for managing user-specific information throughout their session.
26 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
The Working Principle
In a web application context, when a user starts a session (e.g., by logging in), Spring creates a
new instance of the bean associated with the Session scope. This bean instance remains available
and shared throughout the entire duration of that user’s session. Once the user’s session ends (e.g.,
by logging out or session timeout), the bean is discarded, and its resources are released
Example:
In this example, we have a Spring Bean named SessionBean, designed with session scope, which
means it retains its state throughout a user’s session. The SessionBean has a counter that
increments each time the getCounter() method is called. We also have a REST Controller
named CounterController, which utilizes the SessionBean. When the endpoint /get-
counter-value is accessed, the CounterController calls the getCounter() method multiple
times. As a result, the counter increments with each call within the same user session, and the
updated value is returned in the response. This session-scoped bean ensures that each user
maintains an independent counter value, allowing separate counting for different users interacting
with the application.
mport org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionBean {
private int counter = 0;
@RestController
public class CounterController {
@Autowired
private SessionBean sessionBean;
@GetMapping("/get-counter-value")
public String counterValue() {
int couterValue = sessionBean.getCounter();
System.out.println("Session Bean Counter: " + couterValue);
couterValue = sessionBean.getCounter();
27 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
System.out.println("Session Bean Counter: " + couterValue);
couterValue = sessionBean.getCounter();
System.out.println("Session Bean Counter: " + couterValue);
With the SessionBean set to session scope, every time a user starts a new session and accesses
the /get-counter-value endpoint, a unique instance of SessionBean is created. The counter
within the SessionBean increments independently for each method call within the same user
session. This demonstrates the session scope behavior, where the same bean instance persists
throughout the user’s session, ensuring separate counting for each user’s interaction with the
application.
ApplicationContext.
When a bean is defined with the Application scope, a single instance of the bean is created for the entire
ServletContext.
This means that the same instance will be shared across all user sessions and requests within the application.
Application-scoped beans are useful for objects that need to maintain state globally across the application.
28 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
The Working Principle
In a web application context, when the application starts, Spring creates a single instance of the
bean associated with the Application scope. This instance remains available throughout the entire
lifecycle of the web application until it is shut down.
Example:
In this example, we use the custom “application” scope for the ApplicationBean. This scope
behaves similar to the singleton scope but persists throughout the entire application’s lifetime.
The CounterController uses the ApplicationBean instance, and the getCounter() method
increments the counter each time it’s called. Since the “application” scope ensures that there’s only
one instance of the bean throughout the application, the counter value will persist across different
HTTP requests, showing the application scope behavior.
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("application")
public class ApplicationBean {
private int counter = 0;
@RestController
public class CounterController {
@Autowired
private ApplicationBean applicationBean;
@GetMapping("/get-counter-value")
public String counterValue() {
int currentValue = applicationBean.getCounter();
System.out.println("Counter value: " + currentValue);
ApplicationContext.
When a bean is defined with the WebSocket scope, a single instance of the bean is created for
This scope is useful for managing WebSocket-specific data for individual clients connected to the
application.
WebSocket-scoped beans are ideal for real-time applications using WebSocket communication.
Example:
Let’s consider a chat application where multiple users can connect via WebSocket to participate in
real-time chat. Each WebSocket session corresponds to a single user, and we want to maintain user-
specific data for each session.
30 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
@Component
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class WebSocketSessionBean {
private WebSocketSession webSocketSession;
private String username;
In this example, we define a WebSocketSessionBean with the WebSocket scope. When a new
WebSocket connection is established, Spring creates a new instance of this bean and associates it
with the WebSocket session. The WebSocketSessionBean can then hold
the WebSocketSession and other user-specific data, such as the username.
With the WebSocket scope, you can manage WebSocket-related state and handle user-specific data
during WebSocket interactions, providing a seamless real-time experience for your web application
users.
Request – New instance per HTTP request – Request-specific data and handlers
Session – Single instance per user session – User-specific data and shopping carts
Application – Single instance per web application – Application-wide settings and constants
5. Logger:
What is Logger In Spring Boot?
A logger is an object that allows us to generate log messages within the application. Loggers are
part of the logging framework provided by Spring Boot and are used to record various events,
activities, and information during the runtime of our application. These log messages provide
information into the behavior of our application, assist in troubleshooting, and help in monitoring
and maintaining the application’s health.
Logger Interface
Spring Boot internally uses the Logger interface from the SLF4J (Simple Logging Facade for Java)
library as the primary abstraction for creating log messages. We need to connect with the logger
interface to generate log messages in our code.
32 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
Logger Initialization
Logger instances are generally initialized at the class level as private static final field. This practice
ensures that the logger is shared across instances of the same class and eliminates the overhead of
logger creation.
Logger Factory
Spring Boot’s logging framework uses a logger factory to create logger instances behind the
scenes. The factory is responsible for determining which logging implementation (e.g., Logback,
Log4j2) to use and instantiates the appropriate logger accordingly.
Logging Levels
Logging levels are used to categorize log messages based on their severity and importance. Each
logging level corresponds to a specific severity level, which helps developers understand the nature
of the logged events. Spring Boot, along with logging frameworks like SLF4J and Logback,
provides a set of standard logging levels that are commonly used to indicate different levels
of severity. These are trace, debug, info, warn, and error. Below is the arrangement of the
levels based on their severity:
Since the TRACE has the lowest sevirity, in this case all levels messages will appear.
Log Formatting
Log messages can include placeholders for variables and parameters. The logger framework
automatically formats the log messages with the provided values, enhancing readability and making
it easier to understand the context of the log entry. However, we can customize the format of the
log messages as per our requirement.
logger.info("Performing an action...");
In this example, the LoggerFactory is used to create an instance of the logger for the
MyService class. The logger is then used to generate log messages with different
logging levels.
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a
given target object. JDK dynamic proxies are built into the JDK, whereas CGLIB is a
common open-source class definition library (repackaged into spring-core).
If the target object to be proxied implements at least one interface, a JDK dynamic
proxy is used. All of the interfaces implemented by the target type are proxied. If the
target object does not implement any interfaces, a CGLIB proxy is created.
JoinPoint
Simply put, a JoinPoint is a point in the execution flow of a method where an Aspect
(new behavior) can be plugged in.
Advice
It’s the behavior that addresses system-wide concerns (logging, security checks,
etc…). This behavior is represented by a method to be executed at a JoinPoint. This
behavior can be executed Before, After, or Around the JoinPoint according to the
Advice type as we will see later.
Pointcut
A Pointcut is an expression that defines at what JoinPoints a given Advice should be
applied.
Aspect
Aspect is a class in which we define Pointcuts and Advices.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.7.4</version>
</dependency>
</dependencies>
Now, let’s create the Log annotation we want to use:
35 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
What this does is create an annotation that is only applicable to methods and gets processed at
runtime.
The next step is creating the Aspect class with a Pointcut and Advice:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LoggingAspect {
@Pointcut("@annotation(Log)")
public void logPointcut(){
}
@Before("logPointcut()")
public void logAllMethodCallsAdvice(){
System.out.println("In Aspect");
}
}
Linking this to the definitions we introduced up top we notice
the @Aspect annotation which marks the LoggingAspect class as a source
for @Pointcut and Advice (@Before). Note as well that we annotated the class as a @Component
to allow Spring to manage this class as a Bean.
Now, let’s create a Spring Service that will use the aspect we defined:
36 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
import org.springframework.stereotype.Service;
@Service
public class ShipmentService {
@Log
// this here is what's called a join point
public void shipStuff(){
System.out.println("In Service");
}
}
And let’s test it out in a @SpringBootTest
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class AopApplicationTests {
@Autowired
ShipmentService shipmentService;
@Test
void testBeforeLog() {
shipmentService.shipStuff();
}
}
This will spin up a Spring context and load the LoggingAspect and
the ShipmentService. Next, in the test method, we call the shipStuff() method which was
annotated by @Log.
In Aspect
In Service
This means that the logAllMethodCallsAdvice method was indeed executed before the shipStuff()
method.
@Component
@Aspect
public class LoggingAspect {
37 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
@Pointcut("@annotation(Log)")
public void logPointcut(){}
@Before("logPointcut()")
public void logAllMethodCallsAdvice(JoinPoint joinPoint){
System.out.println("In Aspect at " + joinPoint.getSignature().getName());
}
}
And testing it
@SpringBootTest
class AopApplicationTests {
@Autowired
ShipmentService shipmentService;
@Test
void testBeforeLog() {
shipmentService.shipStuff();
}
}
Will print out
In Aspect at shipStuff
In Service
@After
This advice is run after the method finishes running, this could be by normally returning or by
throwing an exception.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterLog {}
@Component
@Aspect
public class LoggingAspect {
...
@Pointcut("@annotation(AfterLog)")
public void logAfterPointcut(){}
@After("logAfterPointcut()")
public void logMethodCallsAfterAdvice(JoinPoint joinPoint) {
System.out.println("In After Aspect at " + joinPoint.getSignature().getName());
}
}
And let’s modify our service to use the new annotation
@Service
public class OrderService {
...
38 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
@AfterLog
public void checkStuff() {
System.out.println("Checking stuff");
}
}
And as for the test
@SpringBootTest
class AopApplicationTests {
...
@Test
void testCheckingStuffWithAfter() {
orderService.checkStuff();
}
}
Checking stuff
In After Aspect at checkStuff
@AfterReturning
This is similar to @After but it’s run only after a normal execution of the method.
@AfterThrowing
This is similar to @After but it’s run only after an exception is thrown while executing the
method.
@Around
This annotation allows us to take actions either before or after a JoinPoint method is run. We can
use it to return a custom value or throw an exception or simply let the method run and return
normally.
@Service
public class ValidationService {
public void validateNumber(int argument) {
System.out.println(argument + " is valid");
}
}
And a new Aspect class
@Component
@Aspect
39 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
public class ValidationAspect {
@Pointcut("within(io.reflectoring.springboot.aop.ValidationService)")
public void validationPointcut(){}
@Around("validationPointcut()")
public void aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("In Around Aspect");
int arg = (int) joinPoint.getArgs()[0];
if (arg < 0)
throw new RuntimeException("Argument should not be negative");
else
joinPoint.proceed();
}
}
The above Pointcut expression will capture all methods that are in the class
ValidationService. Then, the aroundAdvice() advice will check the first
argument of the method if it’s negative it will throw an exception, otherwise it will allow the
method to execute and return normally.
@SpringBootTest
class AopApplicationTests {
...
@Autowired
ValidationService validationService;
@Test
void testValidAroundAspect() {
validationService.validateNumber(10);
}
}
In Around Aspect
10 is valid
@SpringBootTest
class AopApplicationTests {
...
@Autowired
ValidationService validationService;
...
@Test
void testInvalidAroundAspect() {
validationService.validateNumber(-4);
}
}
In Around Aspect
Here, I will show you recommended ways to create a spring boot project structure in Spring boot
applications, which will help beginners to maintain standard coding structure.
Separate package for each layer like a model, controller, dao and service etc.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
It is always a good practice to divide a large Spring-based configuration file into multiple files as
per your convenience. I generally keep Database configuration in one file (DatabaseConfig), Spring
43 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
MVC beans in another file, etc, and then finally import in the main file.
You need not put all your @Configuration into a single class. The @Import annotation can be
used to import additional configuration classes.
For example:
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(...);
}
}
@Configuration
@AnnotationDrivenConfig
@Import(DataSourceConfig.class) // <-- AppConfig imports DataSourceConfig
public class AppConfig extends ConfigurationSupport {
@Autowired DataSourceConfig dataSourceConfig;
@Bean
public void TransferService transferService() {
return new TransferServiceImpl(dataSourceConfig.dataSource());
}
}
@Configuration
@Import({ DataSourceConfig.class, TransactionConfig.class })
public class AppConfig extends ConfigurationSupport {
// @Bean methods here can reference @Bean methods in DataSourceConfig or
TransactionConfig
}
3. Using Auto-configuration
Spring Boot auto-configuration attempts to automatically configure your Spring application based
on the jar dependencies that you have added.
The simplest way to make use of it is to rely on the Spring Boot Starters. So, if you want to interact
44 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
with Redis, you can start by including:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
and so on… By relying on these starters, you are relying on a tested and proven configuration that
is going to work well together.
It is possible to exclude some classes from the Auto-configuration, by using the following
annotation
property: @EnableAutoConfiguration(exclude={ClassNotToAutoconfigure.class}), but
you should do it only if absolutely necessary.
There are many ways to create a Spring Boot application. The simplest way is to use Spring
Initializr at http://start.spring.io/, which is an online Spring Boot application generator.
45 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
5. When to Use Constructor-based and setter-based DI in Spring or Spring boot
applications
From spring Framework documentation, since you can mix constructor-based and setter-
based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter
methods or configuration methods for optional dependencies.
As I can see many developers prefer to use constructor injection over setter based injection
because this makes bean class object as immutable(We cannot change the value by Constructor
injection).
@Service
@Transactional
public class ProductService {
private final ProductRepository productRepository;
This way it will be easier to instantiate ProductService with necessary dependencies for testing if
required.
I observed in many of the spring boot open-source applications, the Spring Data JPA repositories
directly called in Controller classes in Spring boot applications. I generally use Service class
annotated with a @Service annotation to write business-related logic so you can follow this
approach.
For example, UserService, CustomerService, EmployeeService etc.
I listed a few free spring boot projects here at 10+ Free Open Source Projects Using Spring
Boot article.
Reference: https://docs.spring.io/spring/docs/current/spring-framework-
47 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
reference/core.html#beans-definition
public class A {
public A(B b){
....
}
}
public class B {
public B(A b){
....
}
}
One possible solution is to edit the source code of some classes to be configured by setters rather
than constructors. Alternatively, avoid constructor injection and use setter injection only. In other
words, although it is not recommended, you can configure circular dependencies with setter
injection.
Handle proper exceptions and custom error messages for RESTful Web Services developed using
Spring Boot.
Check out this article - Spring Boot 2 Exception Handling for REST APIs.
10. Follow Restful API Design Best Practices in Spring Boot Rest API Applications
I have written a separate article of Restful API design best practices. Here is a list of best practices
to design a clean RESTful API.
48 SIR C R REDDY COLLEGE OF ENGINEERING, ELURU
API & MICROSERVICES Unit-1 Dept. of CSE, JSVG KRISHNA
API & MICROSERVICES