- What is Spring and Spring Boot?
- Difference between Spring and Spring Boot?
2) Spring is popular for dependency injection, whereas Spring Boot is popular for auto-configuration.
3) Spring framework requires developers to setup the web server manually. Spring Boot has built-in servers like Tomcat, Jetty & Undertow.
4) Spring framework requires a deployment descriptor (web.xml) to run an application. Spring Boot doesn’t require a deployment descriptor to run an application.
5) Spring requires many manual configurations, whereas Spring Boot promotes auto-configuration.
6) Spring Framework requires a number of dependencies to create a web app. Spring Boot requires only one dependency to work on web app which is ‘spring-boot-starter-web’.
7) Spring framework requires XML Configurations, whereas Spring Boot doesn’t require XML configuration.
8) Spring Boot provides CLI (Command Line Interface) tool to develop & test the application, whereas Spring framework doesn’t provide such kind of tool.
9) Spring framework requires manually defining dependencies for the Spring project in the pom.xml. Spring Boot offers the concept of starter in pom.xml file that internally takes care of downloading the dependent JARs automatically.
10) Spring Boot offers production-ready features such as metrics, health check and other reports. Spring does not offer such kind of features.
11) Spring framework doesn’t support in-memory databases. Spring Boot includes support for in-memory databases like H2
- What is Dependency Injection?
Dependency Injection (DI) is a design pattern and core principle in the Spring framework that deals with how components or beans in an application acquire their dependencies. Instead of the components themselves creating instances of their dependencies, the responsibility of injecting the dependencies is handed over to an external entity, typically the IoC (Inversion of Control) container, such as the Spring framework. This leads to more decoupled and maintainable code.
Key Concepts of Dependency Injection
Inversion of Control (IoC):
- IoC is the principle where the control of object creation and dependency management is inverted from the components to a container or framework.
- DI is a specific form of IoC where dependencies are injected by the container.
Types of Dependency Injection:
- Constructor Injection: Dependencies are provided through a class constructor.
- Setter Injection: Dependencies are provided through setter methods.
- Field Injection: Dependencies are injected directly into fields using annotations.
Benefits of Dependency Injection
- Decoupling: Components are decoupled from their dependencies, making the code more modular and easier to test.
- Maintainability: Easier to change implementations or configurations without altering the dependent components.
- Testability: Simplifies unit testing by allowing dependencies to be mocked or stubbed easily.
Types of Dependency Injection in Spring
1. Constructor Injection
Example:
javapublic class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.doSomething();
}
}
In this example, MyService
declares a constructor that requires a MyRepository
instance. Spring automatically injects the appropriate MyRepository
bean when MyService
is instantiated.
2. Setter Injection
Example:
javapublic class MyService {
private MyRepository myRepository;
@Autowired
public void setMyRepository(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.doSomething();
}
}
Here, MyService
declares a setter method for MyRepository
. Spring injects the dependency by calling this setter method.
3. Field Injection
Example:
javapublic class MyService {
@Autowired
private MyRepository myRepository;
public void performService() {
myRepository.doSomething();
}
}
In this example, MyRepository
is injected directly into the field myRepository
of MyService
.
Configuring Dependency Injection
Using Annotations
- @Component: Indicates that a class is a Spring component.
- @Autowired: Marks a constructor, field, or setter method to be autowired by Spring’s dependency injection facilities.
- @Service, @Repository, @Controller: Specializations of
@Component
used for specific types of components. - @Qualifier: Used to resolve ambiguity when multiple beans of the same type are present.
Example with Annotations:
java@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(@Qualifier("specificRepository") MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.doSomething();
}
}
@Repository
@Qualifier("specificRepository")
public class MyRepositoryImpl implements MyRepository {
// Implementation details
}
Using XML Configuration
Example:
xml<beans>
<bean id="myRepository" class="com.example.MyRepositoryImpl"/>
<bean id="myService" class="com.example.MyService">
<constructor-arg ref="myRepository"/>
</bean>
</beans>
In this XML configuration, myService
is configured to have myRepository
injected via its constructor.
Conclusion
Dependency Injection is a fundamental concept in Spring that enables loose coupling and enhances the testability and maintainability of an application. By delegating the responsibility of dependency management to the Spring container, components remain focused on their primary responsibilities without worrying about the creation and management of their dependencies.
- What is Inversion of Control?
Inversion of Control (IoC) is a design principle in software engineering where the control flow of a program is inverted compared to traditional procedural programming. In IoC, the control over the flow of a program is shifted from the program itself to an external framework or container. This principle is closely related to, and often used synonymously with, the Dependency Injection (DI) pattern.
Key Concepts of Inversion of Control (IoC)
Control Flow:
- In traditional programming, a program controls the flow of execution.
- In IoC, the control flow is inverted, and the framework or container controls the flow.
Dependency Injection (DI):
- DI is a specific form of IoC where dependencies are injected into a class by an external entity (typically a framework or container).
Decoupling:
- IoC helps in decoupling the components of an application, making the code more modular and easier to maintain.
Benefits of Inversion of Control (IoC)
- Modularity: Promotes modularity by decoupling components, making them easier to test and maintain.
- Extensibility: Allows for easier extension of functionality by adding or replacing components.
- Testability: Enhances testability by facilitating the use of mock objects for testing.
- Reusability: Encourages the reuse of components in different parts of an application or in different applications.
Implementing Inversion of Control (IoC) in Spring
In Spring, IoC is implemented through the use of the Spring IoC container. The container is responsible for managing the lifecycle of objects, including creating, configuring, and assembling them. It achieves this by:
- Component Scanning: Automatically detecting classes annotated with
@Component
(or its specializations) and registering them as beans. - XML Configuration: Defining beans and their dependencies in an XML configuration file.
- Java Configuration: Using Java classes annotated with
@Configuration
to define beans and their dependencies. - Annotation-based Configuration: Using annotations like
@Autowired
,@Component
,@Service
,@Repository
, and@Controller
for dependency injection and bean management.
Example of Dependency Injection (DI) in Spring
Consider a simple example where a UserService
class depends on a UserRepository
interface:
javapublic interface UserRepository {
void save(User user);
}
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void saveUser(User user) {
userRepository.save(user);
}
}
In this example, the UserService
class declares a constructor that accepts a UserRepository
parameter. When an instance of UserService
is created, Spring automatically injects a bean that implements the UserRepository
interface.
Conclusion
Inversion of Control (IoC) is a fundamental concept in modern software development and plays a crucial role in the Spring framework. By inverting the control of object creation and management to the framework, IoC promotes decoupling, modularity, and testability, making applications more maintainable and extensible.
- Inversion of Control vs Dependency Injection?
Inversion of Control (IoC) and Dependency Injection (DI) are related concepts in software engineering, often used together to achieve loose coupling and improve the testability and maintainability of code. While they are closely related, they refer to slightly different aspects of the same principle.
Inversion of Control (IoC)
Definition: IoC is a design principle in which the control flow of a program is inverted compared to traditional programming. In IoC, the control over the flow of a program is shifted from the program itself to an external framework or container.
Key Points:
- IoC is a broad concept that encompasses various design patterns and principles, including DI.
- It emphasizes decoupling components by delegating control over their dependencies to an external entity (e.g., a framework).
Example:
- In a traditional application, a class may create instances of its dependencies directly. In an IoC scenario, these dependencies are provided to the class (injected) by an external entity.
Dependency Injection (DI)
Definition: DI is a specific form of IoC where dependencies are injected into a class by an external entity (typically a framework or container) rather than the class itself creating or managing its dependencies.
Key Points:
- DI is a pattern or mechanism used to achieve IoC.
- It helps in achieving loose coupling between classes, as the class does not need to know how to create its dependencies but relies on an external entity to provide them.
Example:
- In the context of a Spring application, DI is achieved using annotations like
@Autowired
to inject dependencies into a class.
- In the context of a Spring application, DI is achieved using annotations like
Relationship Between IoC and DI
- IoC is a broader concept that encompasses the idea of inverting control, while DI is a specific technique used to implement IoC.
- DI is a way to achieve IoC by externalizing the dependencies of a class and injecting them rather than having the class create or manage its dependencies.
Summary
- Inversion of Control (IoC): A design principle where control over the flow of a program is inverted, with an external entity controlling the creation and management of objects.
- Dependency Injection (DI): A specific implementation of IoC where dependencies of a class are injected into the class by an external entity, rather than the class creating or managing its dependencies.
In practice, the terms IoC and DI are often used interchangeably, as DI is the most common way to achieve IoC in modern software development.
- What happen when we start spring boot application?
When you start a Spring Boot application, several key steps are taken behind the scenes to initialize the application and make it ready to handle incoming requests. Here's an overview of what happens:
Initialization:
- Spring Boot initializes by creating an instance of the
ApplicationContext
. This context is the central interface within a Spring application for providing configuration information to the application.
- Spring Boot initializes by creating an instance of the
Component Scanning:
- Spring Boot scans the application's components (classes annotated with
@Component
,@Service
,@Repository
,@Controller
, etc.) to identify beans and register them in the application context.
- Spring Boot scans the application's components (classes annotated with
Auto-Configuration:
- Spring Boot automatically configures the application based on the dependencies and classpath.
- It looks for libraries in the classpath and configures beans and other settings accordingly.
Application Context Setup:
- Spring Boot sets up the application context with all the necessary configurations, including beans, property sources, and environment settings.
Embedded Web Server Start:
- If the application is a web application, Spring Boot starts an embedded web server (like Tomcat, Jetty, or Undertow) to handle incoming HTTP requests.
Running the Application:
- Once the setup is complete, Spring Boot starts the application, making it ready to handle requests.
- Any
@PostConstruct
methods are invoked, and the application is in a fully initialized state.
Handling Requests:
- The application is now ready to handle incoming requests based on the defined mappings (e.g.,
@RequestMapping
,@GetMapping
,@PostMapping
).
- The application is now ready to handle incoming requests based on the defined mappings (e.g.,
Shutdown:
- When the application is shut down, any
@PreDestroy
methods are invoked, and resources are released.
- When the application is shut down, any
Overall, Spring Boot's auto-configuration and opinionated setup make it easy to create standalone, production-ready Spring applications with minimal manual configuration.
- What is Bean ? Explain about Bean LifeCycle? Explain about different types of Bean?
In Spring Framework, a bean is an object that is instantiated, assembled, and managed by the Spring IoC container. Beans are the basic building blocks of a Spring application and are typically Java objects that form the backbone of the application's business logic.
Bean Lifecycle in Spring
The lifecycle of a Spring bean consists of several phases, each with its corresponding callback methods that you can implement to perform custom initialization and destruction logic. The typical bean lifecycle phases are as follows:
Instantiation:
- The container instantiates a bean using either a constructor (for XML-based configuration) or a static factory method (for Java-based configuration).
Populating properties:
- The container populates the bean's properties, either by setting values directly on the bean's fields or by calling setter methods.
BeanNameAware and BeanFactoryAware (Optional):
- If the bean implements the
BeanNameAware
orBeanFactoryAware
interfaces, the corresponding methods are called, passing the bean's name and the containing BeanFactory.
- If the bean implements the
BeanPostProcessor PreInitialization:
- If any
BeanPostProcessor
implementations are registered with the container, theirpostProcessBeforeInitialization
methods are called.
- If any
Initialization:
- If the bean implements the
InitializingBean
interface, theafterPropertiesSet
method is called. - If the bean has an initialization method defined (e.g.,
init-method
attribute in XML configuration or@PostConstruct
annotation), that method is called.
- If the bean implements the
BeanPostProcessor PostInitialization:
- If any
BeanPostProcessor
implementations are registered with the container, theirpostProcessAfterInitialization
methods are called.
- If any
Bean Ready for Use:
- The bean is now fully initialized and ready to be used by the application.
Destruction:
- If the bean implements the
DisposableBean
interface, thedestroy
method is called when the bean is being removed from the container. - If the bean has a destruction method defined (e.g.,
destroy-method
attribute in XML configuration or@PreDestroy
annotation), that method is called.
- If the bean implements the
Types of Beans in Spring
Singleton:
- By default, beans in Spring are singletons, meaning that only one instance of the bean is created for the entire application context.
- Singleton beans are cached, and subsequent requests for the bean return the cached instance.
Prototype:
- Prototype beans are not cached, and a new instance is created every time the bean is requested from the container.
- This can be useful for beans that are stateful or require a new instance for each use.
Request:
- Request-scoped beans are created once per HTTP request in a web application.
- Each HTTP request gets its instance of the bean, which is destroyed once the request is completed.
Session:
- Session-scoped beans are created once per HTTP session in a web application.
- Each HTTP session gets its instance of the bean, which is destroyed when the session expires.
Global Session:
- Global session-scoped beans are similar to session-scoped beans but are scoped to a global HTTP session in a portlet context.
Application Context:
- Application context-scoped beans are scoped to the lifecycle of the entire application context.
- They are created once per application context and are typically used in a multi-context scenario.
Custom Scope:
- Spring allows you to define custom bean scopes by implementing the
Scope
interface and registering it with the application context.
- Spring allows you to define custom bean scopes by implementing the
Summary
- A bean in Spring is an object managed by the Spring IoC container.
- The bean lifecycle consists of instantiation, initialization, and destruction phases, with corresponding callback methods for customization.
- Spring supports different types of bean scopes, including singleton, prototype, request, session, global session, and application context.
- How to change port number in spring boot application?
You can change the port number of a Spring Boot application by configuring it in the application.properties
or application.yml
file. Here's how you can do it:
Using application.properties
- Open the
src/main/resources/application.properties
file. - Add or update the following line to specify the desired port number:
Replacepropertiesserver.port=8081
8081
with the port number you want to use.
Using application.yml
- Open the
src/main/resources/application.yml
file. - Add or update the following lines to specify the desired port number:
Replaceyamlserver: port: 8081
8081
with the port number you want to use.
Run the Application
Once you've configured the port number, you can run your Spring Boot application. It will now listen on the specified port.
Command Line Argument
Alternatively, you can also specify the port number as a command-line argument when running your Spring Boot application. For example:
shjava -jar -Dserver.port=8081 your-application.jar
This will override any port configuration in your application.properties
or application.yml
file and use port 8081
.
- Which server spring boot uses internally? How to change that?
- How to implement paging and sorting in Spring Boot?
Paging and sorting in Spring Boot can be easily implemented using Spring Data JPA. Spring Data JPA provides built-in support for pagination and sorting, making it straightforward to handle these features in your application. Here’s how you can implement paging and sorting in a Spring Boot application:
Step-by-Step Implementation
1. Set Up Spring Data JPA
Ensure you have the necessary dependencies for Spring Data JPA in your pom.xml
(for Maven) or build.gradle
(for Gradle).
Maven:
xml<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Gradle:
groovyimplementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.h2database:h2'
2. Define an Entity
Create an entity class that represents the data model.
javaimport javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// Getters and setters
}
3. Create a Repository Interface
Create a repository interface that extends PagingAndSortingRepository
or JpaRepository
. These interfaces provide methods for pagination and sorting.
javaimport org.springframework.data.repository.PagingAndSortingRepository;
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}
4. Use Paging and Sorting in a Service
Create a service class to use the repository methods for pagination and sorting.
javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Page<User> getUsers(int page, int size, String sortBy) {
Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
return userRepository.findAll(pageable);
}
}
5. Create a Controller
Create a controller to handle HTTP requests and return paginated and sorted results.
javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sortBy) {
return userService.getUsers(page, size, sortBy);
}
}
Explanation
- Entity: The
User
class is a JPA entity that maps to a database table. - Repository: The
UserRepository
interface extendsPagingAndSortingRepository
, which provides methods for pagination and sorting. - Service: The
UserService
class contains the business logic for fetching paginated and sorted users. - Controller: The
UserController
class handles HTTP GET requests to the/users
endpoint and returns paginated and sorted user data.
Running the Application
Once you have implemented the above steps, you can run your Spring Boot application. You can access the paginated and sorted users by making HTTP GET requests to the /users
endpoint with query parameters for page
, size
, and sortBy
.
For example:
bashGET http://localhost:8080/users?page=0&size=10&sortBy=name
This request will return the first page of users, with 10 users per page, sorted by the name
field.
- What is @SpringBootApplication?
@SpringBootApplication
annotation is a convenience annotation that combines several other annotations commonly used in Spring Boot applications. It is typically placed on the main class of a Spring Boot application to enable various configurations and settings that are needed to run the application.The @SpringBootApplication
annotation is effectively a combination of the following three annotations:
@EnableAutoConfiguration:
- This annotation tells Spring Boot to start adding beans based on the classpath settings, other beans, and various property settings. For example, if
spring-boot-starter-web
is on the classpath, this annotation flags the application as a web application and activates key behaviors, such as setting up aDispatcherServlet
.
- This annotation tells Spring Boot to start adding beans based on the classpath settings, other beans, and various property settings. For example, if
@ComponentScan:
- This annotation tells Spring to scan the current package and its sub-packages for components, configurations, and services. This allows Spring to find and register beans annotated with
@Component
,@Service
,@Repository
, etc.
- This annotation tells Spring to scan the current package and its sub-packages for components, configurations, and services. This allows Spring to find and register beans annotated with
@Configuration:
- This annotation indicates that the class can be used by the Spring IoC container as a source of bean definitions. It allows the class to declare one or more
@Bean
methods that provide the beans to the Spring container.
- This annotation indicates that the class can be used by the Spring IoC container as a source of bean definitions. It allows the class to declare one or more
Here is an example of how @SpringBootApplication
is typically used in a Spring Boot application:
javaimport org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
}
Key Benefits
- Convenience: By using
@SpringBootApplication
, you can avoid specifying each annotation (@EnableAutoConfiguration
,@ComponentScan
, and@Configuration
) separately. This makes your main class cleaner and more readable. - Auto-Configuration: It enables the auto-configuration feature of Spring Boot, which attempts to automatically configure your Spring application based on the dependencies you have added.
- Component Scanning: It simplifies component scanning, ensuring that Spring can find your beans and configurations without needing additional setup.
Customizing the Behavior
If you need to customize the behavior of the auto-configuration or component scanning, you can still use the individual annotations. For example, if you want to specify a different base package for component scanning, you can explicitly add @ComponentScan
with the desired package:
javaimport org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = "com.example.myapp")
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApplication.class, args);
}
}
In summary, @SpringBootApplication
is a powerful and convenient annotation that simplifies the setup and configuration of Spring Boot applications by combining three essential annotations into one.
- Explain about different annotations like @Service, @Controller, @RestController, @Entity, @Component, @Repository, @Autowired, @Required, @Primary, @Async, @Transient, @ComponentScan?
1. @Service
- Purpose: Indicates that a class is a service component in the service layer.
- Usage: Used to annotate service classes, which typically contain business logic.
- Example:java
@Service public class MyService { public void performService() { // business logic } }
2. @Controller
- Purpose: Indicates that a class is a Spring MVC controller, handling HTTP requests.
- Usage: Used to annotate controller classes that handle web requests.
- Example:java
@Controller public class MyController { @GetMapping("/greet") public String greet() { return "greeting"; } }
3. @RestController
- Purpose: A convenience annotation that combines
@Controller
and@ResponseBody
. - Usage: Used to create RESTful web services where methods return JSON/XML responses.
- Example:java
@RestController public class MyRestController { @GetMapping("/hello") public String hello() { return "Hello, World!"; } }
4. @Entity
- Purpose: Specifies that a class is an entity and is mapped to a database table.
- Usage: Used to annotate model classes in JPA (Java Persistence API).
- Example:java
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // getters and setters }
5. @Component
- Purpose: Indicates that a class is a Spring component.
- Usage: Used to define Spring-managed beans.
- Example:java
@Component public class MyComponent { public void doWork() { // logic } }
6. @Repository
- Purpose: Indicates that a class is a repository, which encapsulates database operations.
- Usage: Used to annotate DAO (Data Access Object) classes.
- Example:java
@Repository public class UserRepository { // database access methods }
7. @Autowired
- Purpose: Marks a field, constructor, or setter method for dependency injection.
- Usage: Used to automatically wire beans.
- Example:java
@Service public class MyService { @Autowired private MyRepository myRepository; // service methods }
8. @Required
- Purpose: Indicates that a bean property must be set.
- Usage: Applied to setter methods to enforce that the property is required.
- Example:java
public class MyBean { private String name; @Required public void setName(String name) { this.name = name; } }
9. @Primary
- Purpose: Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency.
- Usage: Used to resolve autowiring conflicts.
- Example:java
@Primary @Bean public MyService primaryService() { return new PrimaryService(); }
10. @Async
- Purpose: Marks a method for asynchronous execution.
- Usage: Used to execute methods asynchronously.
- Example:java
@Service public class MyService { @Async public void asyncMethod() { // asynchronous logic } }
11. @Transient
- Purpose: Indicates that a field is not persistent.
- Usage: Used in JPA entities to specify that the field should not be stored in the database.
- Example:java
@Entity public class User { private String name; @Transient private int age; // not persisted // getters and setters }
12. @ComponentScan
- Purpose: Configures the packages to be scanned for components.
- Usage: Used in configuration classes to specify the base packages for scanning components.
- Example:java
@Configuration @ComponentScan(basePackages = "com.example") public class AppConfig { // configuration }
- Difference between @Controller vs @RestController? The primary difference between
@Controller
and@RestController
lies in the way they handle HTTP responses in a Spring MVC application. @Controller
- Purpose:
@Controller
is used to define a controller in a Spring MVC application. - Response Handling: When a method in a class annotated with
@Controller
returns a value, it is typically interpreted as the name of a view (like a JSP, Thymeleaf template, etc.) that should be rendered. - Usage:
@Controller
is generally used when you want to return HTML views in response to web requests.
Example:
java@Controller public class MyController { @GetMapping("/greet") public String greet(Model model) { model.addAttribute("message", "Hello, World!"); return "greeting"; // Returns the name of the view } }
In the example above, the method
greet
adds an attribute to the model and returns the name of the view (e.g., a Thymeleaf template namedgreeting.html
).@RestController
- Purpose:
@RestController
is a specialized version of@Controller
that is used to create RESTful web services. - Response Handling: When a method in a class annotated with
@RestController
returns a value, it is directly written to the HTTP response body as JSON or XML (depending on the configured message converters).@RestController
is a convenience annotation that combines@Controller
and@ResponseBody
. - Usage:
@RestController
is used when you want to return JSON or XML data directly from your controller methods.
Example:
java@RestController public class MyRestController { @GetMapping("/hello") public String hello() { return "Hello, World!"; // Directly written to the HTTP response body } }
In the example above, the method
hello
returns a string which is directly written to the HTTP response body as plain text (or JSON/XML if it were an object).Key Differences:
Annotation Combination:
@Controller
is often used with@ResponseBody
to return data as a response body.@RestController
combines@Controller
and@ResponseBody
, making it more convenient for RESTful web services.
Response Handling:
@Controller
returns the name of a view which is resolved to an HTML page.@RestController
returns data directly, which is written to the HTTP response body.
Use Case:
- Use
@Controller
when you are developing a web application with views (e.g., HTML pages). - Use
@RestController
when you are developing a REST API that returns data (e.g., JSON or XML).
- Use
Example of Using @Controller with @ResponseBody:
java@Controller public class MyController { @GetMapping("/json") @ResponseBody public String json() { return "{\"message\": \"Hello, World!\"}"; // JSON response } }
Here,
@ResponseBody
is used to indicate that the return value should be written directly to the response body, similar to how@RestController
works.- Purpose:
- What is use of @Configuration?
The @Configuration
annotation in Spring is used to indicate that a class declares one or more @Bean
methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime. It is a key part of the Java-based configuration in Spring.
Key Uses of @Configuration
Bean Definitions:
- It allows you to define beans using Java code rather than XML.
- Beans are methods annotated with
@Bean
within a class annotated with@Configuration
.
Dependency Injection:
- Enables dependency injection by defining beans and their dependencies programmatically.
Component Scanning and Bootstrapping:
- Used in combination with
@ComponentScan
to specify the packages to be scanned for components. - Often combined with
@EnableAutoConfiguration
and@ComponentScan
in Spring Boot applications.
- Used in combination with
Modularity:
- Allows for the configuration to be modularized into multiple classes, each with its own configuration.
Example Usage
Simple Bean Definition
java@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
@Bean
public MyRepository myRepository() {
return new MyRepositoryImpl();
}
}
In the example above, AppConfig
is a configuration class that defines two beans, myService
and myRepository
.
Using @Configuration with @ComponentScan
java@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// configuration and bean definitions
}
Here, @ComponentScan
is used to specify the base packages to scan for components, combining component scanning with explicit bean definitions.
Using @Configuration with @PropertySource
java@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("db.driver"));
dataSource.setUrl(env.getProperty("db.url"));
dataSource.setUsername(env.getProperty("db.username"));
dataSource.setPassword(env.getProperty("db.password"));
return dataSource;
}
}
In this example, @PropertySource
is used to load properties from an external file, and the Environment
is used to access those properties to configure a DataSource
bean.
Benefits of Using @Configuration
Type-Safe Configuration:
- Provides type-safe configuration compared to XML, which can lead to fewer errors.
IDE Support:
- Better support for refactoring and navigation in modern IDEs.
Modularity:
- Encourages modular configuration, allowing different configurations for different parts of the application.
Testability:
- Configuration classes can be easily tested with standard unit tests.
Integration:
- Easily integrates with other parts of Spring such as component scanning and Spring Boot’s auto-configuration.
In summary, @Configuration
is a cornerstone of Java-based Spring configuration, offering a powerful and flexible way to define and manage beans within the Spring container.
- What does autowiring mean? Types of autowiring?
Autowiring in Spring refers to the process of automatically injecting dependencies into a Spring-managed bean. Instead of explicitly wiring the dependencies using XML configuration or Java code, Spring can automatically resolve and inject the collaborating beans.
Types of Autowiring
Spring supports several types of autowiring. Here’s a detailed look at each:
1. Autowiring by Type (@Autowired
)
Field Injection:
javapublic class MyService {
@Autowired
private MyRepository myRepository;
}
Constructor Injection:
javapublic class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
}
Setter Injection:
javapublic class MyService {
private MyRepository myRepository;
@Autowired
public void setMyRepository(MyRepository myRepository) {
this.myRepository = myRepository;
}
}
Explanation: When @Autowired
is used on a field, constructor, or setter method, Spring will automatically inject the appropriate bean by matching the type.
2. Autowiring by Name
javapublic class MyService {
@Autowired
@Qualifier("myRepository")
private MyRepository myRepository;
}
Explanation: When @Qualifier
is used in conjunction with @Autowired
, Spring will resolve the bean by matching the bean name.
3. Autowiring by Qualifier (@Qualifier
)
Field Injection:
javapublic class MyService {
@Autowired
@Qualifier("specificRepository")
private MyRepository myRepository;
}
Constructor Injection:
javapublic class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(@Qualifier("specificRepository") MyRepository myRepository) {
this.myRepository = myRepository;
}
}
Setter Injection:
javapublic class MyService {
private MyRepository myRepository;
@Autowired
public void setMyRepository(@Qualifier("specificRepository") MyRepository myRepository) {
this.myRepository = myRepository;
}
}
Explanation: @Qualifier
is used to specify the exact bean to be injected when there are multiple beans of the same type.
Autowiring Modes in XML Configuration
no (default) - No autowiring. Dependencies must be specified manually.
xml<bean id="myService" class="com.example.MyService"> <property name="myRepository" ref="myRepository"/> </bean>
byName - Autowires by property name. Spring looks for a bean with the same name as the property.
xml<bean id="myService" class="com.example.MyService" autowire="byName"/>
byType - Autowires by property type. Spring looks for a bean with a matching type.
xml<bean id="myService" class="com.example.MyService" autowire="byType"/>
constructor - Autowires by constructor. Similar to
byType
, but applies to constructor arguments.xml<bean id="myService" class="com.example.MyService" autowire="constructor"/>
autodetect - Deprecated. Uses constructor or byType autowiring, depending on which is applicable.
xml<bean id="myService" class="com.example.MyService" autowire="autodetect"/>
Advantages of Autowiring
- Reduces Boilerplate Code: Simplifies the wiring of beans and reduces the amount of configuration needed.
- Increases Flexibility: Makes it easier to swap implementations or change configurations without altering the code.
Disadvantages of Autowiring
- Ambiguity: Can lead to ambiguous dependencies if there are multiple candidates for injection.
- Hidden Dependencies: Makes it harder to understand the dependencies of a class at a glance, as they are not explicitly defined in the configuration.
Example: Complete Autowiring in a Spring Boot Application
Application Configuration:
java@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Service Class:
java@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
myRepository.doSomething();
}
}
Repository Interface:
java@Repository
public interface MyRepository {
void doSomething();
}
In this example, MyService
is automatically injected with an instance of MyRepository
by Spring.
In summary, autowiring in Spring simplifies dependency injection, making the code cleaner and easier to manage. However, careful consideration is needed to avoid issues with ambiguity and hidden dependencies.
- What is ApplicationContext?
ApplicationContext
is a central interface in the Spring Framework that provides configuration information to the application. It represents the Spring IoC (Inversion of Control) container and is responsible for instantiating, configuring, and assembling the beans.
Key Features of ApplicationContext
Bean Factory:
ApplicationContext
extends theBeanFactory
interface, providing all the functionality of aBeanFactory
(which is responsible for managing the lifecycle of beans).
Internationalization (i18n):
- Supports internationalization by providing message resources for different locales.
Event Propagation:
- Supports event handling and propagation, allowing beans to publish and listen for events.
Resource Loading:
- Provides a generic way to load resources (like files, URLs, etc.).
Environment Abstraction:
- Provides access to environment variables and properties, enabling the application to adapt to different environments.
Lifecycle Management:
- Manages the lifecycle of beans, including initialization, destruction, and other lifecycle callbacks.
Example Usage
Creating an ApplicationContext
Using ClassPathXmlApplicationContext (for XML-based configuration):
javaApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyService myService = context.getBean(MyService.class);
myService.performService();
Using AnnotationConfigApplicationContext (for Java-based configuration):
java@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
@Bean
public MyRepository myRepository() {
return new MyRepositoryImpl();
}
}
public class Application {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = context.getBean(MyService.class);
myService.performService();
}
}
Important Methods in ApplicationContext
getBean():
- Retrieves a bean from the Spring container.
javaMyService myService = context.getBean(MyService.class);
getBeansOfType():
- Retrieves all beans of a specified type.
javaMap<String, MyService> services = context.getBeansOfType(MyService.class);
getBeanNamesForType():
- Retrieves the names of all beans of a specified type.
javaString[] beanNames = context.getBeanNamesForType(MyService.class);
getMessage():
- Retrieves a message from the message source for internationalization.
javaString message = context.getMessage("welcome.message", null, Locale.US);
publishEvent():
- Publishes an event to be handled by event listeners.
javacontext.publishEvent(new MyCustomEvent(this, "event data"));
Types of ApplicationContext
ClassPathXmlApplicationContext:
- Loads context definition from an XML file located in the classpath.
javaApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
FileSystemXmlApplicationContext:
- Loads context definition from an XML file located in the file system.
javaApplicationContext context = new FileSystemXmlApplicationContext("path/to/applicationContext.xml");
AnnotationConfigApplicationContext:
- Loads context definition from Java-based configuration classes.
javaApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
GenericWebApplicationContext:
- Suitable for web applications, providing integration with Servlet context.
Benefits of ApplicationContext
- Advanced Dependency Injection: Supports setter-based, constructor-based, and field-based dependency injection.
- Bean Lifecycle Management: Manages the complete lifecycle of beans, including initialization and destruction callbacks.
- Integration with Spring AOP: Supports Aspect-Oriented Programming, enabling the application of cross-cutting concerns.
- Enterprise Services: Provides enterprise-level services such as transaction management, security, and more.
Conclusion
ApplicationContext
is a powerful and flexible interface in the Spring Framework that provides comprehensive support for dependency injection, bean lifecycle management, and many other enterprise-level features. It is a fundamental part of any Spring application, ensuring that the application components are configured, managed, and assembled correctly.
- Difference between @Bean vs @Component?
@Bean
and @Component
are both used for defining beans in a Spring application, but they serve different purposes and are used in different contexts. Here’s a detailed comparison of the two:
@Bean
Purpose:
@Bean
is used to explicitly declare a single bean, rather than letting Spring automatically detect it during component scanning.
Usage:
- It is typically used in Java-based configuration classes, annotated with
@Configuration
. - Provides more control over bean creation and initialization.
- It is typically used in Java-based configuration classes, annotated with
Configuration Class:
- Methods annotated with
@Bean
are located within a@Configuration
class.
- Methods annotated with
Example:
java@Configuration public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } @Bean public MyRepository myRepository() { return new MyRepositoryImpl(); } }
Advantages:
- Provides detailed control over the instantiation, configuration, and initialization of beans.
- Useful for defining beans that need to be configured with specific parameters or for third-party library classes.
@Component
Purpose:
@Component
is a generic stereotype for any Spring-managed component. It tells Spring that the annotated class is a bean.
Usage:
- It is used for automatic component scanning. When Spring scans the classpath, it automatically registers all classes annotated with
@Component
(and other specialized annotations like@Service
,@Repository
, and@Controller
).
- It is used for automatic component scanning. When Spring scans the classpath, it automatically registers all classes annotated with
Component Scanning:
- Classes annotated with
@Component
are automatically detected and registered as beans when component scanning is enabled (using@ComponentScan
).
- Classes annotated with
Example:
java@Component public class MyService { // class implementation } @Component public class MyRepository { // class implementation }
Specialized Annotations:
@Component
is the base annotation, but there are specialized forms for specific types of components:@Service
for service layer beans.@Repository
for data access layer beans.@Controller
for web controllers.
Advantages:
- Simplifies bean registration through classpath scanning.
- Suitable for most application beans, making configuration less verbose.
Key Differences
Declaration:
@Bean
is used on methods in a configuration class (@Configuration
).@Component
is used directly on classes.
Bean Scope:
@Bean
methods can be used to define the scope of the bean (@Scope
can be applied to method level).@Component
beans are typically singleton by default, but scope can be defined with@Scope
.
Use Cases:
- Use
@Bean
for complex bean initialization logic or for integrating third-party libraries. - Use
@Component
(and its specializations) for application-specific beans that can be automatically detected by classpath scanning.
- Use
Control and Flexibility:
@Bean
provides fine-grained control over bean instantiation and configuration.@Component
offers simplicity and convenience for most standard use cases.
Example of Combined Usage
You can combine both @Bean
and @Component
in a Spring application to take advantage of their respective strengths:
java@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl(myRepository());
}
@Bean
public MyRepository myRepository() {
return new MyRepositoryImpl();
}
}
In this example, @ComponentScan
is used to automatically discover @Component
-annotated classes, while @Bean
methods are used to define beans with specific initialization logic.
Conclusion
- Use
@Component
(and its specialized annotations) for most application beans where automatic scanning is sufficient. - Use
@Bean
for explicit bean definitions, especially when detailed control over bean creation and configuration is needed, or when dealing with third-party libraries.
- What is Aspect Oriented Programming?
Aspect-Oriented Programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It enables you to add behavior to existing code without modifying the code itself, typically through the use of "aspects". These aspects enable you to define reusable functionality that can be applied to multiple points in an application.
Key Concepts in AOP
Aspect:
- An aspect is a module that encapsulates a concern that cuts across multiple classes. For example, logging, transaction management, and security are common cross-cutting concerns that can be modularized into aspects.
Join Point:
- A join point is a specific point in the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.
Advice:
- Advice is the action taken by an aspect at a particular join point. Different types of advice include:
- Before Advice: Runs before the method execution.
- After Advice: Runs after the method execution, regardless of its outcome.
- After Returning Advice: Runs after the method execution, only if the method completes successfully.
- After Throwing Advice: Runs after the method execution, only if the method exits by throwing an exception.
- Around Advice: Runs before and after the method execution, allowing you to control whether the method is executed.
- Advice is the action taken by an aspect at a particular join point. Different types of advice include:
Pointcut:
- A pointcut is an expression that matches join points. It defines where advice should be applied. Pointcuts enable you to specify which methods the advice should be applied to, typically using expressions that match method signatures or annotations.
Weaving:
- Weaving is the process of applying aspects to a target object, creating an advised object. Weaving can occur at compile time, load time, or runtime. In Spring AOP, weaving is typically performed at runtime.
AOP in Spring
Spring AOP provides support for aspect-oriented programming within the Spring framework. Spring AOP is proxy-based and operates at the method level. Here is a brief overview of how AOP is implemented in Spring:
Defining an Aspect:
- Create a class annotated with
@Aspect
to define an aspect.
- Create a class annotated with
Defining Advice:
- Use annotations such as
@Before
,@After
,@AfterReturning
,@AfterThrowing
, and@Around
to define different types of advice.
- Use annotations such as
Defining Pointcuts:
- Use the
@Pointcut
annotation to define reusable pointcut expressions.
- Use the
Example
Here’s an example of using AOP in a Spring Boot application:
Add Dependencies:
- Ensure you have the necessary dependencies in your
pom.xml
orbuild.gradle
.
xml<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
- Ensure you have the necessary dependencies in your
Define an Aspect:
javaimport org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.myapp.service.*.*(..))") public void logBeforeMethodExecution() { System.out.println("A method in the service layer is about to be executed."); } }
Enable AspectJ Auto Proxy:
- In your main application class, enable AspectJ auto proxy.
javaimport org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class MySpringBootApplication { public static void main(String[] args) { SpringApplication.run(MySpringBootApplication.class, args); } }
Conclusion
Aspect-Oriented Programming (AOP) is a powerful paradigm that allows for the modularization of cross-cutting concerns, improving code maintainability and reducing duplication. Spring AOP provides a flexible and easy-to-use framework for implementing AOP in Spring-based applications, allowing you to define aspects, pointcuts, and advice to enhance the functionality of your code without modifying the core business logic.
- What is @Qualifier annotation?
The @Qualifier
annotation in Spring is used to resolve the ambiguity when multiple beans of the same type are present in the Spring context and you want to inject a specific bean among them. It helps in explicitly specifying which bean should be injected when there are multiple candidates available.
When to Use @Qualifier
Consider a scenario where you have two beans of the same type, but you want to inject a specific one. Without @Qualifier
, Spring would throw an exception due to ambiguity. The @Qualifier
annotation helps in such cases by narrowing down the candidate beans to the one specified.
Example
Here is an example to illustrate the use of @Qualifier
:
Step 1: Define Multiple Beans of the Same Type
javaimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyService myService1() {
return new MyServiceImpl1();
}
@Bean
public MyService myService2() {
return new MyServiceImpl2();
}
}
In the above configuration, we have two beans of type MyService
.
Step 2: Use @Qualifier to Inject a Specific Bean
javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MyComponent {
private final MyService myService;
@Autowired
public MyComponent(@Qualifier("myService1") MyService myService) {
this.myService = myService;
}
public void performService() {
myService.execute();
}
}
In this example, @Qualifier("myService1")
is used to specify that the myService1
bean should be injected into MyComponent
.
Explanation
- @Configuration: Indicates that the class contains bean definitions.
- @Bean: Defines a bean in the Spring context.
- @Component: Marks the class as a Spring-managed component.
- @Autowired: Indicates that Spring should perform dependency injection.
- @Qualifier: Specifies which bean should be injected when there are multiple candidates.
Key Points
- Explicit Injection:
@Qualifier
is used to explicitly specify which bean to inject when multiple beans of the same type exist. - Combination with @Autowired:
@Qualifier
is often used in conjunction with@Autowired
to fine-tune the injection process. - Bean Names: The value of
@Qualifier
should match the name of one of the candidate beans. Bean names can be explicitly defined or default to the method name (for beans defined in configuration classes).
Conclusion
The @Qualifier
annotation is a powerful feature in Spring that helps resolve ambiguity by specifying exactly which bean should be injected among multiple candidates. This is especially useful in larger applications where multiple beans of the same type might exist and precise control over dependency injection is required.
- What is @Primary annoatation?
The @Primary
annotation in Spring is used to indicate that a specific bean should be given preference when multiple beans of the same type are present in the Spring context. When there are multiple candidates for autowiring, and one of them is annotated with @Primary
, that bean will be injected by default unless another bean is explicitly specified with @Qualifier
.
When to Use @Primary
Use the @Primary
annotation when you want to set a default bean to be injected in situations where multiple beans of the same type exist. This is particularly useful when you have a general-purpose implementation and several specialized implementations of a bean.
Example
Step 1: Define Multiple Beans
javaimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyService myService1() {
return new MyServiceImpl1();
}
@Bean
@Primary
public MyService myService2() {
return new MyServiceImpl2();
}
}
In this configuration, myService2
is annotated with @Primary
, indicating that it should be the default bean.
Step 2: Inject the Bean
javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MyComponent {
private final MyService myService;
@Autowired
public MyComponent(MyService myService) {
this.myService = myService;
}
public void performService() {
myService.execute();
}
}
In this example, the myService2
bean will be injected into MyComponent
because it is marked as @Primary
.
Explanation
- @Configuration: Indicates that the class is a source of bean definitions.
- @Bean: Defines a bean to be managed by the Spring container.
- @Primary: Marks a bean as the primary candidate for injection when multiple beans of the same type are available.
- @Autowired: Indicates that Spring should perform dependency injection.
Combining @Primary and @Qualifier
You can combine @Primary
and @Qualifier
annotations to provide both a default and specific beans.
javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MyComponent {
private final MyService myPrimaryService;
private final MyService mySpecificService;
@Autowired
public MyComponent(MyService myPrimaryService, @Qualifier("myService1") MyService mySpecificService) {
this.myPrimaryService = myPrimaryService;
this.mySpecificService = mySpecificService;
}
public void performPrimaryService() {
myPrimaryService.execute();
}
public void performSpecificService() {
mySpecificService.execute();
}
}
In this example:
myPrimaryService
will be injected withmyService2
because it is marked as@Primary
.mySpecificService
will be injected withmyService1
due to the@Qualifier
annotation.
Key Points
- Default Injection:
@Primary
is used to set a default bean for injection when multiple candidates are present. - Combining with @Qualifier: You can use
@Primary
for default behavior and@Qualifier
for specific needs, providing flexibility in bean injection. - Bean Preferences: Only one bean of a given type should be marked as
@Primary
. If multiple beans are marked as@Primary
, an exception will be thrown during application startup.
Conclusion
The @Primary
annotation is a useful feature in Spring for resolving ambiguity when multiple beans of the same type exist. It allows you to designate a default bean to be injected, simplifying the configuration and reducing the need for explicit qualifiers in many cases. This is particularly helpful in large applications with multiple implementations of the same interface.
- What are uses of filter and ControllerAdvice?
In Spring, filters and @ControllerAdvice
serve different purposes but are both essential in handling various cross-cutting concerns in web applications. Here's an overview of their uses:
Filters
Filters are used to perform filtering tasks on either the request to a resource or on the response from a resource, or both. They are part of the Servlet API and are used to preprocess or postprocess requests and responses.
Uses of Filters:
Authentication and Authorization:
- Filters can intercept incoming requests and check if the user is authenticated and authorized to access the requested resource.
Logging and Auditing:
- Filters can log request details, such as the request URL, parameters, and headers, as well as response details.
Request and Response Modification:
- Filters can modify request or response objects before they reach the controller or before they are sent back to the client.
Cross-Origin Resource Sharing (CORS):
- Filters can handle CORS settings by adding appropriate headers to responses.
Compression:
- Filters can compress response data before sending it to the client.
Example of a Filter:
javaimport javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(urlPatterns = "/*")
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Initialization code
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// Pre-processing
System.out.println("Request received at " + System.currentTimeMillis());
chain.doFilter(request, response);
// Post-processing
System.out.println("Response sent at " + System.currentTimeMillis());
}
@Override
public void destroy() {
// Cleanup code
}
}
@ControllerAdvice
@ControllerAdvice
is a specialization of the @Component
annotation in Spring that allows you to handle exceptions, bind parameters, and apply model attributes to multiple controllers globally. It can be used to define shared logic for all or a subset of controllers.
Uses of @ControllerAdvice:
Global Exception Handling:
@ControllerAdvice
can be used to define methods that handle exceptions thrown by any controller. This centralizes exception handling logic.
Model Attributes:
- Methods annotated with
@ModelAttribute
within a@ControllerAdvice
class can add attributes to the model, making them available to all controllers.
- Methods annotated with
Binding Initializers:
- Methods annotated with
@InitBinder
within a@ControllerAdvice
class can customize the data binding process for all controllers.
- Methods annotated with
Example of @ControllerAdvice for Global Exception Handling:
javaimport org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = { IllegalArgumentException.class, IllegalStateException.class })
protected ResponseEntity<Object> handleConflict(RuntimeException ex, WebRequest request) {
String bodyOfResponse = "This should be application specific";
return new ResponseEntity<>(bodyOfResponse, HttpStatus.CONFLICT);
}
@ExceptionHandler(value = { Exception.class })
protected ResponseEntity<Object> handleGenericException(Exception ex, WebRequest request) {
String bodyOfResponse = "An unexpected error occurred";
return new ResponseEntity<>(bodyOfResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Key Differences
Filters:
- Operate at a lower level than controllers, dealing with raw HTTP requests and responses.
- Ideal for tasks that need to be performed on every request, such as security, logging, and compression.
- Configured at the web application level, affecting all incoming requests.
@ControllerAdvice:
- Operates at a higher level within the Spring MVC framework, specifically designed to work with controllers.
- Ideal for handling exceptions, adding model attributes, and custom data binding across multiple controllers.
- Provides a way to centralize controller-related concerns, making the codebase cleaner and easier to maintain.
Conclusion
Filters and @ControllerAdvice
are powerful tools in Spring for managing cross-cutting concerns. Filters are best suited for low-level request and response processing, while @ControllerAdvice
provides a higher-level mechanism for managing shared logic among controllers, such as exception handling and model attributes. Both can greatly enhance the modularity and maintainability of your Spring applications.
- Explain about different HTTP Methods?
- What is Idempotency? Explain about Idempotent methods?
- What is @Transactional annotation? Understand its uses?
he @Transactional
annotation in Spring is used to manage transaction boundaries declaratively. It simplifies transaction management by allowing you to specify transaction properties directly in your code, without having to deal with low-level transaction APIs.
Uses of @Transactional
Declarative Transaction Management:
- Allows you to define the transactional behavior of methods directly within your code using annotations, instead of configuring transactions in XML or programmatically.
Transaction Propagation:
- Defines how transactions are propagated. You can specify if a method should run within an existing transaction or create a new one, among other behaviors.
Isolation Levels:
- Controls the degree of isolation for transactions, affecting how the transaction is visible to other transactions. This can help manage issues like dirty reads, non-repeatable reads, and phantom reads.
Timeouts:
- Specifies the maximum time a transaction should take before it is automatically rolled back. This can prevent long-running transactions from hanging indefinitely.
Rollback Rules:
- Determines which exceptions should cause a transaction to be rolled back. You can specify specific exceptions or even broad categories of exceptions.
Example
Step 1: Configure Transaction Management
Ensure that transaction management is enabled in your Spring configuration.
javaimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
Step 2: Annotate Methods with @Transactional
Apply the @Transactional
annotation to methods where you want to manage transactions.
javaimport org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyService {
@Transactional
public void performTransaction() {
// Business logic here
// Any database operations performed within this method will be part of the transaction
}
}
Key Properties of @Transactional
- Propagation:
- Defines how the transaction should propagate. Common propagation types include:
REQUIRED
: Supports the current transaction, or creates a new one if none exists.REQUIRES_NEW
: Suspends the current transaction and creates a new one.MANDATORY
: Supports the current transaction; throws an exception if none exists.SUPPORTS
: Executes within a transaction if one exists, otherwise, executes non-transactionally.NOT_SUPPORTED
: Executes non-transactionally, suspending any existing transaction.NEVER
: Executes non-transactionally; throws an exception if a transaction exists.NESTED
: Executes within a nested transaction if a current transaction exists, or creates a new one if none exists.
- Defines how the transaction should propagate. Common propagation types include:
java@Transactional(propagation = Propagation.REQUIRES_NEW)
public void performAnotherTransaction() {
// Business logic with a new transaction
}
- Isolation:
- Defines the transaction isolation level. Common levels include:
DEFAULT
: Uses the default isolation level of the underlying datastore.READ_UNCOMMITTED
: Allows dirty reads.READ_COMMITTED
: Prevents dirty reads.REPEATABLE_READ
: Prevents dirty reads and non-repeatable reads.SERIALIZABLE
: Ensures full serializability but may impact performance.
- Defines the transaction isolation level. Common levels include:
java@Transactional(isolation = Isolation.SERIALIZABLE)
public void performSerializableTransaction() {
// Business logic with serializable isolation
}
- Timeout:
- Specifies the timeout for a transaction in seconds.
java@Transactional(timeout = 5)
public void performTimedTransaction() {
// Business logic that must complete within 5 seconds
}
- RollbackFor and NoRollbackFor:
- Specifies which exceptions should trigger a rollback or which should not.
java@Transactional(rollbackFor = {Exception.class})
public void performTransactionWithRollback() {
// Business logic that will rollback on any exception
}
@Transactional(noRollbackFor = {IllegalArgumentException.class})
public void performTransactionWithoutRollback() {
// Business logic that will not rollback on IllegalArgumentException
}
Example Usage
Here is an example that combines multiple properties:
java@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.REPEATABLE_READ,
timeout = 10,
rollbackFor = {RuntimeException.class}
)
public void performComplexTransaction() {
// Business logic with specific transaction properties
}
Conclusion
The @Transactional
annotation is a powerful tool in Spring for managing transactions declaratively. It allows developers to specify transaction management properties directly in the code, improving readability and maintainability. By using @Transactional
, you can control transaction propagation, isolation levels, timeouts, and rollback rules effectively, ensuring your application's data integrity and consistency.
- What is actuator? Explain about few endpoints of actuator?
Spring Boot Actuator is a sub-project of Spring Boot that provides production-ready features to help you monitor and manage your application. It includes several built-in endpoints that expose various aspects of the application, such as health, metrics, environment properties, and more. These endpoints are primarily used for monitoring, diagnostics, and managing the application in production environments.
Key Features of Spring Boot Actuator
- Health Checks: Provides information about the health of the application.
- Metrics: Exposes metrics related to the application's performance and usage.
- Environment: Displays the environment properties and configurations.
- Thread Dump: Provides a thread dump for the application.
- Mappings: Shows the mappings of controllers and methods.
- Loggers: Allows you to view and configure logging levels at runtime.
- Custom Endpoints: Allows you to create your own custom actuator endpoints.
Common Actuator Endpoints
Here are some commonly used Actuator endpoints and their purposes:
/actuator/health:
- Provides the health status of the application.
- Example response:json
{ "status": "UP" }
- You can also add custom health indicators to include more detailed health checks.
/actuator/info:
- Displays arbitrary application information.
- Example response:json
{ "app": { "name": "MyApp", "version": "1.0.0" } }
- This can be configured to show application-specific information such as version, build details, etc.
/actuator/metrics:
- Provides various metrics related to the application, such as memory usage, garbage collection, CPU usage, etc.
- Example response:json
{ "names": [ "jvm.memory.used", "jvm.memory.max", "system.cpu.usage" ] }
/actuator/mappings:
- Displays a list of all
@RequestMapping
paths and their associated handlers. - Example response:json
{ "contexts": { "application": { "mappings": { "dispatcherServlets": { "dispatcherServlet": [ { "handler": "public java.lang.String com.example.MyController.home()", "predicate": "{GET /}" } ] } } } } }
- Displays a list of all
/actuator/env:
- Shows the current environment properties.
- Example response:json
{ "propertySources": [ { "name": "systemProperties", "properties": { "java.version": { "value": "11.0.6" } } } ] }
/actuator/loggers:
- Allows you to view and change the logging level of the application at runtime.
- Example response:json
{ "loggers": { "com.example.MyClass": { "configuredLevel": "DEBUG", "effectiveLevel": "DEBUG" } } }
/actuator/threaddump:
- Provides a thread dump of the application.
- Example response:json
[ { "threadName": "http-nio-8080-exec-1", "threadId": 28, "blockedTime": -1, "blockedCount": 3, "waitedTime": -1, "waitedCount": 13, "lockName": null, "lockOwnerId": -1, "lockOwnerName": null, "inNative": false, "suspended": false, "threadState": "RUNNABLE", "stackTrace": [ { "className": "java.net.SocketInputStream", "methodName": "socketRead0", "fileName": "SocketInputStream.java", "lineNumber": -2, "nativeMethod": true } ] } ]
Enabling Actuator in Spring Boot
To enable Actuator in your Spring Boot application, you need to add the spring-boot-starter-actuator
dependency in your pom.xml
(for Maven) or build.gradle
(for Gradle) file.
Maven
xml<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Gradle
groovyimplementation 'org.springframework.boot:spring-boot-starter-actuator'
Configuring Actuator
You can configure which endpoints are exposed and their access levels in the application.properties
or application.yml
file.
Example Configuration (application.properties)
propertiesmanagement.endpoints.web.exposure.include=health,info,metrics management.endpoint.health.show-details=always management.endpoint.metrics.enabled=true
Securing Actuator Endpoints
By default, all Actuator endpoints are unsecured. In a production environment, it's crucial to secure these endpoints. You can use Spring Security to secure them.
Example Security Configuration
javaimport org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/actuator/**").authenticated()
.and()
.httpBasic();
}
}
Conclusion
Spring Boot Actuator provides a comprehensive set of tools for monitoring and managing your application. By leveraging Actuator's built-in endpoints, you can gain insights into the application's health, performance, and behavior. Proper configuration and securing of these endpoints are crucial for maintaining a secure and efficient production environment.
- What is Profiling in Spring boot?
Profiling in Spring Boot refers to the mechanism of defining and managing different environments for an application, such as development, testing, and production. This is achieved using the @Profile
annotation, which allows you to specify beans that should only be created in certain profiles. By using profiles, you can segregate configurations and beans specific to different environments, making your application more flexible and easier to manage.
Key Features of Profiling
Environment-Specific Configuration:
- Different configurations can be loaded for different environments, such as database connections, properties, or services.
Conditional Bean Creation:
- Beans can be created conditionally based on the active profile, ensuring that only the necessary beans are loaded in a particular environment.
Simplified Management:
- Profiles simplify the management of configurations by centralizing environment-specific properties and beans.
How to Use Profiles in Spring Boot
1. Defining Profiles in Configuration
You can define environment-specific properties in separate files, typically named application-{profile}.properties
or application-{profile}.yml
.
Example: application-dev.properties
propertiesspring.datasource.url=jdbc:mysql://localhost:3306/devdb spring.datasource.username=devuser spring.datasource.password=devpassword
Example: application-prod.properties
propertiesspring.datasource.url=jdbc:mysql://localhost:3306/proddb spring.datasource.username=produser spring.datasource.password=prodpassword
2. Activating Profiles
Profiles can be activated in several ways:
Command Line: Use the
--spring.profiles.active
argument when running the application.shjava -jar myapp.jar --spring.profiles.active=dev
Environment Variable: Set the
SPRING_PROFILES_ACTIVE
environment variable.shexport SPRING_PROFILES_ACTIVE=dev
Application Properties: Define the active profile in the
application.properties
file.propertiesspring.profiles.active=dev
3. Using @Profile Annotation
You can annotate beans or configuration classes with @Profile
to specify the profiles in which they should be active.
Example: Conditional Bean Definition
javaimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class AppConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/devdb")
.username("devuser")
.password("devpassword")
.build();
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/proddb")
.username("produser")
.password("prodpassword")
.build();
}
}
Example Usage
Consider an application with different configurations for development and production environments. You can use profiles to manage these configurations effectively.
Step 1: Define Configuration Files
Create application-dev.properties
and application-prod.properties
with respective configurations.
Step 2: Define Beans with @Profile
javaimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class AppConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/devdb")
.username("devuser")
.password("devpassword")
.build();
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/proddb")
.username("produser")
.password("prodpassword")
.build();
}
}
Step 3: Activate Profiles
Activate the desired profile when running the application. For development:
shjava -jar myapp.jar --spring.profiles.active=dev
For production:
shjava -jar myapp.jar --spring.profiles.active=prod
Conclusion
Profiling in Spring Boot provides a powerful and flexible way to manage environment-specific configurations and beans. By using profiles, you can ensure that the appropriate configurations are loaded for each environment, simplifying development, testing, and deployment processes. The @Profile
annotation and profile-specific property files make it easy to segregate and manage these configurations effectively.
- How Spring Knows Property file location? explain about different properties?
- @Async in Spring Boot?
In Spring Boot, the @Async
annotation is used to execute methods asynchronously. This means that the method will be executed in a separate thread, and the caller will not block waiting for the method to complete. This can be useful for improving the performance of your application by offloading time-consuming tasks to background threads.
Key Features of @Async
Asynchronous Execution:
- Methods annotated with
@Async
will run in a separate thread, allowing the main thread to continue processing other tasks.
- Methods annotated with
Non-Blocking:
- The caller can continue executing without waiting for the
@Async
method to complete, which can lead to improved responsiveness and performance.
- The caller can continue executing without waiting for the
Return Types:
@Async
methods can returnvoid
,java.util.concurrent.Future
,org.springframework.util.concurrent.ListenableFuture
, orjava.util.concurrent.CompletableFuture
.
Enabling Async Support
To use @Async
in your Spring Boot application, you need to enable async processing by adding the @EnableAsync
annotation to one of your configuration classes.
Step 1: Enable Async Support
Create a configuration class and annotate it with @EnableAsync
.
javaimport org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
}
Step 2: Annotate Methods with @Async
Annotate the methods you want to run asynchronously with @Async
.
javaimport org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncService {
@Async
public void asyncMethod() {
System.out.println("Executing method asynchronously - " + Thread.currentThread().getName());
}
@Async
public CompletableFuture<String> asyncMethodWithReturn() {
System.out.println("Executing method asynchronously with return - " + Thread.currentThread().getName());
return CompletableFuture.completedFuture("Hello from async method!");
}
}
Example Usage
Here's an example that demonstrates how to use @Async
in a Spring Boot application.
Step 1: Create a Service with Async Methods
javaimport org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncService {
@Async
public void performTask() {
System.out.println("Performing task in background - " + Thread.currentThread().getName());
try {
Thread.sleep(5000); // Simulate long running task
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Task completed");
}
@Async
public CompletableFuture<String> performTaskWithReturn() {
System.out.println("Performing task in background with return - " + Thread.currentThread().getName());
try {
Thread.sleep(5000); // Simulate long running task
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return CompletableFuture.completedFuture("Task completed with return");
}
}
Step 2: Call Async Methods from a Controller
javaimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@RestController
@RequestMapping("/api")
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping("/async")
public String callAsyncMethod() {
asyncService.performTask();
return "Async method called";
}
@GetMapping("/async-return")
public CompletableFuture<String> callAsyncMethodWithReturn() {
return asyncService.performTaskWithReturn();
}
}
Example Output
When you call the /api/async
endpoint, you will see something like this in the console:
arduinoPerforming task in background - SimpleAsyncTaskExecutor-1
And the response will be:
sqlAsync method called
For the /api/async-return
endpoint, the response will be returned once the asynchronous method completes:
arduinoPerforming task in background with return - SimpleAsyncTaskExecutor-2
And the response will be:
arduinoTask completed with return
Customizing the Executor
By default, Spring Boot uses a SimpleAsyncTaskExecutor
, which is not suitable for production. You can customize the executor by defining a ThreadPoolTaskExecutor
bean.
javaimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
Then, specify this executor for your async methods:
java@Async("taskExecutor")
public void asyncMethod() {
// ...
}
Conclusion
The @Async
annotation in Spring Boot allows you to execute methods asynchronously, improving the responsiveness and performance of your application by offloading time-consuming tasks to background threads. By enabling async support and customizing the executor, you can effectively manage asynchronous processing in your Spring Boot application.
- Difference between CrudRepository vs JPARespository?
In Spring Data, CrudRepository
and JpaRepository
are both interfaces that provide CRUD (Create, Read, Update, Delete) functionality for interacting with a database. However, they have some differences in terms of the features they offer and the way they are used.
CrudRepository
- Basic CRUD Operations:
CrudRepository
provides basic CRUD operations such assave
,findById
,findAll
,delete
, andcount
. - Interface Definition: It is a generic interface that you can extend for a specific entity type. For example,
CrudRepository<User, Long>
for aUser
entity with a primary key of typeLong
. - Limited Query Methods: Provides only basic query methods. For complex queries, you need to define custom query methods in your repository interface.
JpaRepository
- Extends CrudRepository:
JpaRepository
extendsCrudRepository
, so it inherits all the basic CRUD operations. - Additional Query Methods: Provides additional JPA-specific query methods such as
findAllByOrderBy{Property}Asc
,findFirstBy{Property}
,deleteBy{Property}
, etc. These methods are derived from the method name, and you don't need to write the query explicitly. - Pagination and Sorting: Supports pagination and sorting out of the box with methods like
findAll(Pageable pageable)
andfindAll(Sort sort)
. - Entity Manager:
JpaRepository
extendsPagingAndSortingRepository
, which in turn extendsCrudRepository
, and also provides access to theEntityManager
if you need it for custom queries.
Choosing Between CrudRepository and JpaRepository
- If you need only basic CRUD operations and don't require complex query methods or pagination,
CrudRepository
is sufficient. - If you need additional query methods, pagination, and sorting features provided by JPA,
JpaRepository
is more suitable. - If you are using Spring Data JPA and want to leverage its query derivation features,
JpaRepository
is the better choice.
Example Usage
CrudRepository
javaimport org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Long> {
}
JpaRepository
javaimport org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByFirstName(String firstName);
}
In this example, UserRepository
extends JpaRepository
and provides a custom query method findByFirstName
, which is a JPA-specific query method that retrieves users by their first name.
- Explain about different starter dependencies of Spring boot?
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.