PageNotFoundExceptionMapper.java
package io.extact.rms.platform.jaxrs.mapper;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriInfo;
import jakarta.ws.rs.ext.ExceptionMapper;
import org.eclipse.microprofile.config.Config;
import lombok.extern.slf4j.Slf4j;
/**
* Handle {@link NotFoundException} that occurs when status code is 404.
* The handle of unknown RuntimeException logs stacktrace, but I don't want to
* output stacktrace with 404, so NotFoundException is handled individually.
*/
@Produces(MediaType.APPLICATION_JSON)
@Slf4j
public class PageNotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
private static final String UNHANDLE_404_PATHS_PROP = "exception.mapper.unhandle.404.paths";
@Context
private UriInfo uriInfo;
private Unhandle404 unhandle404;
@Inject
public PageNotFoundExceptionMapper(Config config) {
this.unhandle404 =new Unhandle404(config.getOptionalValue(UNHANDLE_404_PATHS_PROP, String[].class));
}
/**
* Static content registered in the configuration file does not handle anything.
*
* @param exception Occurrence exception
* @return {@link Response}
*/
@Override
public Response toResponse(NotFoundException exception) {
if (!unhandle404.test("/" + uriInfo.getPath())) {
log.warn(exception.getMessage() + " (path=>{})", "/" + uriInfo.getPath());
}
return exception.getResponse();
}
// ----------------------------------------------------- inner class def
static class Unhandle404 implements Predicate<String> {
private String[] unhandlePaths;
public Unhandle404(Optional<String[]> paths) {
this.unhandlePaths = paths.orElse(new String[0]);
}
@Override
public boolean test(String requestPath) {
return Stream.of(unhandlePaths).anyMatch(requestPath::startsWith);
}
}
}