Passionate about JVM languages, Distributed Systems, Concurrency Models, and Algorithms.
alimate / errors-spring-boot-starter Goto Github PK
View Code? Open in Web Editor NEWElegant Error Handling for Spring Boot
License: Apache License 2.0
Elegant Error Handling for Spring Boot
License: Apache License 2.0
Usually, we put valuable data inside the exceptions like traceId, the requested URI, the rejected or failed input values and...
That will be awesome if you add an option to pick the fields of the Exception class and add them to the error representation JSON. For now, It just ignores all fields of the Exception class.
The Exception class:
@ExceptionMapping(statusCode = HttpStatus.NOT_FOUND, errorCode = "the_error_code")
@NoArgsConstructor
@AllArgsConstructor
public class NotFoundException extends Exception {
private String traceId;
}
What I expect:
{
"errors": [
{
"code": "the_error_code",
"message": "the_error_message",
"traceId": "some data here or null if not set"
}
]
}
What I get:
{
"errors": [
{
"code": "the_error_code",
"message": "the_error_message"
}
]
}
Currently, in order to bootstrap the integration tests, we're creating the appropriate ApplicationContext
instance manually which has proven to be cumbersome and error-prone.
We can simply use the @SpringBootTest
and bootstrap a complete Spring Boot application before running tests.
WebErrorHandler
to handle Spring Security specific exceptions.ErrorController
Related issue spring-projects/spring-boot#16258
We should use an empty ImportAutoConfiguration
annotation and specify the to-be-imported configurations in the spring.factories
metafile.
Currently, we only support positional arguments in message interpolations, as follows:
age.min=You should be at least {1} years old but you're {0} years old!
As we expose more and more arguments, those {0}
, {1}
, etc. arguments would make less sense.
We can simply support message expressions like:
age.min=You should be at least {value} years old but you're {invalid} years old!
Since after the merge of #46, all arguments would have names, then we already have the required infrastructure.
We may use MessageSource
along with Spring's EL or Expression Language.
Currently, the SpringValidationWebErrorHandler
is responsible for handling all BindException
s. For validation related errors this works just fine but for other binding failures such as missing fields or type mismatches the current implementation exposes the exception details as the error code, hence leaking too much information!
@RestController
@RequestMapping("/persons")
public class PersonController {
@GetMapping
public List<Person> filterPersons(Filter filter) {
// Return something
}
public static class Filter {
private Type type;
// Getters and setters
}
public enum Type {
INTROVERT, EXTRPVERT
}
}
/persons?type=invalid
, the error would be something like:{
"errors": [
{
"code": "Failed to convert property value of type 'java.lang.String' to required type 'me.alidg.reactiveweb.PersonController$Type' for property 'type'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [me.alidg.reactiveweb.PersonController$Type] for value 'invalid'; nested exception is java.lang.IllegalArgumentException: No enum constant me.alidg.reactiveweb.PersonController.Type.invalid",
"message": null
}
]
}
That's too much information!
SpringValidationWebErrorHandler
to not leak the exception details.SpringValidationWebErrorHandler
should not handle BindingException
s that are originating from type mismatchtes or missing fields.BindingErrorProcessor
implementation could do the trick.Currently reading the source code is the only way to discover the exposed arguments and their names for a particular exception. We have to document all exposed arguments per exception.
When uploading a file, if the given file is bigger than the maximum possible size, it would throw a MaxUploadSizeExceededException
exception.
That's it.
Since we catch all possible exceptions and know about their details, we might as well expose some metrics about them, too.
We may register a WebErrorHandlerPostProcessor
conditionally to expose the related metrics about the handled exception, its corresponding error code, status code, etc.
For instance, if the locale is en_US and only messages.properties is offered, null will be rendered like this:
#classpath:messages.properties
some_code: Something
Error result:
{
"errors": [
{
"code": "some_code",
"message": "null"
}
]
}
The result should grab the default message when its locale is not found.
Spring Framework 5.1 added a few new Servlet related exceptions to report missing Header, Cookie or Matrix Variables:
MissingMatrixVariableException
MissingRequestCookieException
MissingRequestHeaderException
We should consider adding another built-in handler to handle these exceptions in a backward compatible way.
Does the messages parameters (Message parameters are string literals enclosed in {}
, see https://docs.jboss.org/hibernate/validator/6.1/reference/en-US/html_single/#section-message-interpolation) is supported?
For example, would the following work?
@NotBlank(message = "{username.required}")
private final String username;
When the anonymous
is disabled on Spring Security, The ExceptionTranslationFilter
would delegate the AuthenticationException
s to an AuthenticationEntryPoint
, so the WebErrorHandlers
would not get a chance to handle the exception.
Maybe the solution is as simple as registering a custom AuthenticationEntryPoint
.
Firstly, thank you for all the work you've done on this library. It's a pleasure to use.
If I have the following classes:
public class Foo {
@NotNull(message = "a.required")
private int a;
@NotNull(message = "b.required")
private int b;
... getters/setters
}
And
public class Bar {
@Valid
private List<Foo> foos;
... getters/setters
}
If I validate Bar which has a list of Foo objects it seems to work fine as long as the same error isn't thrown twice. So if I have two Foo objects, one with a null 'a' field and one with a null 'b' field it works fine. If I have a list of Foo objects where two or more have null 'b' objects, for example, I get the following:
2018-11-26 18:01:26.763 WARN 18876 --- [o-11000-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Failed to invoke @ExceptionHandler method: public org.springframework.http.ResponseEntity<?> me.alidg.er
rors.mvc.ErrorsControllerAdvice.handleException(java.lang.Throwable,java.util.Locale)
java.lang.IllegalStateException: Duplicate key []
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) ~[na:1.8.0_161]
at java.util.HashMap.merge(HashMap.java:1254) ~[na:1.8.0_161]
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320) ~[na:1.8.0_161]
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) ~[na:1.8.0_161]
at java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1235) ~[na:1.8.0_161]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[na:1.8.0_161]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_161]
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[na:1.8.0_161]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_161]
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[na:1.8.0_161]
at me.alidg.errors.handlers.SpringValidationWebErrorHandler.handle(SpringValidationWebErrorHandler.java:56) ~[errors-spring-boot-starter-1.2.0.jar:na]
at me.alidg.errors.WebErrorHandlers.handle(WebErrorHandlers.java:120) ~[errors-spring-boot-starter-1.2.0.jar:na]
at me.alidg.errors.mvc.ErrorsControllerAdvice.handleException(ErrorsControllerAdvice.java:58) ~[errors-spring-boot-starter-1.2.0.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:405) ~[spring-webmvc-5.0.4.RELEASE.
jar:5.0.4.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:61) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:140) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:78) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1255) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1062) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1008) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) [spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158) [spring-boot-actuator-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126) [spring-boot-actuator-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111) [spring-boot-actuator-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:84) [spring-boot-actuator-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.28.jar:8.5.28]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.28.jar:8.5.28]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.28.jar:8.5.28]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]
It seems not to like the duplicate error codes. Is there a supported way around this or is something custom needed? I'd like it to just continue and return the error once instead of throwing an exception.
ControllerAdvice
to catch all exceptions and turn them into meaningful code-message
paris using the WebErrorHandlers
factory.ErrorController
to catch the remaining exceptions.WebErrorHandler
implementation for Spring MVC specific exceptionsThat'd be awesome if we could provide an abstraction to log all exceptions.
When using Kotlin missing paramters can be thrown as MissingKotlinParameterException
or MismatchedInputException
. It would be nice to have a default handler for these errors.
It should be possible to override the built in error handlers with a custom solution if needed. Because of not being able to do this using this library as is won't work because of #20.
Otherwise, the built-in handlers should be more specific on which exceptions they can handle.
Hi,
IMHO the default behavior regarding validation errors can be improved. Indeed, currently it seems that this lib doesn't rely on the default message provided by the validation api.
Furthermore, the in error field isn't in the resulting json.
For example :
{
"errors": [
{
"code": "javax.validation.constraints.Size.message",
"message": null
}
]
}
To me, if there is no customization, the json should contain the field and the default error message provided by the validation api.
What do you think about that ?
Have a nice day :)
Currently, we only support the 2.x.x
versions of Spring Boot. Supporting multiple versions of Spring Boot in a single codebase seems complicated, since each major release may introduce conflicting and backward-incompatible changes.
With a few simple changes, we should be able to support the 1.5.x
but I couldn't find a way to pull this off, yet! Also, supporting future versions may get as complicated.
One solution is to modularize (not to be confused with JPMS) the project. That is, we can create:
WebErrorHandler
, FingerPrintProvider
or HttpError
.1.x.x
, 2.x.x
, etc.Currently a 500 will be returned if a header that is required is missing. Standard Spring will return a 400 which should be the default behavior of this tool.
I did a little searching and it seems Spring just uses a ServletRequestBindingException
for missing headers. This doesn't provide any way to get the header name or type so it would be a little hard to change the message. The default message is something like: "Missing request header 'name' for method parameter of type String"
Sometimes the caught exception is just a symptom, not the cause of the failure. The WebErrorHandlers
should be able to refine a particular exception before starting the handling procedure.
Currently, one can only register at most one ExceptionRefiner
instance to refine exceptions before processing them. That might be useful to extend this feature in a way that it supports multiple refiners.
It's a common pattern to wrap some exceptions into other exceptions which are more appropriate to a particular abstraction level. For example, when Jackson fails to de-serialize a byte-array into a POJO, the thrown exception will be wrapped inside a Spring exception. The only way for us to handle those Jackson exceptions is to:
WebErrorHandler
.Currently, our tests are running only on JDK 8
and Linux
. In order to make sure it's gonna work everywhere, we should run tests with multiple OSes and multiple JDK versions.
The reactive web support simply does not report the path
as an argument. This behavior is inconsistent with what we have in the Servlet stack.
Errors are not mocked in this code:
@AutoConfigureErrors
@SpringBootTest(classes = Application.class)
@TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
@AutoConfigureMockMvc
public class MockBaseTests extends AbstractTestNGSpringContextTests {
protected static final Logger logger = LoggerFactory.getLogger(MockBaseTests.class);
@Autowired
protected MockMvc mockMvc;
@Test
public void loadContexts() {
logger.info("Mock base tests is loading");
}
@Test
public void testNotFound() throws Exception {
//no path /404
mockMvc.perform(get("/404").contentType(MediaType.APPLICATION_JSON_UTF8)).andExpect(status().isNotFound())
.andDo(print());
}
}
I'm using spring boot 2.0.2.RELEASE, when maven wants to build the project, I got this exception:
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getAnnotationMetadata(AutoConfigurationSorter.java:245) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getOrder(AutoConfigurationSorter.java:214) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.access$000(AutoConfigurationSorter.java:155) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter.lambda$getInPriorityOrder$0(AutoConfigurationSorter.java:62) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) ~[na:1.8.0_102]
at java.util.TimSort.sort(TimSort.java:234) ~[na:1.8.0_102]
at java.util.Arrays.sort(Arrays.java:1512) ~[na:1.8.0_102]
at java.util.ArrayList.sort(ArrayList.java:1454) ~[na:1.8.0_102]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter.getInPriorityOrder(AutoConfigurationSorter.java:61) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.sortAutoConfigurations(AutoConfigurationImportSelector.java:408) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.selectImports(AutoConfigurationImportSelector.java:394) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:831) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:563) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:188) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:316) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:233) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:271) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:91) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:139) [spring-boot-test-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) [spring-test-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365) [surefire-junit4-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273) [surefire-junit4-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238) [surefire-junit4-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159) [surefire-junit4-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:379) [surefire-booter-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:340) [surefire-booter-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:125) [surefire-booter-2.21.0.jar:2.21.0]
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:413) [surefire-booter-2.21.0.jar:2.21.0]
Caused by: java.io.FileNotFoundException: class path resource [ me/alidg/errors/conf/ServletSecurityErrorsAutoConfiguration.class] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:180) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:51) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:88) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:75) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81) ~[spring-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getAnnotationMetadata(AutoConfigurationSorter.java:241) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
... 52 common frames omitted```
Since we're not too dependent on Spring Boot 2.x
abstractions, it may be possible to add the 1.5.x
version support.
Since we changed our strategy regarding the validation exceptions, we may do not need to register an instance of Validator
in our auto-configuration.
Validator
Hi! Great project!
Added in the dependency and getting null when trying simple 404 test. I must be doing something very wrong somewhere any ideas?
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
null
There was an unexpected error (type=null, status=null)
Sometimes Spring MVC and WebFlux decide to throw MultipartException
for multipart requests. For example, if the endpoint supposed to be a multipart one but the request isn't, then Spring throws this general exception.
Suppose:
@RestController
@RequestMapping("/somewhere")
public class TheController {
@GetMapping
public String handle(@RequestParam Integer page) {
// Return something
}
}
Then if we a send a request to somewhere like /somewhere?page=invalid
, Then Spring MVC throws an instance of TypeMismatchException
or MethodArgumentTypeMismatchException
which we don't handle properly.
The issue is self-explanatory.
It would be helpful for contributors and would make code reviews much easier.
In order to add more and more details in error HTTP responses, we may need to enrich the HttpError
class with more relevant information such as the WebRequest
(See #32).
As the Spring Framework 5.2 and Spring Boot 2.2 are both around the corner, we might as well start the integration process before the actual release.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.