Commit 468728a2 authored by Phillip Webb's avatar Phillip Webb

Polish

parent 07b88630
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -24,8 +24,9 @@ import org.springframework.context.ApplicationContext; ...@@ -24,8 +24,9 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
/** /**
* @author Dave Syer * Test for application hierarchies created using {@link SpringApplicationBuilder}.
* *
* @author Dave Syer
*/ */
public class SpringApplicationHierarchyTests { public class SpringApplicationHierarchyTests {
......
...@@ -116,4 +116,4 @@ public class AuthenticationManagerConfiguration extends ...@@ -116,4 +116,4 @@ public class AuthenticationManagerConfiguration extends
auth.parentAuthenticationManager(parent); auth.parentAuthenticationManager(parent);
} }
} }
} }
\ No newline at end of file
...@@ -45,9 +45,11 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur ...@@ -45,9 +45,11 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur
@Import({ SpringBootWebSecurityConfiguration.class, @Import({ SpringBootWebSecurityConfiguration.class,
AuthenticationManagerConfiguration.class }) AuthenticationManagerConfiguration.class })
public class SecurityAutoConfiguration { public class SecurityAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public SecurityProperties securityProperties() { public SecurityProperties securityProperties() {
return new SecurityProperties(); return new SecurityProperties();
} }
}
\ No newline at end of file }
...@@ -124,8 +124,8 @@ public class WebMvcAutoConfiguration { ...@@ -124,8 +124,8 @@ public class WebMvcAutoConfiguration {
// Defined as a nested config to ensure WebMvcConfigurerAdapter it not read when not // Defined as a nested config to ensure WebMvcConfigurerAdapter it not read when not
// on the classpath // on the classpath
@EnableWebMvc
@Configuration @Configuration
@EnableWebMvc
public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter { public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter {
private static Log logger = LogFactory.getLog(WebMvcConfigurerAdapter.class); private static Log logger = LogFactory.getLog(WebMvcConfigurerAdapter.class);
......
...@@ -49,8 +49,8 @@ ...@@ -49,8 +49,8 @@
<spring-data-jpa.version>1.5.0.RELEASE</spring-data-jpa.version> <spring-data-jpa.version>1.5.0.RELEASE</spring-data-jpa.version>
<spring-data-mongodb.version>1.4.0.RELEASE</spring-data-mongodb.version> <spring-data-mongodb.version>1.4.0.RELEASE</spring-data-mongodb.version>
<spring-data-redis.version>1.1.1.RELEASE</spring-data-redis.version> <spring-data-redis.version>1.1.1.RELEASE</spring-data-redis.version>
<spring-data-rest.version>2.0.0.RELEASE</spring-data-rest.version> <spring-data-rest.version>2.0.0.RELEASE</spring-data-rest.version>
<spring-hateoas.version>0.9.0.RELEASE</spring-hateoas.version> <spring-hateoas.version>0.9.0.RELEASE</spring-hateoas.version>
<spring-rabbit.version>1.2.1.RELEASE</spring-rabbit.version> <spring-rabbit.version>1.2.1.RELEASE</spring-rabbit.version>
<spring-mobile.version>1.1.1.RELEASE</spring-mobile.version> <spring-mobile.version>1.1.1.RELEASE</spring-mobile.version>
<spring-security.version>3.2.1.RELEASE</spring-security.version> <spring-security.version>3.2.1.RELEASE</spring-security.version>
...@@ -494,16 +494,16 @@ ...@@ -494,16 +494,16 @@
<artifactId>spring-data-redis</artifactId> <artifactId>spring-data-redis</artifactId>
<version>${spring-data-redis.version}</version> <version>${spring-data-redis.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.hateoas</groupId> <groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId> <artifactId>spring-hateoas</artifactId>
<version>${spring-hateoas.version}</version> <version>${spring-hateoas.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId> <artifactId>spring-data-rest-webmvc</artifactId>
<version>${spring-data-rest.version}</version> <version>${spring-data-rest.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.integration</groupId> <groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId> <artifactId>spring-integration-core</artifactId>
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<!-- Your own application should inherit from spring-boot-starter-parent --> <!-- Your own application should inherit from spring-boot-starter-parent -->
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -24,7 +24,7 @@ import sample.data.jpa.domain.Hotel; ...@@ -24,7 +24,7 @@ import sample.data.jpa.domain.Hotel;
@RepositoryRestResource(collectionResourceRel = "hotels", path = "hotels") @RepositoryRestResource(collectionResourceRel = "hotels", path = "hotels")
interface HotelRepository extends PagingAndSortingRepository<Hotel, Long> { interface HotelRepository extends PagingAndSortingRepository<Hotel, Long> {
Hotel findByCityAndName(City city, String name); Hotel findByCityAndName(City city, String name);
} }
package sample.data.jpa; /*
* Copyright 2012-2014 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.
*/
import static org.hamcrest.Matchers.containsString; package sample.data.jpa;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -17,6 +28,11 @@ import org.springframework.test.web.servlet.MockMvc; ...@@ -17,6 +28,11 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/** /**
* Integration test to run the application. * Integration test to run the application.
* *
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package sample.data.jpa.service; package sample.data.jpa.service;
import org.junit.Test; import org.junit.Test;
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package sample.secure; package sample.secure;
import static org.junit.Assert.assertEquals;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -38,6 +36,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; ...@@ -38,6 +36,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import sample.secure.SampleSecureApplicationTests.TestConfiguration; import sample.secure.SampleSecureApplicationTests.TestConfiguration;
import static org.junit.Assert.assertEquals;
/** /**
* Basic integration tests for demo application. * Basic integration tests for demo application.
* *
...@@ -58,9 +58,9 @@ public class SampleSecureApplicationTests { ...@@ -58,9 +58,9 @@ public class SampleSecureApplicationTests {
@Before @Before
public void init() { public void init() {
AuthenticationManager authenticationManager = context AuthenticationManager authenticationManager = this.context.getBean(
.getBean(AuthenticationManagerBuilder.class).getOrBuild(); AuthenticationManagerBuilder.class).getOrBuild();
authentication = authenticationManager this.authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken("user", "password")); .authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
} }
...@@ -71,25 +71,25 @@ public class SampleSecureApplicationTests { ...@@ -71,25 +71,25 @@ public class SampleSecureApplicationTests {
@Test(expected = AuthenticationException.class) @Test(expected = AuthenticationException.class)
public void secure() throws Exception { public void secure() throws Exception {
assertEquals(service.secure(), "Hello Security"); assertEquals(this.service.secure(), "Hello Security");
} }
@Test @Test
public void authenticated() throws Exception { public void authenticated() throws Exception {
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(this.authentication);
assertEquals(service.secure(), "Hello Security"); assertEquals(this.service.secure(), "Hello Security");
} }
@Test @Test
public void preauth() throws Exception { public void preauth() throws Exception {
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(this.authentication);
assertEquals(service.authorized(), "Hello World"); assertEquals(this.service.authorized(), "Hello World");
} }
@Test(expected = AccessDeniedException.class) @Test(expected = AccessDeniedException.class)
public void denied() throws Exception { public void denied() throws Exception {
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(this.authentication);
assertEquals(service.denied(), "Goodbye World"); assertEquals(this.service.denied(), "Goodbye World");
} }
@PropertySource("classpath:test.properties") @PropertySource("classpath:test.properties")
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<!-- Your own application should inherit from spring-boot-starter-parent --> <!-- Your own application should inherit from spring-boot-starter-parent -->
......
...@@ -76,26 +76,20 @@ public class SampleMethodSecurityApplication extends WebMvcConfigurerAdapter { ...@@ -76,26 +76,20 @@ public class SampleMethodSecurityApplication extends WebMvcConfigurerAdapter {
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// @formatter:off // @formatter:off
auth.inMemoryAuthentication() auth.inMemoryAuthentication().withUser("admin").password("admin")
.withUser("admin").password("admin").roles("ADMIN", "USER") .roles("ADMIN", "USER").and().withUser("user").password("user")
.and() .roles("USER");
.withUser("user").password("user").roles("USER");
// @formatter:on // @formatter:on
} }
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
// @formatter:off // @formatter:off
http http.authorizeRequests().antMatchers("/login").permitAll().anyRequest()
.authorizeRequests() .fullyAuthenticated().and().formLogin().loginPage("/login")
.antMatchers("/login").permitAll() .failureUrl("/login?error").and().logout()
.anyRequest().fullyAuthenticated() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")).and()
.and() .exceptionHandling().accessDeniedPage("/access?error");
.formLogin().loginPage("/login").failureUrl("/login?error")
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and()
.exceptionHandling().accessDeniedPage("/access?error");
// @formatter:on // @formatter:on
} }
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/> <include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- logger name="org.springframework.boot" level="DEBUG"/--> <!-- logger name="org.springframework.boot" level="DEBUG"/-->
<logger name="org.springframework.security" level="DEBUG"/> <logger name="org.springframework.security" level="DEBUG"/>
</configuration> </configuration>
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
package sample.ui.method; package sample.ui.method;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
...@@ -45,6 +42,9 @@ import org.springframework.util.MultiValueMap; ...@@ -45,6 +42,9 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/** /**
* Basic integration tests for demo application. * Basic integration tests for demo application.
* *
......
...@@ -30,12 +30,12 @@ The parent pom adds two main fetaures to your project: ...@@ -30,12 +30,12 @@ The parent pom adds two main fetaures to your project:
* dependency management configuration, so you don't have to specify * dependency management configuration, so you don't have to specify
versions or excludes with your own dependencies, as long as they are versions or excludes with your own dependencies, as long as they are
part of the Spring Boot stack part of the Spring Boot stack
* plugin configuration, so you don't have to configure some common * plugin configuration, so you don't have to configure some common
settings in the main Maven plugins used to get a project off the settings in the main Maven plugins used to get a project off the
ground (e.g. the ground (e.g. the
[Spring Boot Maven plugin](../spring-boot-tools/spring-boot-maven-plugin/README.md)) [Spring Boot Maven plugin](../spring-boot-tools/spring-boot-maven-plugin/README.md))
As an example, if you want to build a simple RESTful web service with As an example, if you want to build a simple RESTful web service with
embedded Tomcat, you only need one dependency: embedded Tomcat, you only need one dependency:
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
......
...@@ -18,13 +18,13 @@ ...@@ -18,13 +18,13 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.hateoas</groupId> <groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId> <artifactId>spring-hateoas</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId> <artifactId>spring-data-rest-webmvc</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
...@@ -308,17 +309,22 @@ ...@@ -308,17 +309,22 @@
</goals> </goals>
<configuration> <configuration>
<transformers> <transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource> <resource>META-INF/spring.handlers</resource>
</transformer> </transformer>
<transformer implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer"> <transformer
implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
<resource>META-INF/spring.factories</resource> <resource>META-INF/spring.factories</resource>
</transformer> </transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource> <resource>META-INF/spring.schemas</resource>
</transformer> </transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" /> <transformer
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${start-class}</mainClass> <mainClass>${start-class}</mainClass>
</transformer> </transformer>
</transformers> </transformers>
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -27,25 +27,26 @@ import org.springframework.util.ObjectUtils; ...@@ -27,25 +27,26 @@ import org.springframework.util.ObjectUtils;
*/ */
public class ErrorPage { public class ErrorPage {
private final String path; private final HttpStatus status;
private Class<? extends Throwable> exception = null; private final Class<? extends Throwable> exception;
private HttpStatus status = null; private final String path;
public ErrorPage(String path) { public ErrorPage(String path) {
super(); this.status = null;
this.exception = null;
this.path = path; this.path = path;
} }
public ErrorPage(HttpStatus status, String path) { public ErrorPage(HttpStatus status, String path) {
super();
this.status = status; this.status = status;
this.exception = null;
this.path = path; this.path = path;
} }
public ErrorPage(Class<? extends Throwable> exception, String path) { public ErrorPage(Class<? extends Throwable> exception, String path) {
super(); this.status = null;
this.exception = exception; this.exception = exception;
this.path = path; this.path = path;
} }
...@@ -61,15 +62,17 @@ public class ErrorPage { ...@@ -61,15 +62,17 @@ public class ErrorPage {
} }
/** /**
* @return the exception type (or null for a page that matches by status) * Returns the exception type (or {@code null} for a page that matches by status)
* @return the exception type or {@code null}
*/ */
public Class<? extends Throwable> getException() { public Class<? extends Throwable> getException() {
return this.exception; return this.exception;
} }
/** /**
* The HTTP status value that this error page matches. * The HTTP status value that this error page matches (or {@code null} for a page that
* @return the status * matches by exception).
* @return the status or {@code null}
*/ */
public HttpStatus getStatus() { public HttpStatus getStatus() {
return this.status; return this.status;
...@@ -80,7 +83,7 @@ public class ErrorPage { ...@@ -80,7 +83,7 @@ public class ErrorPage {
* @return the status value (or 0 for a page that matches any status) * @return the status value (or 0 for a page that matches any status)
*/ */
public int getStatusCode() { public int getStatusCode() {
return this.status == null ? 0 : this.status.value(); return (this.status == null ? 0 : this.status.value());
} }
/** /**
...@@ -88,15 +91,15 @@ public class ErrorPage { ...@@ -88,15 +91,15 @@ public class ErrorPage {
* @return the exception type name (or {@code null} if there is none) * @return the exception type name (or {@code null} if there is none)
*/ */
public String getExceptionName() { public String getExceptionName() {
return this.exception == null ? null : this.exception.getName(); return (this.exception == null ? null : this.exception.getName());
} }
/** /**
* @return is this error page a global one (matches all unmatched status and exception * @return is this error page a global one (matches all unmatched status and exception
* types)? * types)
*/ */
public boolean isGlobal() { public boolean isGlobal() {
return this.status == null && this.exception == null; return (this.status == null && this.exception == null);
} }
@Override @Override
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -51,18 +51,28 @@ import org.springframework.stereotype.Component; ...@@ -51,18 +51,28 @@ import org.springframework.stereotype.Component;
* of that type in the context will be applied to this container). * of that type in the context will be applied to this container).
* *
* @author Dave Syer * @author Dave Syer
* * @author Phillip Webb
*/ */
@Component @Component
@Order(Ordered.HIGHEST_PRECEDENCE) @Order(Ordered.HIGHEST_PRECEDENCE)
public class ErrorWrapperEmbeddedServletContainerFactory extends public class ErrorWrapperEmbeddedServletContainerFactory extends
AbstractEmbeddedServletContainerFactory implements Filter { AbstractEmbeddedServletContainerFactory implements Filter {
// From RequestDispatcher but not referenced to remain compatible with Servlet 2.5
private static final String ERROR_EXCEPTION = "javax.servlet.error.exception";
private static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
private static final String ERROR_MESSAGE = "javax.servlet.error.message";
private static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
private String global; private String global;
private Map<Integer, String> statuses = new HashMap<Integer, String>(); private final Map<Integer, String> statuses = new HashMap<Integer, String>();
private Map<Class<? extends Throwable>, String> exceptions = new HashMap<Class<? extends Throwable>, String>(); private final Map<Class<?>, String> exceptions = new HashMap<Class<?>, String>();
@Override @Override
public void init(FilterConfig filterConfig) throws ServletException { public void init(FilterConfig filterConfig) throws ServletException {
...@@ -71,65 +81,90 @@ public class ErrorWrapperEmbeddedServletContainerFactory extends ...@@ -71,65 +81,90 @@ public class ErrorWrapperEmbeddedServletContainerFactory extends
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException { FilterChain chain) throws IOException, ServletException {
String errorPath; if (request instanceof HttpServletRequest
ErrorWrapperResponse wrapped = new ErrorWrapperResponse( && response instanceof HttpServletResponse) {
(HttpServletResponse) response); doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
}
else {
chain.doFilter(request, response);
}
}
private void doFilter(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
ErrorWrapperResponse wrapped = new ErrorWrapperResponse(response);
try { try {
chain.doFilter(request, wrapped); chain.doFilter(request, wrapped);
int status = wrapped.getStatus(); int status = wrapped.getStatus();
if (status >= 400) { if (status >= 400) {
errorPath = this.statuses.containsKey(status) ? this.statuses.get(status) handleErrorStatus(request, response, status, wrapped.getMessage());
: this.global;
if (errorPath != null) {
request.setAttribute("javax.servlet.error.status_code", status);
request.setAttribute("javax.servlet.error.message",
wrapped.getMessage());
((HttpServletRequest) request).getRequestDispatcher(errorPath)
.forward(request, response);
}
else {
((HttpServletResponse) response).sendError(status,
wrapped.getMessage());
}
} }
} }
catch (Throwable e) { catch (Throwable ex) {
Class<? extends Throwable> cls = e.getClass(); handleException(request, response, wrapped, ex);
errorPath = this.exceptions.containsKey(cls) ? this.exceptions.get(cls)
: this.global;
if (errorPath != null) {
request.setAttribute("javax.servlet.error.status_code", 500);
request.setAttribute("javax.servlet.error.exception", e);
request.setAttribute("javax.servlet.error.message", e.getMessage());
wrapped.sendError(500, e.getMessage());
((HttpServletRequest) request).getRequestDispatcher(errorPath).forward(
request, response);
}
else {
rethrow(e);
}
} }
} }
private void rethrow(Throwable e) throws IOException, ServletException { private void handleErrorStatus(HttpServletRequest request,
if (e instanceof RuntimeException) { HttpServletResponse response, int status, String message)
throw (RuntimeException) e; throws ServletException, IOException {
String errorPath = getErrorPath(this.statuses, status);
if (errorPath == null) {
response.sendError(status, message);
return;
} }
if (e instanceof Error) { setErrorAttributes(request, status, message);
throw (Error) e; request.getRequestDispatcher(errorPath).forward(request, response);
}
private void handleException(HttpServletRequest request,
HttpServletResponse response, ErrorWrapperResponse wrapped, Throwable ex)
throws IOException, ServletException {
String errorPath = getErrorPath(this.exceptions, ex.getClass());
if (errorPath == null) {
rethrow(ex);
return;
}
setErrorAttributes(request, 500, ex.getMessage());
request.setAttribute(ERROR_EXCEPTION, ex);
request.setAttribute(ERROR_EXCEPTION_TYPE, ex.getClass().getName());
wrapped.sendError(500, ex.getMessage());
request.getRequestDispatcher(errorPath).forward(request, response);
}
private String getErrorPath(Map<?, String> map, Object key) {
if (map.containsKey(key)) {
return map.get(key);
}
return this.global;
}
private void setErrorAttributes(ServletRequest request, int status, String message) {
request.setAttribute(ERROR_STATUS_CODE, status);
request.setAttribute(ERROR_MESSAGE, message);
}
private void rethrow(Throwable ex) throws IOException, ServletException {
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
if (ex instanceof Error) {
throw (Error) ex;
} }
if (e instanceof IOException) { if (ex instanceof IOException) {
throw (IOException) e; throw (IOException) ex;
} }
if (e instanceof ServletException) { if (ex instanceof ServletException) {
throw (ServletException) e; throw (ServletException) ex;
} }
throw new IllegalStateException("Unidentified Exception", e); throw new IllegalStateException(ex);
} }
@Override @Override
public EmbeddedServletContainer getEmbeddedServletContainer( public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) { ServletContextInitializer... initializers) {
return new EmbeddedServletContainer() { return new EmbeddedServletContainer() {
@Override @Override
...@@ -145,6 +180,7 @@ public class ErrorWrapperEmbeddedServletContainerFactory extends ...@@ -145,6 +180,7 @@ public class ErrorWrapperEmbeddedServletContainerFactory extends
return -1; return -1;
} }
}; };
} }
@Override @Override
...@@ -169,6 +205,7 @@ public class ErrorWrapperEmbeddedServletContainerFactory extends ...@@ -169,6 +205,7 @@ public class ErrorWrapperEmbeddedServletContainerFactory extends
private static class ErrorWrapperResponse extends HttpServletResponseWrapper { private static class ErrorWrapperResponse extends HttpServletResponseWrapper {
private int status; private int status;
private String message; private String message;
public ErrorWrapperResponse(HttpServletResponse response) { public ErrorWrapperResponse(HttpServletResponse response) {
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -84,7 +84,7 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit ...@@ -84,7 +84,7 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit
servletContext)); servletContext));
application.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class); application.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
application = configure(application); application = configure(application);
// Ensure error pages ar registered // Ensure error pages are registered
application.sources(ErrorWrapperEmbeddedServletContainerFactory.class); application.sources(ErrorWrapperEmbeddedServletContainerFactory.class);
return (WebApplicationContext) application.run(); return (WebApplicationContext) application.run();
} }
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,6 +18,7 @@ package org.springframework.boot.context.web; ...@@ -18,6 +18,7 @@ package org.springframework.boot.context.web;
import java.io.IOException; import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
...@@ -31,24 +32,30 @@ import org.springframework.mock.web.MockFilterChain; ...@@ -31,24 +32,30 @@ import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpServletResponse;
import static org.junit.Assert.assertEquals; import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/** /**
* Tests for {@link ErrorWrapperEmbeddedServletContainerFactory}.
*
* @author Dave Syer * @author Dave Syer
*/ */
public class ErrorWrapperEmbeddedServletContainerFactoryTests { public class ErrorWrapperEmbeddedServletContainerFactoryTests {
private ErrorWrapperEmbeddedServletContainerFactory filter = new ErrorWrapperEmbeddedServletContainerFactory(); private ErrorWrapperEmbeddedServletContainerFactory filter = new ErrorWrapperEmbeddedServletContainerFactory();
private MockHttpServletRequest request = new MockHttpServletRequest(); private MockHttpServletRequest request = new MockHttpServletRequest();
private MockHttpServletResponse response = new MockHttpServletResponse(); private MockHttpServletResponse response = new MockHttpServletResponse();
private MockFilterChain chain = new MockFilterChain(); private MockFilterChain chain = new MockFilterChain();
@Test @Test
public void notAnError() throws Exception { public void notAnError() throws Exception {
this.filter.doFilter(this.request, this.response, this.chain); this.filter.doFilter(this.request, this.response, this.chain);
assertEquals(this.request, this.chain.getRequest()); assertThat(this.chain.getRequest(), equalTo((ServletRequest) this.request));
assertEquals(this.response, assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getResponse(),
((HttpServletResponseWrapper) this.chain.getResponse()).getResponse()); equalTo((ServletResponse) this.response));
} }
@Test @Test
...@@ -63,10 +70,12 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests { ...@@ -63,10 +70,12 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests {
} }
}; };
this.filter.doFilter(this.request, this.response, this.chain); this.filter.doFilter(this.request, this.response, this.chain);
assertEquals(400, assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getStatus(),
((HttpServletResponseWrapper) this.chain.getResponse()).getStatus()); equalTo(400));
assertEquals(400, this.request.getAttribute("javax.servlet.error.status_code")); assertThat(this.request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE),
assertEquals("BAD", this.request.getAttribute("javax.servlet.error.message")); equalTo((Object) 400));
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_MESSAGE),
equalTo((Object) "BAD"));
} }
@Test @Test
...@@ -81,10 +90,12 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests { ...@@ -81,10 +90,12 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests {
} }
}; };
this.filter.doFilter(this.request, this.response, this.chain); this.filter.doFilter(this.request, this.response, this.chain);
assertEquals(400, assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getStatus(),
((HttpServletResponseWrapper) this.chain.getResponse()).getStatus()); equalTo(400));
assertEquals(400, this.request.getAttribute("javax.servlet.error.status_code")); assertThat(this.request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE),
assertEquals("BAD", this.request.getAttribute("javax.servlet.error.message")); equalTo((Object) 400));
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_MESSAGE),
equalTo((Object) "BAD"));
} }
@Test @Test
...@@ -99,9 +110,13 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests { ...@@ -99,9 +110,13 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests {
} }
}; };
this.filter.doFilter(this.request, this.response, this.chain); this.filter.doFilter(this.request, this.response, this.chain);
assertEquals(500, assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getStatus(),
((HttpServletResponseWrapper) this.chain.getResponse()).getStatus()); equalTo(500));
assertEquals(500, this.request.getAttribute("javax.servlet.error.status_code")); assertThat(this.request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE),
assertEquals("BAD", this.request.getAttribute("javax.servlet.error.message")); equalTo((Object) 500));
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_MESSAGE),
equalTo((Object) "BAD"));
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE),
equalTo((Object) RuntimeException.class.getName()));
} }
} }
...@@ -52,7 +52,7 @@ public class JavaLoggerSystemTests { ...@@ -52,7 +52,7 @@ public class JavaLoggerSystemTests {
@Before @Before
public void init() throws SecurityException, IOException { public void init() throws SecurityException, IOException {
defaultLocale = Locale.getDefault(); this.defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.ENGLISH); Locale.setDefault(Locale.ENGLISH);
this.logger = new Jdk14Logger(getClass().getName()); this.logger = new Jdk14Logger(getClass().getName());
} }
...@@ -62,7 +62,7 @@ public class JavaLoggerSystemTests { ...@@ -62,7 +62,7 @@ public class JavaLoggerSystemTests {
System.clearProperty("LOG_FILE"); System.clearProperty("LOG_FILE");
System.clearProperty("LOG_PATH"); System.clearProperty("LOG_PATH");
System.clearProperty("PID"); System.clearProperty("PID");
Locale.setDefault(defaultLocale); Locale.setDefault(this.defaultLocale);
} }
@Test @Test
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment