1

I am getting below error when I try to use @Async annotation.

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.

Code:

@Async
@Override
@Transactional
public void triggerEmailCommunication(List<String> eventCode, Integer authorizationId, Integer claimId,
        boolean callMethod) {
    Map<String, Object> emailBody = new HashMap<>();
    try {

        if (callMethod) {
            LOGGER.info("Communication async flow triggerEmailCommunication method starts.");
            emailBody = emailBodyObject(authorizationId, claimId, eventCode);
  }


private Map<String, Object> emailBodyObject(Integer authorizationId, Integer claimId, List<String> eventCode)
        throws CareBusinessServiceException {
    LOGGER.info("EmailBodyObject method starts.");
    Map<String, Object> emailBody = new HashMap<String, Object>();
    EmailClaimDetailsVO emailClaimDetails = new EmailClaimDetailsVO();
    ClaimAuthorizationVO claimAuthVO = new ClaimAuthorizationVO();
    Claim claim = new Claim();
    Authorization authorization = new Authorization();
    List<String> rejectReasonList = new ArrayList<>();
    Provider provider = new Provider();
    String providerName = null;
    String claimIntimationNbr = null;
    String authorizationNbr = null;
    SimpleDateFormat formatter = new SimpleDateFormat(AmhiConstants.DATE_FORMAT_DD_MM_YYYY);
    try {
        Integer claimIntimationId = null;
        if (null != claimId) {
            claim = enableBusinessService.retrieveClaimDetails(claimId);
     } catch(Exception e) {
     }
}

DAO Layer

@Override
public Claim retrieveClaimIdRecord(Integer claimId) {
    CriteriaBuilder builder = manager.getCriteriaBuilder();
    CriteriaQuery<Claim> criteriaQuery = builder.createQuery(Claim.class);
    Root<Claim> root = criteriaQuery.from(Claim.class);
    ArrayList<Predicate> conditions = new ArrayList<>();
    conditions.add(builder.equal(root.get(Claim_.claimId), claimId));
    criteriaQuery.select(root).where(conditions.toArray(new Predicate[] {}));
    javax.persistence.Query query = manager.createQuery(criteriaQuery);
    List<Claim> claims = query.getResultList();
    if(CollectionUtils.isNotEmpty(claims)){
        return claims.get(0);
    }
    return new Claim();
}

The value is getting retrieved from DB. But I am getting above exception as mentioned.

bharathi
  • 6,019
  • 23
  • 90
  • 152

1 Answers1

0

In my case it happened when I created a bean at request level and tried to access it from another thread created using @Async annotation. The bean information was stored in the thread local of the original thread only.

Are you using something created and stored in the thread local of the base thread in the function or subsequent functions after @Async notification?

@Async creates another thread but doesn't copy the thread local of the original thread which causes the issue.

See this - https://jira.spring.io/browse/SPR-6873

  • Is there any solution for for the above issue. – bharathi Sep 06 '18 at 07:07
  • Although I have never tried it but, you'll have to create a custom ThreadPoolTaskExecutor for your application. See this - https://stackoverflow.com/questions/23732089/how-to-enable-request-scope-in-async-task-executor#33337838 And if there are not that many objects, you can pass them around your code. – Kush Khandelwal Sep 07 '18 at 08:10