2

I use @RestResource in my Spring Data Rest web application. And I would like to custom 404 error of my RestResource.

I'm aware of ControlerAdvice, handler... BUT it doesn't work with RestResource.

I already tried a lot of things :

  • Set setThrowExceptionIfNoHandlerFound to true with a bean or in application.properties
  • Disable spring.resources.add-mappings=false in application.properties
  • Add basePackages or basePackageClass on ControllerAdvice
  • Extends RepositoryRestExceptionHandler (but I can't override it because method are package private)

My current source code is :

@RestResource(path="user")
public interface UserRepository extends Repository<User, Long> {

    User findById(Long id);

}

-

@EnableWebMvc
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ErrorHandlerController extends ResponseEntityExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    ResponseEntity<?> handleNotFound(ResourceNotFoundException ex) {
        ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, "Internal server error");
        return new ResponseEntity<>(apiError, apiError.getHttpStatus());
    }

}

Edit 1 (my question isn't a duplicate):

I also try to add a new RestControllerAdviceHandler like this (but it doesn't work) :

@RestControllerAdvice
public class RestControllerAdviceHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        return new ResponseEntity<>(" test ", HttpStatus.NOT_FOUND);
    }

}

Edit 2 (about spring framework source code):

After more research in spring source code I find the code below. It seems that if entity is not found, no exception is raised, RestResource just returned a new ResponseEntity>(HttpStatus.NOT_FOUND)). Maybe it's really impossible to intercept and customize the Not Found error with RestResource ?

/**
     * <code>GET /{repository}/{id}</code> - Returns a single entity.
     * 
     * @param resourceInformation
     * @param id
     * @return
     * @throws HttpRequestMethodNotSupportedException
     */
    @RequestMapping(value = BASE_MAPPING + "/{id}", method = RequestMethod.GET)
    public ResponseEntity<Resource<?>> getItemResource(RootResourceInformation resourceInformation,
            @BackendId Serializable id, final PersistentEntityResourceAssembler assembler, @RequestHeader HttpHeaders headers)
            throws HttpRequestMethodNotSupportedException {

        return getItemResource(resourceInformation, id).map(it -> {

            PersistentEntity<?, ?> entity = resourceInformation.getPersistentEntity();

            return resourceStatus.getStatusAndHeaders(headers, it, entity).toResponseEntity(//
                    () -> assembler.toFullResource(it));

        }).orElseGet(() -> new ResponseEntity<Resource<?>>(HttpStatus.NOT_FOUND));
    }
18
  • 1
    @chrylis I try to transform 404 response empty body in a structured json body. Any idea ? Commented Sep 6, 2018 at 14:47
  • 1
    @SupunWijerathne We have similar state, when Entity is not Found, we would like to tell Entity doesn't Exist as a blank 404 may not make much sense for all business purposes. Any suggestions? Commented Oct 4, 2018 at 14:41
  • 2
    @shivaspk There is no answer... So, I found a workaround... I create a component class extending org.springframework.web.filter.OncePerRequestFilter and I intercept all response where the body don't start with "{". So all request that are not json formatted. Then, I replace the body of response with a json. I combine request url and statusCode to find the errorMessage. It's not perfect at all but it works... Hope that helps. Commented Oct 4, 2018 at 15:08
  • 1
    Looks like it has been marked as a bug and hopefully addressed in future. jira.spring.io/browse/… Commented Oct 4, 2018 at 22:59
  • 1
    @J.Marciano Thanks for the information ! Do you check that your ResponseBodyAdvice is called on 404 ? I'm not sure. But if it's right, it's really interesting. I think that ResponseBodyAdvice is more high level than OncePerRequestFilter. Commented Oct 25, 2018 at 16:24

1 Answer 1

1

This is finally fixed in Spring Data REST's upcoming release 3.2.

A ResourceNotFoundException exception is thrown, which can now properly be intercepted. Your solution using @ControllerAdvice will work.

Tested with Spring Boot 2.2.0 M2 and the following ExceptionHandler:

@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomRepositoryRestExceptionHandler {

    @ExceptionHandler
    ResponseEntity<?> handleNotFound(ResourceNotFoundException o_O) {
        // Simply re-throw the exception and let the default handling kick in, which will produce a response body.
        throw o_O;
    }
}

As already posted in the comments, the issue is https://jira.spring.io/browse/DATAREST-1143 .

Sign up to request clarification or add additional context in comments.

Comments

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.