Remove ErrorAttributes.ERROR_ATTRIBUTE
This commit removes the now defunkt `ErrorAttributes.ERROR_ATTRIBUTE` that was introduce to register handled errors as metrics. This has been replaced since 3.0 by a direct support in Spring Framework and had no effect whatsoever since that release. This also updates the documentation to point to the Framework mechanism that replaced it. Fixes gh-33731
This commit is contained in:
@@ -189,10 +189,8 @@ include::code:MyErrorWebExceptionHandler[]
|
||||
|
||||
For a more complete picture, you can also subclass `DefaultErrorWebExceptionHandler` directly and override specific methods.
|
||||
|
||||
In some cases, errors handled at the controller or handler function level are not recorded by the <<actuator#actuator.metrics.supported.spring-webflux, metrics infrastructure>>.
|
||||
Applications can ensure that such exceptions are recorded with the request metrics by setting the handled exception as a request attribute:
|
||||
|
||||
include::code:MyExceptionHandlingController[]
|
||||
In some cases, errors handled at the controller level are not recorded by web observations or the <<actuator#actuator.metrics.supported.spring-webflux, metrics infrastructure>>.
|
||||
Applications can ensure that such exceptions are recorded with the observations by {spring-framework-docs}/integration/observability.html#observability.http-server.reactive[setting the handled exception on the observation context].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -355,10 +355,8 @@ include::code:MyControllerAdvice[]
|
||||
|
||||
In the preceding example, if `MyException` is thrown by a controller defined in the same package as `SomeController`, a JSON representation of the `MyErrorBody` POJO is used instead of the `ErrorAttributes` representation.
|
||||
|
||||
In some cases, errors handled at the controller level are not recorded by the <<actuator#actuator.metrics.supported.spring-mvc, metrics infrastructure>>.
|
||||
Applications can ensure that such exceptions are recorded with the request metrics by setting the handled exception as a request attribute:
|
||||
|
||||
include::code:MyController[]
|
||||
In some cases, errors handled at the controller level are not recorded by web observations or the <<actuator#actuator.metrics.supported.spring-mvc, metrics infrastructure>>.
|
||||
Applications can ensure that such exceptions are recorded with the observations by {spring-framework-docs}/integration/observability.html#observability.http-server.servlet[setting the handled exception on the observation context].
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.docs.web.reactive.webflux.errorhandling;
|
||||
|
||||
import org.springframework.boot.web.reactive.error.ErrorAttributes;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.reactive.result.view.Rendering;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
@Controller
|
||||
public class MyExceptionHandlingController {
|
||||
|
||||
@GetMapping("/profile")
|
||||
public Rendering userProfile() {
|
||||
// ...
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalStateException.class)
|
||||
public Rendering handleIllegalState(ServerWebExchange exchange, IllegalStateException exc) {
|
||||
exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);
|
||||
return Rendering.view("errorView").modelAttribute("message", exc.getMessage()).build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.docs.web.servlet.springmvc.errorhandling;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
@Controller
|
||||
public class MyController {
|
||||
|
||||
@ExceptionHandler(CustomException.class)
|
||||
String handleCustomException(HttpServletRequest request, CustomException ex) {
|
||||
request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex);
|
||||
return "errorView";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.docs.web.reactive.webflux.errorhandling
|
||||
|
||||
import org.springframework.boot.web.reactive.error.ErrorAttributes
|
||||
import org.springframework.stereotype.Controller
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.reactive.result.view.Rendering
|
||||
import org.springframework.web.server.ServerWebExchange
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
@Controller
|
||||
class MyExceptionHandlingController {
|
||||
|
||||
@GetMapping("/profile")
|
||||
fun userProfile(): Rendering {
|
||||
// ...
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalStateException::class)
|
||||
fun handleIllegalState(exchange: ServerWebExchange, exc: IllegalStateException): Rendering {
|
||||
exchange.attributes.putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc)
|
||||
return Rendering.view("errorView").modelAttribute("message", exc.message ?: "").build()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.docs.web.servlet.springmvc.errorhandling
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes
|
||||
import org.springframework.stereotype.Controller
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
|
||||
@Controller
|
||||
class MyController {
|
||||
|
||||
@ExceptionHandler(CustomException::class)
|
||||
fun handleCustomException(request: HttpServletRequest, ex: CustomException?): String {
|
||||
request.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, ex)
|
||||
return "errorView"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -152,7 +152,6 @@ public class DefaultErrorAttributes implements ErrorAttributes {
|
||||
@Override
|
||||
public Throwable getError(ServerRequest request) {
|
||||
Optional<Object> error = request.attribute(ERROR_INTERNAL_ATTRIBUTE);
|
||||
error.ifPresent((value) -> request.attributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, value));
|
||||
return (Throwable) error
|
||||
.orElseThrow(() -> new IllegalStateException("Missing exception attribute in ServerWebExchange"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,13 +34,6 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
*/
|
||||
public interface ErrorAttributes {
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerRequest#attribute(String) request attribute} holding the
|
||||
* error resolved by the {@code ErrorAttributes} implementation.
|
||||
* @since 2.5.0
|
||||
*/
|
||||
String ERROR_ATTRIBUTE = ErrorAttributes.class.getName() + ".error";
|
||||
|
||||
/**
|
||||
* Return a {@link Map} of the error attributes. The map can be used as the model of
|
||||
* an error page, or returned as a {@link ServerResponse} body.
|
||||
|
||||
@@ -216,9 +216,6 @@ public class DefaultErrorAttributes implements ErrorAttributes, HandlerException
|
||||
if (exception == null) {
|
||||
exception = getAttribute(webRequest, RequestDispatcher.ERROR_EXCEPTION);
|
||||
}
|
||||
// store the exception in a well-known attribute to make it available to metrics
|
||||
// instrumentation.
|
||||
webRequest.setAttribute(ErrorAttributes.ERROR_ATTRIBUTE, exception, WebRequest.SCOPE_REQUEST);
|
||||
return exception;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,14 +34,6 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
*/
|
||||
public interface ErrorAttributes {
|
||||
|
||||
/**
|
||||
* Name of the {@link jakarta.servlet.http.HttpServletRequest#getAttribute(String)
|
||||
* request attribute} holding the error resolved by the {@code ErrorAttributes}
|
||||
* implementation.
|
||||
* @since 2.5.0
|
||||
*/
|
||||
String ERROR_ATTRIBUTE = ErrorAttributes.class.getName() + ".error";
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} of the error attributes. The map can be used as the model of
|
||||
* an error page {@link ModelAndView}, or returned as a
|
||||
|
||||
@@ -160,7 +160,6 @@ class DefaultErrorAttributesTests {
|
||||
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(serverRequest,
|
||||
ErrorAttributeOptions.of(Include.EXCEPTION, Include.MESSAGE));
|
||||
assertThat(this.errorAttributes.getError(serverRequest)).isSameAs(error);
|
||||
assertThat(serverRequest.attribute(ErrorAttributes.ERROR_ATTRIBUTE)).containsSame(error);
|
||||
assertThat(attributes).containsEntry("exception", RuntimeException.class.getName());
|
||||
assertThat(attributes).containsEntry("message", "Test");
|
||||
}
|
||||
@@ -178,7 +177,6 @@ class DefaultErrorAttributesTests {
|
||||
assertThat(attributes).containsEntry("message", "invalid request");
|
||||
assertThat(attributes).containsEntry("exception", RuntimeException.class.getName());
|
||||
assertThat(this.errorAttributes.getError(serverRequest)).isSameAs(error);
|
||||
assertThat(serverRequest.attribute(ErrorAttributes.ERROR_ATTRIBUTE)).containsSame(error);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -194,7 +192,6 @@ class DefaultErrorAttributesTests {
|
||||
assertThat(attributes).containsEntry("message", "could not process request");
|
||||
assertThat(attributes).containsEntry("exception", ResponseStatusException.class.getName());
|
||||
assertThat(this.errorAttributes.getError(serverRequest)).isSameAs(error);
|
||||
assertThat(serverRequest.attribute(ErrorAttributes.ERROR_ATTRIBUTE)).containsSame(error);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -88,8 +88,6 @@ class DefaultErrorAttributesTests {
|
||||
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest,
|
||||
ErrorAttributeOptions.of(Include.MESSAGE));
|
||||
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(ex);
|
||||
assertThat(this.webRequest.getAttribute(ErrorAttributes.ERROR_ATTRIBUTE, WebRequest.SCOPE_REQUEST))
|
||||
.isSameAs(ex);
|
||||
assertThat(modelAndView).isNull();
|
||||
assertThat(attributes).doesNotContainKey("exception");
|
||||
assertThat(attributes).containsEntry("message", "Test");
|
||||
@@ -102,8 +100,6 @@ class DefaultErrorAttributesTests {
|
||||
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest,
|
||||
ErrorAttributeOptions.of(Include.MESSAGE));
|
||||
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(ex);
|
||||
assertThat(this.webRequest.getAttribute(ErrorAttributes.ERROR_ATTRIBUTE, WebRequest.SCOPE_REQUEST))
|
||||
.isSameAs(ex);
|
||||
assertThat(attributes).doesNotContainKey("exception");
|
||||
assertThat(attributes).containsEntry("message", "Test");
|
||||
}
|
||||
@@ -115,8 +111,6 @@ class DefaultErrorAttributesTests {
|
||||
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest,
|
||||
ErrorAttributeOptions.defaults());
|
||||
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(ex);
|
||||
assertThat(this.webRequest.getAttribute(ErrorAttributes.ERROR_ATTRIBUTE, WebRequest.SCOPE_REQUEST))
|
||||
.isSameAs(ex);
|
||||
assertThat(attributes).doesNotContainKey("exception");
|
||||
assertThat(attributes).doesNotContainKey("message");
|
||||
}
|
||||
@@ -166,8 +160,6 @@ class DefaultErrorAttributesTests {
|
||||
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest,
|
||||
ErrorAttributeOptions.of(Include.MESSAGE));
|
||||
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(wrapped);
|
||||
assertThat(this.webRequest.getAttribute(ErrorAttributes.ERROR_ATTRIBUTE, WebRequest.SCOPE_REQUEST))
|
||||
.isSameAs(wrapped);
|
||||
assertThat(attributes).doesNotContainKey("exception");
|
||||
assertThat(attributes).containsEntry("message", "Test");
|
||||
}
|
||||
@@ -179,8 +171,6 @@ class DefaultErrorAttributesTests {
|
||||
Map<String, Object> attributes = this.errorAttributes.getErrorAttributes(this.webRequest,
|
||||
ErrorAttributeOptions.of(Include.MESSAGE));
|
||||
assertThat(this.errorAttributes.getError(this.webRequest)).isSameAs(error);
|
||||
assertThat(this.webRequest.getAttribute(ErrorAttributes.ERROR_ATTRIBUTE, WebRequest.SCOPE_REQUEST))
|
||||
.isSameAs(error);
|
||||
assertThat(attributes).doesNotContainKey("exception");
|
||||
assertThat(attributes).containsEntry("message", "Test error");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user