Home Blog Page 84

Caching with Spring Boot (@Cacheable)

0
java spring boot course
java spring boot course

Table of Contents

  1. Introduction to Caching in Spring Boot
  2. Benefits of Caching
  3. Setting Up Caching in Spring Boot
  4. Understanding @Cacheable Annotation
  5. Caching Providers in Spring Boot
  6. Cacheable Methods and Cache Names
  7. Cache Eviction and Expiration
  8. Advanced Caching Features (e.g., @CachePut, @CacheEvict)
  9. Troubleshooting Caching Issues
  10. Summary

1. Introduction to Caching in Spring Boot

Caching is an essential concept in application performance optimization. It allows you to store frequently accessed data in memory, thereby reducing the load on underlying resources such as databases or external services. In Spring Boot, caching can be easily enabled and configured using Spring’s powerful caching abstraction.

Spring provides a simple yet flexible mechanism for caching with annotations like @Cacheable, @CachePut, and @CacheEvict. This module will explore how to use these annotations and configure caching effectively in your Spring Boot application.


2. Benefits of Caching

  • Improved Performance: Reduces the need to fetch data repeatedly from a database or make external API calls by caching results.
  • Reduced Latency: Fetching data from memory is much faster than querying a database or external service.
  • Scalability: Cache helps to reduce the load on critical resources, making your application more scalable.
  • Cost-effective: For applications relying heavily on external APIs or databases, caching can reduce operational costs related to database and network calls.

3. Setting Up Caching in Spring Boot

To enable caching in Spring Boot, you need to add the necessary dependencies and configurations.

Add Caching Dependency

If you’re using Maven, add the following dependency:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

For Gradle, use:

implementation 'org.springframework.boot:spring-boot-starter-cache'

Enable Caching in Your Spring Boot Application

You need to enable caching in your Spring Boot application by adding the @EnableCaching annotation to one of your configuration classes.

@Configuration
@EnableCaching
public class CacheConfig {
}

This annotation enables Spring’s caching support across the application.


4. Understanding @Cacheable Annotation

The @Cacheable annotation tells Spring to cache the result of a method based on its arguments. If the method is called again with the same arguments, Spring will return the cached result rather than executing the method.

Example of @Cacheable

@Service
public class ProductService {

@Cacheable(value = "products", key = "#id")
public Product getProductById(Long id) {
simulateSlowService();
return new Product(id, "Product Name");
}

private void simulateSlowService() {
try {
Thread.sleep(3000); // Simulate a delay
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

In this example:

  • The @Cacheable annotation tells Spring to cache the result of getProductById.
  • The value parameter is the name of the cache.
  • The key parameter specifies the cache key, which in this case is the id of the product.

5. Caching Providers in Spring Boot

Spring Boot supports several caching providers, including:

  • Simple in-memory cache: Default caching provider (using ConcurrentMapCache).
  • EhCache: Popular open-source caching solution.
  • Redis: A fast, open-source key-value store.
  • Caffeine: High-performance, Java-based caching library.
  • Guava: Google’s caching library.

To use an external caching provider, you need to include the corresponding dependency and configure it in application.properties or application.yml.

Example: Using Redis for Caching

Add the Redis dependency:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Configure Redis in application.properties:

spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379

6. Cacheable Methods and Cache Names

In addition to basic method caching, Spring also allows you to specify cache names, expiration times, and conditional caching.

Cache Names

You can specify multiple cache names by providing an array for the value attribute:

@Cacheable(value = {"cache1", "cache2"}, key = "#id")
public Product getProductById(Long id) {
// Method logic
}

This will store the cached data in both cache1 and cache2.

Conditional Caching

You can control when to cache results based on method parameters or other conditions:

@Cacheable(value = "products", key = "#id", condition = "#id > 10")
public Product getProductById(Long id) {
// Method logic
}

Here, the cache will only be used if the id is greater than 10.


7. Cache Eviction and Expiration

Spring Boot supports cache eviction using the @CacheEvict annotation. This allows you to remove specific entries from the cache or clear the entire cache.

Example: Evicting Cache

@CacheEvict(value = "products", key = "#id")
public void deleteProduct(Long id) {
productRepository.deleteById(id);
}

This will remove the cached entry for the product with the specified id when the deleteProduct method is called.

Cache Expiration

To set cache expiration times, you typically configure this at the provider level. For example, in Redis or EhCache, you can set TTL (Time To Live) settings to automatically expire cached entries after a certain period.


8. Advanced Caching Features (e.g., @CachePut, @CacheEvict)

@CachePut

The @CachePut annotation is used to update the cache without interfering with the method execution. It forces the cache to be updated with the method’s result even if the method is executed.

@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
return productRepository.save(product);
}

Here, after saving the updated product, the cache is updated with the new value.

@CacheEvict (Advanced Use)

You can also evict the cache based on specific conditions like method execution or after a certain delay:

@CacheEvict(value = "products", allEntries = true)
public void clearCache() {
// Logic to clear the cache
}

This clears all entries from the products cache.


9. Troubleshooting Caching Issues

  • Cache not updating: Ensure that the cache manager is properly configured, and check if the @CachePut and @CacheEvict annotations are being used correctly.
  • Inconsistent cache values: Verify that the cache key generation logic (key attribute in annotations) is accurate.
  • Cache misses: This may occur if the cache is being cleared unexpectedly or if the cache expires too quickly.

10. Summary

Caching in Spring Boot can greatly improve the performance of your applications by reducing redundant operations. By leveraging annotations like @Cacheable, @CachePut, and @CacheEvict, you can easily manage your cache logic. Spring Boot’s flexible caching framework supports a variety of cache providers, making it suitable for different types of applications, from small to large-scale systems.

Spring Boot Admin and Health Endpoints

0
java spring boot course
java spring boot course

Table of Contents

  1. What is Spring Boot Admin?
  2. Why Use Spring Boot Admin?
  3. Setting Up Spring Boot Admin Server
  4. Registering Clients to the Admin Server
  5. Exploring Spring Boot Admin Dashboard
  6. Spring Boot Actuator Health Endpoints
  7. Custom Health Indicators
  8. Securing Spring Boot Admin
  9. Spring Boot Admin Notifications and Alerts
  10. Summary

1. What is Spring Boot Admin?

Spring Boot Admin is a community-driven project by Codecentric that provides a web-based UI for managing and monitoring Spring Boot applications. It leverages Spring Boot Actuator under the hood to gather metrics and system health data, presenting it in a centralized, visual format. It’s especially useful when you have multiple microservices running and need a single pane of glass to monitor them all.


2. Why Use Spring Boot Admin?

  • Monitor multiple Spring Boot applications in one dashboard
  • Visual representation of application metrics, logs, environment, and endpoints
  • Easily track application status and health
  • Customize health checks and alerts
  • Centralize management of log levels, threads, and JVM state

3. Setting Up Spring Boot Admin Server

To set up a Spring Boot Admin Server:

Add Dependencies

In your Admin Server’s pom.xml:

<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>3.1.8</version> <!-- Use compatible version -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Enable Admin Server

@SpringBootApplication
@EnableAdminServer
public class AdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class, args);
}
}

Basic Config in application.properties

server.port=8080
spring.application.name=admin-server

4. Registering Clients to the Admin Server

On each Spring Boot application you want to monitor:

Add Client Dependencies

<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>3.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Configure Application Properties

spring.application.name=my-app
management.endpoints.web.exposure.include=*
spring.boot.admin.client.url=http://localhost:8080

Ensure that the actuator endpoints are exposed and accessible.


5. Exploring Spring Boot Admin Dashboard

Once everything is configured:

  • Visit http://localhost:8080 (Admin Server UI)
  • You’ll see the registered clients with their:
    • Health
    • Metrics
    • Beans
    • Environment variables
    • JVM memory, threads, GC info
    • Loggers and configuration
    • Custom endpoints

Each client is continuously monitored and updated in real time.


6. Spring Boot Actuator Health Endpoints

Spring Boot Admin uses the actuator’s /health endpoint to determine if an application is up or down.

By default, the /actuator/health shows a simple “UP” or “DOWN”. You can show detailed health information by setting:

management.endpoint.health.show-details=always

Default Health Indicators

Spring Boot includes indicators for:

  • Disk space
  • Database
  • Redis, MongoDB
  • Ping
  • Custom indicators

7. Custom Health Indicators

You can define your own logic for health reporting:

@Component
public class MyCustomHealthIndicator implements HealthIndicator {

@Override
public Health health() {
// Your custom logic
boolean isHealthy = checkService();
if (isHealthy) {
return Health.up().withDetail("customService", "Available").build();
} else {
return Health.down().withDetail("customService", "Unavailable").build();
}
}

private boolean checkService() {
// Simulate a service check
return true;
}
}

This will appear under the /actuator/health and in the Spring Boot Admin dashboard.


8. Securing Spring Boot Admin

You can secure the Admin UI and client registration using Spring Security:

Security Configuration (Server)

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/assets/**", "/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
}

You can also secure the actuator endpoints on each client.


9. Spring Boot Admin Notifications and Alerts

Spring Boot Admin supports notifications via:

  • Email
  • Slack
  • PagerDuty
  • HipChat
  • OpsGenie
  • Let’s you define thresholds and alerting rules

To enable Slack integration, add:

<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-notifier-slack</artifactId>
</dependency>

And configure:

spring.boot.admin.notify.slack.enabled=true
spring.boot.admin.notify.slack.webhook-url=https://hooks.slack.com/services/...

10. Summary

Spring Boot Admin combined with Actuator provides a comprehensive, real-time dashboard for managing and monitoring Spring Boot applications. It scales well for microservices, enhances observability, and supports both out-of-the-box and custom metrics and health indicators. It also improves operational response time by enabling secure, centralized monitoring with real-time notifications.

Spring Boot Actuator for Monitoring

0
java spring boot course
java spring boot course

Table of Contents

  1. What is Spring Boot Actuator?
  2. Why Use Actuator?
  3. Adding Actuator to Your Project
  4. Exposing Actuator Endpoints
  5. Commonly Used Endpoints
  6. Customizing Endpoint Exposure
  7. Securing Actuator Endpoints
  8. Actuator and Health Monitoring
  9. Metrics and Integration with Prometheus/Grafana
  10. Creating Custom Actuator Endpoints
  11. Summary

1. What is Spring Boot Actuator?

Spring Boot Actuator is a powerful feature of the Spring Boot ecosystem that enables production-ready features for monitoring and managing applications. It exposes various REST endpoints to monitor the internal state and behavior of your application without changing the code logic.


2. Why Use Actuator?

  • Health Checks – Monitor application readiness and liveness.
  • Metrics – View memory usage, CPU load, and JVM statistics.
  • Audit Events – Track important system events.
  • Thread Dumps – Analyze running threads.
  • Environment Info – View environment variables, active profiles, etc.
  • Integration – Easily integrate with Prometheus, Micrometer, and other monitoring tools.

3. Adding Actuator to Your Project

Add the Spring Boot Actuator dependency in your pom.xml:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Or if you’re using Gradle:

implementation 'org.springframework.boot:spring-boot-starter-actuator'

4. Exposing Actuator Endpoints

By default, only the /actuator/health and /actuator/info endpoints are exposed over HTTP. To expose all or specific endpoints, configure your application.properties or application.yml:

management.endpoints.web.exposure.include=*

Or selectively:

management.endpoints.web.exposure.include=health,info,metrics,env

5. Commonly Used Endpoints

EndpointDescription
/actuator/healthApplication health status
/actuator/infoApp info like version, build
/actuator/metricsDetailed metrics (JVM, CPU, etc.)
/actuator/envEnvironment variables
/actuator/beansList of all Spring beans
/actuator/loggersView/change logging levels
/actuator/mappingsShow request-to-handler mappings

To get a full list, visit /actuator after exposing endpoints.


6. Customizing Endpoint Exposure

You can include/exclude endpoints individually:

management.endpoints.web.exposure.include=health,metrics
management.endpoints.web.exposure.exclude=beans,env

To change the base path for all actuator endpoints:

management.endpoints.web.base-path=/management

7. Securing Actuator Endpoints

Actuator endpoints can expose sensitive application internals. Use Spring Security to restrict access:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/actuator/health", "/actuator/info").permitAll()
.antMatchers("/actuator/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic();
}
}

You can also use application.properties to enable HTTP Basic authentication.


8. Actuator and Health Monitoring

The /actuator/health endpoint provides insight into the application’s status. You can include detailed health info:

management.endpoint.health.show-details=always

Spring Boot integrates with various health indicators:

  • Database health
  • Disk space
  • Redis/Mongo/RabbitMQ connections
  • Custom health indicators (covered below)

Custom Health Indicator

@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// You can add logic here to check custom conditions
return Health.up().withDetail("customService", "Available").build();
}
}

9. Metrics and Integration with Prometheus/Grafana

Spring Boot integrates with Micrometer, which supports metrics exporting.

To use Prometheus:

<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

Expose the Prometheus endpoint:

management.endpoints.web.exposure.include=prometheus

Then access metrics at /actuator/prometheus and configure Prometheus to scrape it.


10. Creating Custom Actuator Endpoints

You can define your own actuator endpoints:

@Component
@Endpoint(id = "custom")
public class CustomEndpoint {

@ReadOperation
public Map<String, String> customEndpoint() {
return Map.of("status", "Custom actuator endpoint working");
}
}

The above creates an endpoint at /actuator/custom.


11. Summary

Spring Boot Actuator offers comprehensive monitoring and management capabilities for Spring Boot applications. By exposing standardized and custom endpoints, you gain real-time insights into application behavior, making it invaluable for debugging, observability, and DevOps automation.

JWT-Based Authentication (Stateless Auth) in Spring Boot

0
java spring boot course
java spring boot course

Table of Contents

  1. Introduction to JWT
  2. How JWT Works (Stateless Auth)
  3. Benefits of JWT in Spring Applications
  4. Generating JWT Tokens
  5. Validating JWT Tokens
  6. Creating a Custom Filter
  7. Configuring Spring Security for JWT
  8. Testing the Full Flow
  9. Best Practices
  10. Summary

1. Introduction to JWT

JSON Web Tokens (JWT) are a compact, URL-safe means of representing claims to be transferred between two parties. In the context of Spring Security, JWTs are used to authorize users in a stateless manner—no server-side session storage is required.

A JWT typically contains three parts:

  • Header: Type and signing algorithm.
  • Payload: User information and claims.
  • Signature: Verifies the token wasn’t tampered with.

2. How JWT Works (Stateless Auth)

In JWT-based stateless authentication:

  1. The user logs in with credentials.
  2. Server authenticates and returns a signed JWT token.
  3. The client stores the JWT (usually in localStorage or cookies).
  4. For each request, the client sends the token in the Authorization header.
  5. The server verifies the token and processes the request.

3. Benefits of JWT in Spring Applications

  • Stateless: No session storage on server.
  • Scalable: Ideal for distributed systems.
  • Self-contained: Carries user data and metadata.
  • Cross-platform: Can be used across languages and services.

4. Generating JWT Tokens

Use a utility class to generate tokens:

public class JwtUtil {
private final String SECRET_KEY = "your-secret";

public String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.claim("roles", userDetails.getAuthorities())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10 hrs
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}

5. Validating JWT Tokens

public boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}

You’ll also need methods like extractUsername(), extractExpiration() etc., using Jwts.parser().


6. Creating a Custom JWT Filter

This filter intercepts requests, extracts the JWT, and sets the security context.

public class JwtRequestFilter extends OncePerRequestFilter {

@Autowired
private JwtUtil jwtUtil;

@Autowired
private UserDetailsService userDetailsService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {

final String authHeader = request.getHeader("Authorization");

String username = null;
String jwt = null;

if (authHeader != null && authHeader.startsWith("Bearer ")) {
jwt = authHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

if (jwtUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

token.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

SecurityContextHolder.getContext().setAuthentication(token);
}
}

chain.doFilter(request, response);
}
}

7. Configuring Spring Security for JWT

Update your security configuration:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Autowired
private JwtRequestFilter jwtRequestFilter;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);

http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

return http.build();
}
}

8. Testing the Full Flow

  1. Authenticate:
    • POST to /authenticate with username and password.
    • Receive JWT token.
  2. Access Protected Resource:
    • Set header: Authorization: Bearer <token>
    • GET /api/protected – success if token is valid.

9. Best Practices

  • Always sign tokens with a strong secret or RSA keys.
  • Use HTTPS to secure tokens in transit.
  • Set short expiration times and refresh tokens.
  • Avoid storing JWTs in localStorage on browsers prone to XSS.
  • Use claim fields wisely—don’t overstuff JWTs.

10. Summary

JWT-based authentication provides a scalable, stateless solution for securing your Spring Boot APIs. It avoids session storage, making it ideal for RESTful microservices.

Key Concepts Covered:

  • What JWT is and how it works
  • How to generate, sign, and validate tokens
  • Creating a custom JWT filter
  • Securing endpoints using JWT

Creating Custom Spring Boot Starters

0
java spring boot course
java spring boot course

Table of Contents

  1. Introduction to Spring Boot Starters
  2. Why Create a Custom Starter?
  3. Anatomy of a Spring Boot Starter
  4. Creating the Starter Module
  5. Defining Auto-Configuration
  6. Using @Conditional Annotations
  7. Registering the Auto-Configuration Class
  8. Publishing Your Starter
  9. Using Your Starter in a Project
  10. Best Practices
  11. Summary

1. Introduction to Spring Boot Starters

Spring Boot starters are dependency descriptors that bundle together related libraries, configurations, and auto-configuration logic. For instance, when you add spring-boot-starter-web, it pulls in all dependencies needed to build a web application and configures them automatically.

A custom Spring Boot starter allows you to encapsulate common functionality (libraries, configurations, and auto-configs) and share it across multiple Spring Boot projects.


2. Why Create a Custom Starter?

Creating a custom starter is useful when:

  • You want to standardize configuration across microservices.
  • You repeatedly use the same set of dependencies and configuration classes.
  • You are developing an internal or third-party SDK with Spring Boot support.

3. Anatomy of a Spring Boot Starter

A typical custom starter project has two Maven modules:

  1. Autoconfigure Module – Contains the configuration logic.
  2. Starter Module – Brings in the autoconfigure module and defines the starter dependency.

4. Creating the Starter Module

Step 1: Set Up Two Maven Modules

  • my-custom-starter-autoconfigure
  • my-custom-starter

Directory structure:

my-custom-starter/
├── my-custom-starter/
│ └── pom.xml
├── my-custom-starter-autoconfigure/
│ └── pom.xml
└── pom.xml

5. Defining Auto-Configuration

In the my-custom-starter-autoconfigure module:

Add Required Dependencies

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

Create a Configuration Class

@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyServiceProperties.class)
public class MyServiceAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public MyService myService(MyServiceProperties properties) {
return new MyService(properties.getMessage());
}
}

Properties Class

@ConfigurationProperties("my.service")
public class MyServiceProperties {
private String message = "Hello from MyService";

public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}

6. Using @Conditional Annotations

Spring Boot’s conditional annotations make autoconfiguration smart:

  • @ConditionalOnClass: Only configure if class is present.
  • @ConditionalOnMissingBean: Only create bean if it’s not already defined.
  • @ConditionalOnProperty: Enable config based on property value.

Example:

@Bean
@ConditionalOnProperty(name = "my.service.enabled", havingValue = "true", matchIfMissing = true)
public MyService myService() {
return new MyService();
}

7. Registering the Auto-Configuration Class

You must register the auto-configuration class using the spring.factories file.

In:
src/main/resources/META-INF/spring.factories

Add:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MyServiceAutoConfiguration

8. Publishing Your Starter

Package both modules and publish to your internal or public Maven repository.

mvn clean install
# or publish to remote repo

9. Using Your Starter in a Project

Now you can add your starter in another project:

<dependency>
<groupId>com.example</groupId>
<artifactId>my-custom-starter</artifactId>
<version>1.0.0</version>
</dependency>

And optionally configure it in application.properties:

my.service.enabled=true
my.service.message=Hello from Custom Starter

10. Best Practices

  • Keep logic in the autoconfigure module; starter should be a thin wrapper.
  • Use appropriate @Conditional annotations to avoid conflicts.
  • Provide reasonable defaults in your properties classes.
  • Document available properties for users of your starter.

11. Summary

Creating a custom Spring Boot starter streamlines repetitive setup and promotes consistent configurations across your projects. By encapsulating dependencies, auto-configurations, and custom properties, you make your reusable functionality portable and production-ready.