Description
In my Spring Boot 3.4.0 based application, I have an @Aspect
named TenantServiceAspect
that intercepts repository method calls to apply multi-tenancy filters using Hibernate filters.
This aspect works perfectly fine in Spring Boot 3.3.10.
However, during load testing, sometimes when the application is restarted under heavy load, the beforeExecution()
method of the aspect is not triggered for certain repository calls, especially this one
The problem is not due to the load test. Since the load test constantly tries to make a request while the project is closed, when I restart the project, it probably causes this error because the request comes when the Spring Boot project is not fully ready.
Spring Boot version: 3.4.0
Java version: 21
Batch rest service
@RestController
@RequiredArgsConstructor
@RequestMapping("batch")
public class BatchService {
private final BatchBusinessService batchBusinessService;
@GetMapping(value = "/findBatchByCode", produces = {MediaType.APPLICATION_JSON_VALUE})
ResponseEntity<ServiceResponse<BatchDto>> findBatchByCode(@RequestParam("code") String code) {
return buildResponseEntity(batchBusinessService.findBatchByCode(code));
};
}
BatchBusinessService class
package com.example.batch.service;
import com.example.batch.data.domain.Batch;
import com.example.batch.data.dto.BatchDto;
import com.example.batch.data.repository.BatchRepository;
import com.example.batch.mapper.BatchMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class BatchBusinessService {
private final BatchRepository batchRepository;
private final BatchMapper mapper;
public BatchDto findBatchByCode(String code) {
Batch batch = batchRepository.findByCode(code).orElse(null);
return mapper.toDto(batch);
}
}
BatchRepository interface
package com.example.batch.data.repository;
import com.example.batch.data.domain.Batch;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface BatchRepository extends JpaRepository<Batch, Long>, JpaSpecificationExecutor<Batch> {
Optional<Batch> findByCode(String code);
}
Aspect class
package com.example.framework.multitenancy.aspect;
import com.example.logger.LogFactory;
import com.example.logger.Logger;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class TenantServiceAspect {
private static final Logger LOGGER = LogFactory.getLogger(TenantServiceAspect.class);
@PersistenceContext
public EntityManager entityManager;
public TenantServiceAspect() {
}
@Pointcut("execution(* org.springframework.data.jpa.repository.JpaRepository.*(..))")
void isRepository() {
}
@Pointcut("execution(public * com.example..*.repository..*(..))")
void isCustomRepository() {
}
@Before("(isCustomRepository() || isRepository())")
public void beforeExecution(JoinPoint joinPoint) {
LOGGER.warn("TenantServiceAspect triggered for method: {}", joinPoint.getSignature());
Filter filter = ((Session)this.entityManager.unwrap(Session.class)).enableFilter("companyFilter").setParameter("companyId", 1L);
filter.validate();
}
}
Note: While investigating the root cause, I noticed something strange in Spring Boot's managed dependencies:
- Spring Boot 3.3.10 uses
aspectjweaver
version 1.9.23 - Spring Boot 3.4.0+ (including 3.4.3) uses
aspectjweaver
version 1.9.22.1
While I haven’t confirmed the exact root cause yet, I’ve noticed that starting from Spring Boot 3.4.0, the spring-boot-starter-data-jpa no longer includes the spring-boot-starter-aop dependency by default:
Release Note:
“Remove spring-boot-starter-aop dependency from spring-boot-starter-data-jpa and spring-boot-starter-integration”
spring-projects/spring-boot#42934
I’m wondering if this change might somehow be related to the issue I'm facing — specifically, that sometimes my @aspect (TenantServiceAspect) does not get triggered in version 3.4.0, even though it works fine in 3.3.10.
It’s possible that under some conditions (e.g., app restarts, load), the absence of AOP support could lead to such inconsistent behavior.
Just sharing this in case it helps identify the root cause or helps someone else running into similar issues after upgrading to 3.4.0.
Intellij IDEA Profiler Fail and Successfull Output