Skip to content

Aspect Not Triggered After Restart in Spring Boot 3.4.x (But Works in 3.3.10) #34735

Closed
@zoroglu

Description

@zoroglu

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

3.3.10
Image

3.4.0
Image

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

Image

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: feedback-providedFeedback has been providedtype: regressionA bug that is also a regression

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions