Reputation: 1271
I got a working spring boot rest service. When the path is wrong it doesn't return anything. No response At all. At the same time it doesn't throw error either. Ideally I expected a 404 not found error.
I got a GlobalErrorHandler
@ControllerAdvice
public class GlobalErrorHandler extends ResponseEntityExceptionHandler {
}
There is this method in ResponseEntityExceptionHandler
protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
return handleExceptionInternal(ex, null, headers, status, request);
}
I have marked error.whitelabel.enabled=false
in my properties
What else must I do for this service to throw a 404 not found response back to clients
I referred a lot of threads and don't see this trouble faced by anybody.
This is my main application class
@EnableAutoConfiguration // Sprint Boot Auto Configuration
@ComponentScan(basePackages = "com.xxxx")
@EnableJpaRepositories("com.xxxxxxxx") // To segregate MongoDB
// and JPA repositories.
// Otherwise not needed.
@EnableSwagger // auto generation of API docs
@SpringBootApplication
@EnableAspectJAutoProxy
@EnableConfigurationProperties
public class Application extends SpringBootServletInitializer {
private static Class<Application> appClass = Application.class;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(appClass).properties(getProperties());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public FilterRegistrationBean correlationHeaderFilter() {
FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
filterRegBean.setFilter(new CorrelationHeaderFilter());
filterRegBean.setUrlPatterns(Arrays.asList("/*"));
return filterRegBean;
}
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
static Properties getProperties() {
Properties props = new Properties();
props.put("spring.config.location", "classpath:/");
return props;
}
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter() {
WebMvcConfigurerAdapter webMvcConfigurerAdapter = new WebMvcConfigurerAdapter() {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false).favorParameter(true).parameterName("media-type")
.ignoreAcceptHeader(false).useJaf(false).defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON);
}
};
return webMvcConfigurerAdapter;
}
@Bean
public RequestMappingHandlerMapping defaultAnnotationHandlerMapping() {
RequestMappingHandlerMapping bean = new RequestMappingHandlerMapping();
bean.setUseSuffixPatternMatch(false);
return bean;
}
}
Upvotes: 18
Views: 53362
Reputation: 3233
Add this to your Properties file.
spring:
mvc:
throw-exception-if-no-handler-found: true
web:
resources:
add-mappings: false
In your @ControllerAdvice
class add this:
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<Object> handleNoHandlerFound404() {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);;
}
Upvotes: 0
Reputation: 4247
The solution is pretty easy:
First you need to implement the controller that will handle all error cases. This controller must have @ControllerAdvice
-- required to define @ExceptionHandler
that apply to all @RequestMappings
.
@ControllerAdvice
public class ExceptionHandlerController {
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(value= HttpStatus.NOT_FOUND)
@ResponseBody
public ErrorResponse requestHandlingNoHandlerFound() {
return new ErrorResponse("custom_404", "message for 404 error code");
}
}
Provide exception you want to override response in @ExceptionHandler
. NoHandlerFoundException
is an exception that will be generated when Spring will not be able to delegate request (404 case). You also can specify Throwable
to override any exceptions.
Second you need to tell Spring to throw exception in case of 404 (could not resolve handler):
@SpringBootApplication
@EnableWebMvc
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
DispatcherServlet dispatcherServlet = (DispatcherServlet)ctx.getBean("dispatcherServlet");
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
}
Result when I use non defined URL
{
"errorCode": "custom_404",
"errorMessage": "message for 404 error code"
}
UPDATE: In case you configure your SpringBoot application using application.properties
then you need to add the following properties instead of configuring DispatcherServlet
in main method (thanks to @mengchengfeng):
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
Upvotes: 35
Reputation: 29
I know this is an old question but here is another way to configure the DispatcherServlet
in code but not in the main class. You can use a separate @Configuration
class:
@EnableWebMvc
@Configuration
public class ExceptionHandlingConfig {
@Autowired
private DispatcherServlet dispatcherServlet;
@PostConstruct
private void configureDispatcherServlet() {
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
}
Please not that this does not work without the @EnableWebMvc
annotation.
Upvotes: 0