1

I have an Api endpoint with Spring 5 as @RestController and I want to specify the Cache-Control for all endpoints at once (via a Config or an Annotation,...).

Currently I do this on every single method. I also had to use ResponseEntity to set the Cache-Control which bloats the code even more.

@RestController
@RequestMapping("/api")
public class MyApi {

    @PostMapping("/search")
    public ResponseEntity<SearchResultDto> search(SearchDto searchDto) {
        // ...
        return ResponseEntity.ok()
                .cacheControl(CacheControl.maxAge(20, TimeUnit.SECONDS))
                .body(searchResultDto);
    }

    @GetMapping("/get")
    public ResponseEntity<EntityDto> get(Long id) {
        // ...
        return ResponseEntity.ok()
                .cacheControl(CacheControl.maxAge(20, TimeUnit.SECONDS))
                .body(entityDto);
    }

    // ... more methods

}
  • I tried Aspects, but it is not possible to alter the http headers after they are created.
@Aspect
@Component
public class CacheAspect {

    @Pointcut("within(io.company.MyApi)")
    public void apiMethods() {
    }

    @Around("apiMethods()")
    public Object addCacheControlOnResponseEntity(ProceedingJoinPoint pjp) throws Throwable {
        Object retval = pjp.proceed();

        if (retval instanceof ResponseEntity) {
            ((ResponseEntity) retval).getHeaders().setCacheControl(CacheControl.maxAge(15, TimeUnit.SECONDS));
            // exception is thrown, because map can not be modified anymore
        }

        return retval;
    }
}
  • I tried interceptors (HandlerInterceptor), but here it is the same problem, that the http headers can not be modified afterwards.
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                response.setHeader(HttpHeaders.CACHE_CONTROL, CacheControl.maxAge(2, TimeUnit.SECONDS).getHeaderValue());
                // header does not get modified
            }

            @Override
            public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
                response.setHeader(HttpHeaders.CACHE_CONTROL, CacheControl.maxAge(2, TimeUnit.SECONDS).getHeaderValue());
                // header does not get modified
            }
        });
    }
}
  • I tried to add a resource handler (ResourceHandler) (for usually static content) and set the caching strategy for /api/**, but it was not applied.
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/api/**")
                .setCacheControl(CacheControl.maxAge(10, TimeUnit.SECONDS));
        // didn't had any effect
    }
}

... I am out of ideas

What can I do to write less duplicate/boilerplate code?

1
  • Using Interceptor looks like a good solution. Maybe you could try changing the response in the preHandle, but I am not sure it would suit your need. Else, you should wrap the response as suggested in this post: stackoverflow.com/questions/30702970/… Commented May 2, 2018 at 8:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.