Quick Guide to Spring Boot
Essential Tips and Tricks for Rapid Java Development
Table of contents
- Introduction to Spring Boot
- Getting Started with Spring Boot
- Core Concepts and Features
- Spring Boot Annotations
- Core Annotations
- Configuration Annotations
- Component Scanning Annotations
- Stereotype Annotations
- Web Annotations
- Dependency Injection Annotations
- Configuration Properties Annotations
- Caching Annotations
- Scheduling Annotations
- Aspect-Oriented Programming (AOP) Annotations
- Testing Annotations
- Miscellaneous Annotations
- @ConditionalOnProperty
- @Profile
- @Conditional
- @Import
- @ImportResource
- Auto-Configuration
- 1. Introduction to Auto-Configuration
- 2. How Auto-Configuration Works
- 3. Common Auto-Configuration Examples
- 4. Disabling Specific Auto-Configuration
- 5. Customizing Auto-Configuration
- 6. Creating Your Own Auto-Configuration
- 7. Debugging Auto-Configuration
- 8. Using @EnableAutoConfiguration
- Spring Boot Profiles
- 1. Introduction to Profiles
- 2. Defining Profiles
- 3. Activating Profiles
- 4. Profile-Specific Beans
- 5. Multiple Profiles
- 6. Default Profile
- 7. Testing with Profiles
- 8. Merging Properties
- Configuration in Spring Boot
- Externalised Configuration
- Configuration Properties
- 1. Externalized Configuration
- 2. Configuration Properties
- 3. Profile-Specific Configuration
- 4. Type-Safe Configuration
- 5. Default Property Values
- 6. Custom Configuration Properties
- 7. Property Sources
- 8. Spring Environment Abstraction
- 9. Configuration Classes
- 10. Conditional Configuration
- Building RESTful Web Services
- Conclusion
Introduction to Spring Boot
Spring Boot is an open-source framework that simplifies the development of Java applications. It is built on the Spring Framework and allows developers to create stand-alone, production-grade applications that "just run". Spring Boot reduces the amount of boilerplate code and configuration required to set up a Spring application, enabling rapid development.
Why Use Spring Boot?
Spring Boot offers several key benefits:
Rapid Development: With built-in conventions and defaults, you can get started quickly.
Standalone Applications: Spring Boot applications run independently without needing a traditional application server, thanks to embedded servers like Tomcat or Jetty.
Microservices Support: Designed to support microservices architecture, making it easy to build and deploy microservices.
Production-Ready Features: Includes built-in features for monitoring, metrics, and externalized configuration.
Convention over Configuration: Reduces the need for extensive configuration files by following sensible defaults.
Getting Started with Spring Boot
Setting up the Development Environment
Before starting with Spring Boot, ensure you have the following installed:
Java Development Kit (JDK): Version 8 or higher.
Integrated Development Environment (IDE): IntelliJ IDEA, Eclipse, or your preferred IDE.
Build Tool: Maven or Gradle.
Spring Boot Initializr
Spring Boot Initializr is a web-based tool to bootstrap your Spring Boot project. It allows you to select your project’s dependencies and configurations, and generates a ready-to-run application.
Go to Spring Boot Initializr.
Choose your project settings: Group, Artifact, Name, and Packaging (JAR or WAR).
Select dependencies (e.g., Spring Web, Spring Data JPA, Spring Security).
Click "Generate" to download the project as a ZIP file.
Extract the ZIP file and open it in your IDE.
Creating Your First Spring Boot Application
Once you’ve set up your project using Spring Boot Initializr, you can create your first Spring Boot application.
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
This simple class uses the @SpringBootApplication
annotation, which is a composite annotation that includes @Configuration
, @EnableAutoConfiguration
, and @ComponentScan
. It tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
Understanding the Project Structure
When you generate a Spring Boot project, it follows a standard structure:
src/main/java: Contains the application source code.
src/main/resources: Contains application resources such as properties files and static files.
src/test/java: Contains the test source code.
pom.xml (for Maven) or build.gradle (for Gradle): Contains the project dependencies and build configurations.
Core Concepts and Features
Spring Boot Starters
Spring Boot starters are a set of convenient dependency descriptors you can include in your application. They simplify the process of setting up new Spring applications by providing default configurations and dependencies for common tasks and technologies. Each starter is a Maven dependency that includes other dependencies to bootstrap a Spring application. By using starters, developers can quickly add necessary libraries and configurations to their projects without manually specifying each dependency.
Key Features of Spring Boot Starters
Convenience: Starters aggregate common dependencies into a single dependency entry in your
pom.xml
orbuild.gradle
file.Consistency: They ensure consistent versions of dependencies, which helps in avoiding version conflicts.
Reduced Configuration: Starters reduce the boilerplate configuration required to set up a Spring application.
Focused Purpose: Each starter is designed for a specific purpose or technology, making it easy to understand and use.
Common Spring Boot Starters
Here are some of the most commonly used Spring Boot starters, along with descriptions and examples of their usage:
spring-boot-starter-web
Description: Starter for building web, including RESTful, applications using Spring MVC. It uses Tomcat as the default embedded container.
Dependencies: Includes Spring MVC, Jackson (for JSON processing), and embedded Tomcat.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-data-jpa
Description: Starter for using Spring Data JPA with Hibernate as the JPA implementation.
Dependencies: Includes Spring Data JPA, Hibernate, and a connection pool (HikariCP by default).
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
spring-boot-starter-security
Description: Starter for using Spring Security.
Dependencies: Includes Spring Security.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
spring-boot-starter-test
Description: Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest, and Mockito.
Dependencies: Includes Spring Boot Test, JUnit, AssertJ, Hamcrest, and Mockito.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
spring-boot-starter-thymeleaf
Description: Starter for building web applications using Thymeleaf.
Dependencies: Includes Thymeleaf and Spring MVC.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
spring-boot-starter-logging
Description: Starter for logging using Logback.
Dependencies: Includes Logback, SLF4J, and Log4j 2.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
spring-boot-starter-aop
Description: Starter for aspect-oriented programming with Spring AOP and AspectJ.
Dependencies: Includes Spring AOP and AspectJ.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
spring-boot-starter-jersey
Description: Starter for building RESTful applications using JAX-RS and Jersey.
Dependencies: Includes Jersey, Spring Framework, and required dependencies for JAX-RS.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
spring-boot-starter-websocket
Description: Starter for building WebSocket applications.
Dependencies: Includes Spring WebSocket.
Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
Spring Boot Annotations
Core Annotations
@SpringBootApplication
Description: This annotation is used to mark the main class of a Spring Boot application. It combines three annotations:
@Configuration
,@EnableAutoConfiguration
, and@ComponentScan
. This single annotation simplifies the configuration and setup of a Spring Boot application.Usage: Place this annotation on the main class that will run the Spring Boot application.
Example:
@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
Configuration Annotations
@Configuration
Description: Indicates that the class can be used by the Spring IoC container as a source of bean definitions. This is used to define beans and configure settings within a Spring application.
Usage: Apply this annotation to configuration classes where you define beans.
Example:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
@Bean
Description: Indicates that a method produces a bean to be managed by the Spring container. This is used within
@Configuration
classes to define beans that are available for dependency injection.Usage: Annotate methods in a
@Configuration
class to define beans.Example:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
Component Scanning Annotations
@ComponentScan
Description: Configures component scanning directives for use with
@Configuration
classes. It specifies the base packages to scan for Spring-managed components.Usage: Use this annotation on configuration classes or in combination with
@SpringBootApplication
to specify which packages to scan.Example:
@SpringBootApplication
@ComponentScan(basePackages = "com.example")
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
Stereotype Annotations
@Component
Description: Indicates that an annotated class is a Spring-managed component. It is a generic stereotype for any Spring-managed component.
Usage: Annotate classes to be auto-detected during classpath scanning and registered as beans.
Example:
@Component
public class MyComponent {
// ...
}
@Service
Description: Specializes
@Component
to indicate that a class performs some service, such as business logic. It is used to annotate service-layer components.Usage: Annotate service classes to denote that they hold business logic.
Example:
@Service
public class MyService {
// ...
}
@Repository
Description: Specializes
@Component
to indicate that a class is a repository, which encapsulates the logic required to access data sources. It is used to define data access components.Usage: Annotate data access classes or DAOs.
Example:
@Repository
public class MyRepository {
// ...
}
@Controller
Description: Specializes
@Component
to indicate that a class is a web controller. It handles web requests and returns views.Usage: Annotate classes that handle HTTP requests and responses in a web application.
Example:
@Controller
public class MyController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
@RestController
Description: A convenience annotation that combines
@Controller
and@ResponseBody
. It is used to create RESTful web services by returning data directly rather than rendering a view.Usage: Annotate classes that handle RESTful web services.
Example:
@RestController
public class MyRestController {
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
}
Web Annotations
@RequestMapping
Description: Used to map web requests to specific handler classes and/or handler methods. It can be used to specify the URL path, HTTP method, and other parameters.
Usage: Annotate methods or classes to handle specific HTTP requests.
Example:
@RestController
@RequestMapping("/api")
public class MyController {
@GetMapping("/items")
public List<Item> getItems() {
return itemService.getAllItems();
}
}
@GetMapping
, @PostMapping
, @PutMapping
, @DeleteMapping
Description: Specialized versions of
@RequestMapping
for specific HTTP methods (GET, POST, PUT, DELETE).Usage: Use these annotations to handle specific types of HTTP requests.
Example:
@RestController
public class MyController {
@PostMapping("/items")
public Item createItem(@RequestBody Item item) {
return itemService.saveItem(item);
}
}
@PathVariable
Description: Used to bind a method parameter to a URI template variable. It extracts values from the URI and passes them to handler methods.
Usage: Annotate method parameters to bind them to path variables in the URL.
Example:
@GetMapping("/items/{id}")
public Item getItem(@PathVariable Long id) {
return itemService.getItemById(id);
}
@RequestParam
Description: Used to bind a method parameter to a web request parameter. It retrieves values from the query string or form data.
Usage: Annotate method parameters to bind them to query parameters in the request.
Example:
@GetMapping("/search")
public List<Item> searchItems(@RequestParam String query) {
return itemService.searchItems(query);
}
@RequestBody
Description: Used to bind the body of the web request to a method parameter. It is used to receive data from the client.
Usage: Annotate method parameters to bind them to the request body.
Example:
@PostMapping("/items")
public Item createItem(@RequestBody Item item) {
return itemService.saveItem(item);
}
@ResponseBody
Description: Indicates that the return value of a method should be used as the response body. It is used to return data directly rather than a view.
Usage: Annotate methods in controllers to return data directly.
Example:
@Controller
public class MyController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello, World!";
}
}
@ExceptionHandler
Description: Used to handle exceptions thrown by request handling methods. It allows for custom error handling and response generation.
Usage: Annotate methods in a controller or
@ControllerAdvice
class to handle exceptions.Example:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleException(Exception e) {
return "Error: " + e.getMessage();
}
}
Dependency Injection Annotations
@Autowired
Description: Marks a constructor, field, setter method, or config method to be autowired by Spring's dependency injection facilities. It allows Spring to resolve and inject collaborating beans into your bean.
Usage: Annotate fields, constructors, or setter methods to inject dependencies.
Example:
@Service
public class MyService {
private final MyRepository myRepository;
@Autowired
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
}
@Qualifier
Description: Used in conjunction with
@Autowired
to specify which bean should be injected when multiple beans of the same type exist. It helps to resolve ambiguity.Usage: Annotate fields or parameters to specify the exact bean to be injected.
Example:
@Service
public class MyService {
@Autowired
@Qualifier("specialBean")
private MyRepository myRepository;
}
@Primary
Description: Indicates that a bean should be given preference when multiple beans of the same type exist. It helps in resolving conflicts by specifying the primary bean to use.
Usage: Annotate a bean to mark it as the primary choice.
Example:
@Service
@Primary
public class PrimaryService implements MyService {
// ...
}
Configuration Properties Annotations
@Value
Description: Used to inject values into fields, constructor arguments, or method parameters from a property file (e.g.,
application.properties
).Usage: Annotate fields or method parameters to bind property values.
Example:
@Component
public class MyComponent {
@Value("${app.name}")
private String appName;
}
@ConfigurationProperties
Description: Binds external properties (from
application.properties
orapplication.yml
) to a Java bean. It allows for grouping properties into a configuration class.Usage: Annotate a class to bind configuration properties to it.
Example:
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private String version;
// Getters and setters
}
@PropertySource
Description: Specifies the location of properties files to be loaded. It allows for defining custom property sources.
Usage: Annotate a configuration class to specify additional property files.
Example:
@Configuration
@PropertySource("classpath:custom.properties")
public class AppConfig {
// Configuration
}
Caching Annotations
@EnableCaching
Description: Enables caching support in a Spring application. It is used to enable the caching abstraction provided by Spring.
Usage: Annotate a configuration class to enable caching.
Example:
@Configuration
@EnableCaching
public class CacheConfig {
// Cache configuration
}
@Cacheable
Description: Indicates that the result of a method should be cached. It helps to reduce the number of times the method is executed by storing its results.
Usage: Annotate methods whose results should be cached.
Example:
@Service
public class MyService {
@Cacheable(value = "items", key = "#id")
public Item getItem(Long id) {
return itemRepository.findById(id).orElse(null);
}
}
@CacheEvict
Description: Indicates that one or more caches should be cleared. It helps in removing specific cache entries or clearing all entries.
Usage: Annotate methods to clear cache entries.
Example:
@Service
public class MyService {
@CacheEvict(value = "items", allEntries = true)
public void clearCache() {
// Clear cache
}
}
@CachePut
Description: Indicates that a method call should update (put) the cache with the method's result. It updates the cache without interfering with the method execution.
Usage: Annotate methods to update the cache.
Example:
@Service
public class MyService {
@CachePut(value = "items", key = "#item.id")
public Item updateItem(Item item) {
return itemRepository.save(item);
}
}
@Caching
Description: Allows grouping multiple cache annotations to be applied on a single method. It provides more control over caching operations.
Usage: Annotate methods to apply multiple caching operations.
Example:
@Service
public class MyService {
@Caching(evict = {
@CacheEvict(value = "items", key = "#item.id"),
@CacheEvict(value = "items", allEntries = true)
})
public void deleteItem(Long id) {
itemRepository.deleteById(id);
}
}
Scheduling Annotations
@EnableScheduling
Description: Enables Spring’s scheduled task execution capability. It allows for scheduling tasks at fixed intervals or with cron expressions.
Usage: Annotate a configuration class to enable scheduling.
Example:
@Configuration
@EnableScheduling
public class SchedulingConfig {
// Scheduling configuration
}
@Scheduled
Description: Marks a method to be scheduled to run periodically. It supports fixed-rate, fixed-delay, and cron-based scheduling.
Usage: Annotate methods to specify their execution schedule.
Example:
@Component
public class ScheduledTasks {
@Scheduled(fixedRate = 5000)
public void performTask() {
System.out.println("Regular task performed");
}
}
Aspect-Oriented Programming (AOP) Annotations
@EnableAspectJAutoProxy
Description: Enables support for handling components marked with
@Aspect
annotations. It allows for AOP configuration.Usage: Annotate a configuration class to enable AspectJ auto-proxying.
Example:
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
// AOP configuration
}
@Aspect
Description: Indicates that the class is an aspect, which is a modularization of a concern that cuts across multiple classes. It is used for defining cross-cutting concerns like logging, security, etc.
Usage: Annotate classes to define aspects.
Example:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Logging before method: " + joinPoint.getSignature().getName());
}
}
Testing Annotations
@SpringBootTest
Description: Used for unit tests that require Spring Boot features. It loads the complete application context and allows for integration testing.
Usage: Annotate test classes that need Spring Boot’s application context.
Example:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTests {
@Autowired
private MyService myService;
@Test
public void testServiceMethod() {
assertNotNull(myService);
}
}
@MockBean
Description: Used to add mock beans to the Spring ApplicationContext. It replaces a bean with a mock for testing purposes.
Usage: Annotate fields in test classes to add mock beans.
Example:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTests {
@MockBean
private MyRepository myRepository;
@Autowired
private MyService myService;
@Test
public void testServiceMethod() {
assertNotNull(myService);
}
}
@SpyBean
Description: Used to add spy beans to the Spring ApplicationContext. It creates a spy that can be used to partially mock and verify interactions.
Usage: Annotate fields in test classes to add spy beans.
Example:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyServiceTests {
@SpyBean
private MyService myService;
@Test
public void testServiceMethod() {
assertNotNull(myService);
}
}
@DataJpaTest
Description: Used for testing JPA repositories. It configures an in-memory database and scans for JPA entities and repositories.
Usage: Annotate test classes that focus on JPA components.
Example:
@RunWith(SpringRunner.class)
@DataJpaTest
public class MyRepositoryTests {
@Autowired
private MyRepository myRepository;
@Test
public void testRepositoryMethod() {
// Test repository method
}
}
Miscellaneous Annotations
@ConditionalOnProperty
Description: Used to conditionally include beans based on a Spring Environment property. It allows bean registration based on property values.
Usage: Annotate configuration classes or beans to conditionally load them based on properties.
Example:
@Configuration
public class MyConfig {
@Bean
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public MyService myService() {
return new MyServiceImpl();
}
}
@Profile
Description: Specifies that a component is eligible for registration when one or more specified profiles are active. It allows beans to be activated based on the environment profile.
Usage: Annotate configuration classes or beans to activate them for specific profiles.
Example:
@Configuration
@Profile("dev")
public class DevConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
@Conditional
Description: Marks that the component should be registered if the given condition matches. It allows for conditional bean registration based on custom logic.
Usage: Annotate configuration classes or beans to conditionally register them based on custom conditions.
Example:
@Configuration
@Conditional(MyCondition.class)
public class MyConfig {
// Configuration
}
@Import
Description: Imports additional configuration classes. It allows for modular configuration by importing other configuration classes.
Usage: Annotate configuration classes to include other configuration classes.
Example:
@Configuration
@Import({ConfigA.class, ConfigB.class})
public class MainConfig {
// Main configuration
}
@ImportResource
Description: Imports XML-based Spring configurations. It allows for loading XML configuration files into the application context.
Usage: Annotate configuration classes to include XML-based configuration files.
Example:
@Configuration
@ImportResource("classpath:config.xml")
public class AppConfig {
// Configuration
}
Auto-Configuration
Spring Boot's auto-configuration is one of its key features, designed to simplify the development process by automatically configuring Spring applications based on the dependencies and settings found on the classpath. Here’s a detailed look at what auto-configuration is and how it works:
1. Introduction to Auto-Configuration
Auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added. For example, if HSQLDB is on your classpath and you have not manually configured any database connection beans, then we will auto-configure an in-memory database.
2. How Auto-Configuration Works
Classpath Detection: Spring Boot looks at the libraries on the classpath. Depending on the libraries present, it tries to guess the required configurations.
Conditional Beans: Auto-configuration is achieved using
@Conditional
annotations. These annotations check for the presence of specific classes or beans before creating new beans.META-INF/spring.factories: Spring Boot uses the
spring.factories
file located inMETA-INF
to list all the auto-configuration classes that should be considered.
3. Common Auto-Configuration Examples
Here are a few common examples of what Spring Boot can automatically configure:
DataSource: If H2, HSQLDB, or Derby is present in your classpath, Spring Boot automatically configures an in-memory database.
JPA: If Hibernate is present, Spring Boot will automatically configure a
LocalContainerEntityManagerFactoryBean
and aJpaTransactionManager
.Web Applications: If you have
spring-boot-starter-web
on your classpath, Spring Boot will auto-configure Tomcat, Jackson, and a basic error handling mechanism.
4. Disabling Specific Auto-Configuration
You can disable specific auto-configuration classes by using the spring.autoconfigure.exclude
property.
Example:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Or, you can use the @SpringBootApplication
annotation’s exclude attribute.
Example:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
5. Customizing Auto-Configuration
While auto-configuration works out of the box, you often need to customize some aspects.
Application Properties: Use
application.properties
orapplication.yml
to set configuration properties.Custom Bean Definitions: Define custom beans to override or complement the auto-configuration beans.
6. Creating Your Own Auto-Configuration
You can create custom auto-configuration for your own libraries or applications.
Steps to Create Custom Auto-Configuration:
Create the Configuration Class: Annotate your class with
@Configuration
and@ConditionalOnClass
or other@Conditional
annotations.@Configuration @ConditionalOnClass(DataSource.class) public class MyDataSourceAutoConfiguration { @Bean @ConditionalOnMissingBean public DataSource dataSource() { return new HikariDataSource(); } }
Register Your Configuration: Create a file named
spring.factories
inMETA-INF
and register your configuration class.org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.MyDataSourceAutoConfiguration
7. Debugging Auto-Configuration
Spring Boot provides several ways to see what configurations are being applied.
Enable Debug Logging: Set the
debug
property totrue
in yourapplication.properties
.debug=true
Actuator Endpoint: Use the
actuator
endpoint/actuator/conditions
to see a detailed report of what configurations were applied and why.
8. Using @EnableAutoConfiguration
The @EnableAutoConfiguration
annotation is a core part of Spring Boot. It’s typically used alongside @SpringBootApplication
.
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@SpringBootApplication
is a combination of three annotations:
@Configuration
: Indicates that the class can be used by the Spring IoC container as a source of bean definitions.@EnableAutoConfiguration
: Enables Spring Boot’s auto-configuration mechanism.@ComponentScan
: Enables component scanning so that web controllers and other components you create will be automatically discovered and registered as beans in the Spring application context.
Spring Boot Profiles
Spring Boot profiles provide a way to segregate parts of your application configuration and make it only available in certain environments. This is particularly useful for managing different configurations for development, testing, production, and other environments.
1. Introduction to Profiles
Profiles in Spring Boot allow you to define different sets of configuration properties and beans that are active only in specific environments. For example, you might have different database configurations for development and production environments.
2. Defining Profiles
You can define profiles in your application.properties
or application.yml
files. Each profile-specific file contains configuration properties for that profile.
Example:
# application.properties
spring.profiles.active=dev
# application-dev.properties
spring.datasource.url=jdbc:h2:mem:devdb
spring.jpa.hibernate.ddl-auto=create-drop
# application-prod.properties
spring.datasource.url=jdbc:mysql://prod-db-url:3306/proddb
spring.jpa.hibernate.ddl-auto=update
In the example above:
The default profile is set to
dev
.When the
dev
profile is active, Spring Boot uses theapplication-dev.properties
file for configuration.When the
prod
profile is active, Spring Boot uses theapplication-prod.properties
file for configuration.
3. Activating Profiles
Profiles can be activated in several ways:
Using application properties: As shown above with
spring.profiles.active
.Command-line arguments: You can pass the active profile as a command-line argument when starting your application.
java -jar myapp.jar --spring.profiles.active=prod
Environment variables: Set the
SPRING_PROFILES_ACTIVE
environment variable.export SPRING_PROFILES_ACTIVE=prod
Programmatically: Set the active profile in your application code.
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(MyApplication.class); app.setAdditionalProfiles("prod"); app.run(args); } }
4. Profile-Specific Beans
You can also define beans that are only loaded in specific profiles using the @Profile
annotation.
Example:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class DataSourceConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return new HikariDataSource(); // Configure dev data source
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
return new HikariDataSource(); // Configure prod data source
}
}
5. Multiple Profiles
You can activate multiple profiles at once by separating them with a comma.
Example:
spring.profiles.active=dev,local
In this case, properties from both application-dev.properties
and application-local.properties
will be loaded.
6. Default Profile
Spring Boot uses the default
profile when no other profile is explicitly activated. You can define properties and beans for the default profile by not specifying a profile at all.
7. Testing with Profiles
Spring Boot also supports using profiles in tests. You can specify which profile to use for a test using the @ActiveProfiles
annotation.
Example:
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles("test")
public class MyServiceTest {
@Test
public void testSomething() {
// Test code
}
}
8. Merging Properties
Properties from multiple active profiles are merged. If a property is defined in more than one profile, the last one wins.
Example:
# application.properties
logging.level.root=INFO
# application-dev.properties
logging.level.root=DEBUG
# application-prod.properties
logging.level.root=ERROR
If both dev
and prod
profiles are active, the value from application-prod.properties
will override the others.
Configuration in Spring Boot
Externalised Configuration
Spring Boot allows you to externalise your configuration so you can work with the same application code in different environments. The application.properties
or application.yml
file is used to define configuration properties.
Example application.properties
:
server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root
You can also use environment variables, command-line arguments, and other sources to externalize configuration.
Configuration Properties
Spring Boot simplifies the configuration of applications, allowing developers to focus more on writing business logic rather than dealing with boilerplate code and complex setup. Here’s a detailed overview of configuration in Spring Boot:
1. Externalized Configuration
Spring Boot allows you to externalize your configuration so you can work with the same application code in different environments. This is done through properties files, YAML files, environment variables, and command-line arguments.
Properties and YAML Files
-
server.port=8081 spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=root spring.datasource.password=password
application.yml:
server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: root password: password
Environment Variables
You can set environment variables to configure Spring Boot applications:
export SERVER_PORT=8081
export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/mydb
export SPRING_DATASOURCE_USERNAME=root
export SPRING_DATASOURCE_PASSWORD=password
Command-Line Arguments
You can pass properties as command-line arguments:
java -jar myapp.jar --server.port=8081 --spring.datasource.url=jdbc:mysql://localhost:3306/mydb
2. Configuration Properties
Spring Boot provides the @ConfigurationProperties
annotation to map external properties to Java objects.
Example:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "mail")
public class MailProperties {
private String host;
private int port;
private String from;
// Getters and setters
}
In application.properties
or application.yml
:
mail.host=smtp.example.com
mail.port=587
mail.from=noreply@example.com
mail:
host: smtp.example.com
port: 587
from: noreply@example.com
3. Profile-Specific Configuration
Profiles allow you to define different configurations for different environments. You can create profile-specific properties files or YAML files.
Activate a profile by setting spring.profiles.active
:
spring.profiles.active=dev
4. Type-Safe Configuration
Spring Boot’s @ConfigurationProperties
support type-safe configuration by binding properties to POJOs. This makes it easier to manage and validate configurations.
Example:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private String description;
// Getters and setters
}
5. Default Property Values
You can specify default values for properties in the configuration classes.
Example:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name = "MyApp";
private String description = "Default description";
// Getters and setters
}
6. Custom Configuration Properties
You can create custom properties and use them in your Spring Boot application.
Example:
Create a configuration properties class:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "custom") public class CustomProperties { private String property1; private int property2; // Getters and setters }
Define properties in
application.properties
:custom.property1=value1 custom.property2=123
7. Property Sources
Spring Boot supports multiple property sources, including:
application.properties
andapplication.yml
Environment variables
Command-line arguments
Custom property sources (e.g., database, cloud configuration services)
8. Spring Environment Abstraction
Spring Boot provides the Environment
abstraction to access and manipulate property sources.
Example:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Autowired
private Environment env;
public void printProperty() {
System.out.println(env.getProperty("custom.property1"));
}
}
9. Configuration Classes
Spring Boot allows you to use Java-based configuration by creating configuration classes annotated with @Configuration
.
Example:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
return new MyBean();
}
}
10. Conditional Configuration
Spring Boot provides several @Conditional
annotations to conditionally load beans based on the presence of certain conditions.
Example:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
@Conditional(MyCondition.class)
public MyBean myBean() {
return new MyBean();
}
}
Building RESTful Web Services
RESTful web services, or REST APIs, are web services that follow the REST architectural style, providing interoperability between computer systems on the internet. With Spring Boot, building RESTful web services becomes straightforward thanks to its auto-configuration, starter dependencies, and extensive annotations.
Key Concepts of REST
Resources: In REST, resources are objects or representations of information that are exposed through an API. Each resource is identified by a URI.
HTTP Methods: The common HTTP methods used in RESTful services include:
GET
: Retrieve a resource.POST
: Create a new resource.PUT
: Update an existing resource.DELETE
: Delete a resource.PATCH
: Partially update a resource.
Setting Up Spring Boot for RESTful Web Services
To get started with a Spring Boot project for RESTful web services, you need to include the necessary dependencies. Typically, you would include spring-boot-starter-web
in your pom.xml
or build.gradle
.
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Gradle
implementation 'org.springframework.boot:spring-boot-starter-web'
Creating a RESTful Controller
A RESTful controller in Spring Boot is created using the @RestController
annotation. This annotation combines @Controller
and @ResponseBody
, eliminating the need to annotate each method with @ResponseBody
.
Example:
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
private List<User> users = new ArrayList<>();
@GetMapping
public List<User> getAllUsers() {
return users;
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return users.stream().filter(user -> user.getId().equals(id)).findFirst().orElse(null);
}
@PostMapping
public User createUser(@RequestBody User user) {
users.add(user);
return user;
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User updatedUser) {
User user = users.stream().filter(u -> u.getId().equals(id)).findFirst().orElse(null);
if (user != null) {
user.setName(updatedUser.getName());
user.setEmail(updatedUser.getEmail());
}
return user;
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
users.removeIf(user -> user.getId().equals(id));
}
}
Handling HTTP Methods
@GetMapping
Maps HTTP GET
requests onto specific handler methods.
@PostMapping
Maps HTTP POST
requests onto specific handler methods.
@PutMapping
Maps HTTP PUT
requests onto specific handler methods.
@DeleteMapping
Maps HTTP DELETE
requests onto specific handler methods.
@PatchMapping
Maps HTTP PATCH
requests onto specific handler methods.
Request and Response Bodies
Spring Boot simplifies the process of handling request and response bodies using the @RequestBody
and @ResponseBody
annotations.
@RequestBody: Used to map the body of the HTTP request to an object.
@ResponseBody: Used to map the return value of the method to the HTTP response body.
Exception Handling
Spring Boot provides a way to handle exceptions in a RESTful service using @ControllerAdvice
and @ExceptionHandler
.
Example:
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleResourceNotFoundException(ResourceNotFoundException ex) {
return ex.getMessage();
}
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleGenericException(Exception ex) {
return ex.getMessage();
}
}
Validation
Spring Boot integrates with the Java Bean Validation API to validate incoming request data.
Example:
import javax.validation.constraints.*;
public class User {
private Long id;
@NotBlank(message = "Name is mandatory")
private String name;
@Email(message = "Email should be valid")
private String email;
// Getters and setters
}
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public User createUser(@Validated @RequestBody User user) {
// Handle user creation
return user;
}
}
HATEOAS (Hypermedia as the Engine of Application State)
Spring Boot supports HATEOAS, which helps create more discoverable REST APIs by including links in responses.
Example:
import org.springframework.hateoas.*;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public EntityModel<User> getUserById(@PathVariable Long id) {
User user = // fetch user;
EntityModel<User> resource = EntityModel.of(user);
resource.add(Link.of("/api/users/" + id).withSelfRel());
return resource;
}
}
Security
Spring Boot provides comprehensive support for securing RESTful web services using Spring Security.
Example:
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/api/users/**").authenticated()
.and()
.httpBasic();
return http.build();
}
}
Testing RESTful Web Services
Spring Boot provides several utilities to test RESTful services, such as MockMvc
.
Example:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void shouldReturnAllUsers() throws Exception {
mockMvc.perform(get("/api/users"))
.andExpect(status().isOk());
}
@Test
public void shouldCreateUser() throws Exception {
String userJson = "{\"name\": \"John\", \"email\": \"john@example.com\"}";
mockMvc.perform(post("/api/users")
.contentType("application/json")
.content(userJson))
.andExpect(status().isOk());
}
}
Conclusion
Spring Boot is a powerful and versatile framework that significantly simplifies the development of Java applications. By leveraging the Spring Framework, Spring Boot allows developers to create stand-alone, production-grade applications with minimal configuration. Its key features, such as auto-configuration, starter dependencies, and extensive annotations, enable rapid development and reduce boilerplate code.
Spring Boot's support for microservices architecture, embedded servers, and production-ready features make it an ideal choice for modern application development. The framework's emphasis on "convention over configuration" ensures that developers can focus on writing business logic rather than dealing with complex setup and configuration.
Whether you are building RESTful web services, integrating with databases, or implementing security, Spring Boot provides a comprehensive set of tools and annotations to streamline the development process. Its robust ecosystem, including Spring Boot Initializr, makes it easy to get started and quickly build scalable and maintainable applications.
By understanding the core concepts, annotations, and features of Spring Boot, developers can harness its full potential to create efficient and high-quality Java applications. Whether you are a beginner or an experienced developer, Spring Boot offers a seamless and productive development experience, making it a valuable addition to your toolkit.