I have a hibernate filter defined on my entities which I am injecting using aspect for all repositories which implements my TenantableRepository.
The issue is that the filter is not getting injected in the repository calls executed within CompletetableFuture method. But filter is getting injected properly outside it. I understand that the threads are different but aspect is being called both the times though.
I want the filter to get enabled from all flows. API or async processes.
Here is the Aspect I have defined to work on all TenantableRepositories' methods starting with find.
@Aspect
@Component
@Slf4j
public class TenantFilterAspect {
@PersistenceContext
private EntityManager entityManager;
@Before("execution(* com.demo.repository.TenantableRepository+.find*(..))")
public void beforeFindOfTenantableRepository() {
log.info("Called aspect");
entityManager
.unwrap(Session.class)
.enableFilter(Tenantable.TENANT_FILTER_NAME)
.setParameter(Tenantable.TENANT_COLUMN, TenantContext.getTenantId());
}
}
I have a controller to test the flow. Here I am making 2 repository calls. One in main thread and one under async CompletetableFuture method.
import org.springframework.beans.factory.annotation.Autowired;
@RestController
@Slf4j
@RequestMapping(value = "/v1/api/test", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public class TestController {
@Autowired
MyEntityRepository myEntityRepository;
@RequestMapping(value = "/aysnc", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public @ResponseBody
ResponseEntity<APIResponse> testAsync(HttpServletRequest httpServletRequest) throws InterruptedException {
Optional<MyEntity> entity = myEntityRepository.findByFirstName("Firstname");
if(!entity.isEmpty()){
log.info("1. Main: found entity:{}",entity.get());
}
CompletableFuture.runAsync(this::callAsyncMethod);
return ResponseEntity.status(HttpStatus.OK)
.body("Ok");
}
public void callAsyncMethod() {
Optional<MyEntity> entity = myEntityRepository.findByFirstName("Firstname");
if(!entity.isEmpty()){
log.info("2. Async: found entity:{}",entity.get());
}
}
}
The issue is that the filter is not getting injected in the repo call under async CompletetableFuture method callAsyncMethod(). But filter is getting injected properly in first repo call before async method.
I understand that the threads are different but aspect is being called both the times. I get the log printed but the filter is still not enabled.
What am I doing wrong here?
TenantContext.getTenantIdis based on aThreadLocal. What do you think happens to the value bound to thread 1 when you execute in thread 2.@Transactionalservice method it would work as it would use a shared entitymanager. I suspect the same would happen if you setspring.jpa.open-in-view=falsein yourapplication.properties.