skip to Main Content

I have developed a REST end-point in Springboot that takes a String ID and responds with a ModelAndView. This end-point is marked with @Cacheable annotation. Now there are two things that can happen at the given end-point.

Case 1: The request ID exists in the DB and yields a URL to which redirection needs to happen. In this case, response should be cached so that upon consecutive requests of the same ID, the result can be served from Cache

Case 2: The requested ID doesn’t exist in the DB and thus redirection should happen to a specific URL and no caching should be done in this scenario.

So below is my method

@GetMapping("{id}")
    @Cacheable(value = "url-single", key = "#id", unless = "#result.view!="redirect:/notfound"")
    public ModelAndView redirect(@PathVariable("id") String id, ServletRequest servletRequest,
            ServletResponse servletResponse) {
        HttpServletRequest request = HttpServletRequest.class.cast(servletRequest);
        LOG.info("Redirection request from: {} for Short URL Key: {}", request.getRemoteAddr(), id);
        try {
            Optional<String> originalUrlOptional = urlManagerService.retrieveOriginalUrl(id);
            if (originalUrlOptional.isPresent() && !StringUtils.isEmpty(originalUrlOptional.get())) {
                LOG.info("Found Original URL: {} for Short URL Key: {}", originalUrlOptional.get(), id);
                return new ModelAndView("redirect:https://" + originalUrlOptional.get());
            }

        } catch (NoSuchElementException e) {
            LOG.error("Error while redirecting: {}", e.getMessage(), e);
        }
        return new ModelAndView("redirect:/notfound");
    }

If I understand it correctly from here, the keyword unless in @Cacheable applies to the return type and in order to access any particular member variable of the return type object, we have to refer to it as #result.attributeName <comparison> <value>.

So why isn’t anything being stored in my Redis cache? If I remove the unless condition, everything gets stored. Is the condition not correct?

2

Answers


  1. Chosen as BEST ANSWER

    I found where I was going wrong after playing with the unless conditional keyword for awhile. The #result inside the double quotes (") of the unless keyword is literally the object to returned. What that means is that, you can call whatever method can be called on that object.

    The statement "#result.view=="redirect:/notfound"" was failing because the object didn't expose any member variable called view. Using the expression unless = "#result.getViewName().equals("redirect:/notfound")" actually did the trick because there was a method getViewName() on the object that returned String and calling equals() on it did the actual comparison.

    I guess I got stuck here because I wasn't not familiar with Spring Expression Language or SpEL


  2. I have been looking at your unless statement:

    unless = "#result.view!="redirect:/notfound""
    

    so this means that it WONT be cached if the result.view IS NOT redirect:/notfound.

    My assumption is that you want to cache it, except when redirect:/notfound.
    There is a “double negative” here.

    So you probably should use:

    unless = "#result.view=="redirect:/notfound""
    

    (so use ‘==’ instead of ‘!=’)

    Let me know if this works!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search