Search code examples
javaspringspring-bootspring-web

Spring Boot App fails to register RequestContextListener


I'm creating simple REST controllers, for which in my spring boot app I have added the configuration for RequestContextListener

@Configuration
@WebListener
public class DataApiRequestContextListener extends RequestContextListener {

}

In the controller I try ot build location header for successful post request

@Async("webExecutor")
@PostMapping("/company")
public CompletableFuture<ResponseEntity<Object>> save(@RequestBody Company company) {

    Company savedCompany = companyRepository.save(company);

    URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
            .buildAndExpand(savedCompany.getId()).toUri();

    ResponseEntity<Object> response = ResponseEntity.created(location).build();
    LOGGER.debug("Reponse Status for POST Request is :: " + response.getStatusCodeValue());
    LOGGER.debug("Reponse Data for POST Request is :: " + response.getHeaders().getLocation().toString());
    return CompletableFuture.completedFuture(response);
}

I get the exception

java.lang.IllegalStateException: No current ServletRequestAttributes

when I'm trying to build the location URI using ServletUriComponentsBuilder at this line

URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                    .buildAndExpand(savedCompany.getId()).toUri();

Solution

  • Use fromRequestUri if using @async

    @Async("webExecutor")
    @PostMapping("/company")
    public CompletableFuture<ResponseEntity<Object>> save(HttpServletRequest request, @RequestBody Company company) {
    
        Company savedCompany = companyRepository.save(company);
    
        URI location = ServletUriComponentsBuilder.fromRequestUri(request).path("/{id}")
                    .buildAndExpand(savedOrganization.getId()).toUri();
    
        ResponseEntity<Object> response = ResponseEntity.created(location).build();
        LOGGER.debug("Reponse Status for POST Request is :: " + response.getStatusCodeValue());
        LOGGER.debug("Reponse Data for POST Request is :: " + response.getHeaders().getLocation().toString());
        return CompletableFuture.completedFuture(response);
    }
    

    OR without @async should work and return you location uri.

    @PostMapping("/company")
    public CompletableFuture<ResponseEntity<Object>> save(@RequestBody Company company) {
    
        Company savedCompany = companyRepository.save(company);
    
        URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(savedCompany.getId()).toUri();
    
        ResponseEntity<Object> response = ResponseEntity.created(location).build();
        LOGGER.debug("Reponse Status for POST Request is :: " + response.getStatusCodeValue());
        LOGGER.debug("Reponse Data for POST Request is :: " + response.getHeaders().getLocation().toString());
        return CompletableFuture.completedFuture(response);
    }