diff --git a/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/MyException.java b/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/MyException.java new file mode 100644 index 0000000000..fd4c88a365 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/MyException.java @@ -0,0 +1,25 @@ +/* + * Copyright 2012-2015 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 + * + * http://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 sample.tomcat.jsp; + +public class MyException extends RuntimeException { + + public MyException(String message) { + super(message); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/MyRestResponse.java b/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/MyRestResponse.java new file mode 100644 index 0000000000..72ea6479e7 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/MyRestResponse.java @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2015 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 + * + * http://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 sample.tomcat.jsp; + +public class MyRestResponse { + + private String message; + + public MyRestResponse(String message) { + this.message = message; + } + + public String getMessage() { + return this.message; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/WelcomeController.java b/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/WelcomeController.java index db81154356..1e17d9f07f 100644 --- a/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/WelcomeController.java +++ b/spring-boot-samples/spring-boot-sample-tomcat-jsp/src/main/java/sample/tomcat/jsp/WelcomeController.java @@ -20,8 +20,12 @@ import java.util.Date; import java.util.Map; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; @Controller public class WelcomeController { @@ -36,4 +40,20 @@ public class WelcomeController { return "welcome"; } + @RequestMapping("/fail") + public String fail() { + throw new MyException("Oh dear!"); + } + + @RequestMapping("/fail2") + public String fail2() { + throw new IllegalStateException(); + } + + @ExceptionHandler(MyException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public @ResponseBody MyRestResponse handleMyRuntimeException(MyException exception) { + return new MyRestResponse("Some data I want to send back to the client."); + } + } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java b/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java index 8e95e4b7a2..14f5f05595 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/ErrorPageFilter.java @@ -117,9 +117,9 @@ public class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContaine ErrorWrapperResponse wrapped = new ErrorWrapperResponse(response); try { chain.doFilter(request, wrapped); - int status = wrapped.getStatus(); - if (status >= 400) { - handleErrorStatus(request, response, status, wrapped.getMessage()); + if (wrapped.hasErrorToSend()) { + handleErrorStatus(request, response, wrapped.getStatus(), + wrapped.getMessage()); response.flushBuffer(); } else if (!request.isAsyncStarted() && !response.isCommitted()) { @@ -143,7 +143,6 @@ public class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContaine handleCommittedResponse(request, null); return; } - String errorPath = getErrorPath(this.statuses, status); if (errorPath == null) { response.sendError(status, message); @@ -324,6 +323,10 @@ public class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContaine return this.message; } + public boolean hasErrorToSend() { + return this.hasErrorToSend; + } + } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java index c4a4cf8d83..401a47c055 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/web/SpringBootServletInitializer.java @@ -64,6 +64,18 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit protected final Log logger = LogFactory.getLog(getClass()); + private boolean registerErrorPageFilter = true; + + /** + * Set if the {@link ErrorPageFilter} should be registered. Set to {@code false} if + * error page mappings should be handled via the Servlet container and not Spring + * Boot. + * @param registerErrorPageFilter if the {@link ErrorPageFilter} should be registered. + */ + protected final void setRegisterErrorPageFilter(boolean registerErrorPageFilter) { + this.registerErrorPageFilter = registerErrorPageFilter; + } + @Override public void onStartup(ServletContext servletContext) throws ServletException { WebApplicationContext rootAppContext = createRootApplicationContext(servletContext); @@ -106,7 +118,9 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit "No SpringApplication sources have been defined. Either override the " + "configure method or add an @Configuration annotation"); // Ensure error pages are registered - application.getSources().add(ErrorPageFilter.class); + if (this.registerErrorPageFilter) { + application.getSources().add(ErrorPageFilter.class); + } return run(application); } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java b/spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java index 3625ba4c27..c5d2abfa26 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/web/SpringBootServletInitializerTests.java @@ -38,7 +38,7 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; /** - * Tests for {@link SpringBootServletInitializerTests}. + * Tests for {@link SpringBootServletInitializer}. * * @author Phillip Webb * @author Andy Wilkinson @@ -82,8 +82,8 @@ public class SpringBootServletInitializerTests { assertThat(servletInitializer.applicationBuilder.built, equalTo(true)); } - @SuppressWarnings("rawtypes") @Test + @SuppressWarnings("rawtypes") public void mainClassHasSensibleDefault() throws Exception { new WithConfigurationAnnotation() .createRootApplicationContext(this.servletContext); @@ -93,6 +93,14 @@ public class SpringBootServletInitializerTests { is(equalTo((Class) WithConfigurationAnnotation.class))); } + @Test + public void withErrorPageFilterNotRegistered() throws Exception { + new WithErrorPageFilterNotRegistered() + .createRootApplicationContext(this.servletContext); + assertThat(this.application.getSources(), + equalToSet(WithErrorPageFilterNotRegistered.class)); + } + private Matcher> equalToSet(Object... items) { Set set = new LinkedHashSet(); Collections.addAll(set, items); @@ -138,6 +146,16 @@ public class SpringBootServletInitializerTests { } + @Configuration + public class WithErrorPageFilterNotRegistered extends + MockSpringBootServletInitializer { + + public WithErrorPageFilterNotRegistered() { + setRegisterErrorPageFilter(false); + } + + } + @Configuration public static class Config {