diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CompositeHealthIndicatorConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CompositeHealthIndicatorConfiguration.java index 33dc0885e6..b81dd28559 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CompositeHealthIndicatorConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/CompositeHealthIndicatorConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.core.ResolvableType; * * @param The health indicator type * @param T he bean source type + * @author Stephane Nicoll * @since 1.4.0 */ public abstract class CompositeHealthIndicatorConfiguration { @@ -61,8 +62,8 @@ public abstract class CompositeHealthIndicatorConfiguration { private final Map clients; private final ElasticsearchHealthIndicatorProperties properties; - SpringData(Map clients, + ElasticsearchSpringDataHealthIndicatorConfiguration(Map clients, ElasticsearchHealthIndicatorProperties properties) { this.clients = clients; this.properties = properties; @@ -72,12 +72,12 @@ class ElasticsearchHealthIndicatorConfiguration { @Configuration @ConditionalOnBean(JestClient.class) @ConditionalOnEnabledHealthIndicator("elasticsearch") - static class Jest extends + static class ElasticsearchJestHealthIndicatorConfiguration extends CompositeHealthIndicatorConfiguration { private final Map clients; - Jest(Map clients) { + ElasticsearchJestHealthIndicatorConfiguration(Map clients) { this.clients = clients; } @@ -88,9 +88,11 @@ class ElasticsearchHealthIndicatorConfiguration { } @Override - protected ElasticsearchJestHealthIndicator createHealthIndicator(JestClient client) { + protected ElasticsearchJestHealthIndicator createHealthIndicator( + JestClient client) { return new ElasticsearchJestHealthIndicator(client); } + } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java index 5b9dd66540..da763c61a4 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java @@ -98,8 +98,8 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; MongoDataAutoConfiguration.class, RabbitAutoConfiguration.class, RedisAutoConfiguration.class, SolrAutoConfiguration.class }) @EnableConfigurationProperties({ HealthIndicatorProperties.class }) -@Import({ ElasticsearchHealthIndicatorConfiguration.SpringData.class, - ElasticsearchHealthIndicatorConfiguration.Jest.class }) +@Import({ ElasticsearchHealthIndicatorConfiguration.ElasticsearchSpringDataHealthIndicatorConfiguration.class, + ElasticsearchHealthIndicatorConfiguration.ElasticsearchJestHealthIndicatorConfiguration.class }) public class HealthIndicatorAutoConfiguration { private final HealthIndicatorProperties properties; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java index 058ebe18b0..8b851243cf 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/ElasticsearchHealthIndicator.java @@ -70,4 +70,5 @@ public class ElasticsearchHealthIndicator extends AbstractHealthIndicator { builder.withDetail("initializingShards", response.getInitializingShards()); builder.withDetail("unassignedShards", response.getUnassignedShards()); } + } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchJestHealthIndicatorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchJestHealthIndicatorTests.java index 93548211e9..84f28c1ded 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchJestHealthIndicatorTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/ElasticsearchJestHealthIndicatorTests.java @@ -59,7 +59,6 @@ public class ElasticsearchJestHealthIndicatorTests { public void elasticSearchIsDown() throws IOException { given(this.jestClient.execute(any(Action.class))).willThrow( new CouldNotConnectException("http://localhost:9200", new IOException())); - Health health = this.healthIndicator.health(); assertThat(health.getStatus()).isEqualTo(Status.DOWN); } @@ -69,7 +68,6 @@ public class ElasticsearchJestHealthIndicatorTests { public void elasticSearchIsOutOfService() throws IOException { given(this.jestClient.execute(any(Action.class))) .willReturn(createJestResult(4, 1)); - Health health = this.healthIndicator.health(); assertThat(health.getStatus()).isEqualTo(Status.OUT_OF_SERVICE); } @@ -77,7 +75,6 @@ public class ElasticsearchJestHealthIndicatorTests { private static JestResult createJestResult(int shards, int failedShards) { String json = String.format("{_shards: {\n" + "total: %s,\n" + "successful: %s,\n" + "failed: %s\n" + "}}", shards, shards - failedShards, failedShards); - SearchResult searchResult = new SearchResult(new Gson()); searchResult.setJsonString(json); searchResult.setJsonObject(new JsonParser().parse(json).getAsJsonObject()); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jest/JestAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jest/JestAutoConfiguration.java index 9ac19e1dd2..3a95540965 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jest/JestAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jest/JestAutoConfiguration.java @@ -48,7 +48,8 @@ public class JestAutoConfiguration { private final ObjectProvider gsonProvider; - public JestAutoConfiguration(JestProperties properties, ObjectProvider gsonProvider) { + public JestAutoConfiguration(JestProperties properties, + ObjectProvider gsonProvider) { this.properties = properties; this.gsonProvider = gsonProvider; } @@ -62,8 +63,8 @@ public class JestAutoConfiguration { } protected HttpClientConfig createHttpClientConfig() { - HttpClientConfig.Builder builder = new HttpClientConfig - .Builder(this.properties.getUris()); + HttpClientConfig.Builder builder = new HttpClientConfig.Builder( + this.properties.getUris()); if (StringUtils.hasText(this.properties.getUsername())) { builder.defaultCredentials(this.properties.getUsername(), this.properties.getPassword()); @@ -73,8 +74,7 @@ public class JestAutoConfiguration { builder.gson(gson); } return builder.connTimeout(this.properties.getConnectionTimeout()) - .readTimeout(this.properties.getReadTimeout()) - .build(); + .readTimeout(this.properties.getReadTimeout()).build(); } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java index 733f91a7f7..ef155ef193 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/artemis/ArtemisConnectionFactoryFactory.java @@ -132,7 +132,7 @@ class ArtemisConnectionFactoryFactory { Constructor constructor = factoryClass.getConstructor(boolean.class, TransportConfiguration[].class); T connectionFactory = constructor.newInstance(false, - new TransportConfiguration[] {transportConfiguration}); + new TransportConfiguration[] { transportConfiguration }); String user = this.properties.getUser(); if (StringUtils.hasText(user)) { connectionFactory.setUser(user); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQConnectionFactoryFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQConnectionFactoryFactory.java index 2395cce3a2..637fbe3be4 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQConnectionFactoryFactory.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQConnectionFactoryFactory.java @@ -112,9 +112,10 @@ class HornetQConnectionFactoryFactory { this.properties.getEmbedded().generateTransportParameters()); ServerLocator serviceLocator = HornetQClient .createServerLocatorWithoutHA(transportConfiguration); - Constructor constructor = factoryClass.getDeclaredConstructor(HornetQProperties.class, - ServerLocator.class); - return BeanUtils.instantiateClass(constructor, this.properties, serviceLocator); + Constructor constructor = factoryClass + .getDeclaredConstructor(HornetQProperties.class, ServerLocator.class); + return BeanUtils.instantiateClass(constructor, this.properties, + serviceLocator); } catch (NoClassDefFoundError ex) { throw new IllegalStateException("Unable to create InVM " @@ -130,8 +131,8 @@ class HornetQConnectionFactoryFactory { params.put(TransportConstants.PORT_PROP_NAME, this.properties.getPort()); TransportConfiguration transportConfiguration = new TransportConfiguration( NettyConnectorFactory.class.getName(), params); - Constructor constructor = factoryClass.getDeclaredConstructor(HornetQProperties.class, - boolean.class, TransportConfiguration[].class); + Constructor constructor = factoryClass.getDeclaredConstructor( + HornetQProperties.class, boolean.class, TransportConfiguration[].class); return BeanUtils.instantiateClass(constructor, this.properties, false, new TransportConfiguration[] { transportConfiguration }); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQXAConnectionFactoryConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQXAConnectionFactoryConfiguration.java index 174c8145fc..0175a080a1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQXAConnectionFactoryConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/HornetQXAConnectionFactoryConfiguration.java @@ -46,7 +46,7 @@ class HornetQXAConnectionFactoryConfiguration { @Bean(name = { "jmsConnectionFactory", "xaJmsConnectionFactory" }) public ConnectionFactory jmsConnectionFactory(ListableBeanFactory beanFactory, HornetQProperties properties, XAConnectionFactoryWrapper wrapper) - throws Exception { + throws Exception { return wrapper.wrapConnectionFactory( new HornetQConnectionFactoryFactory(beanFactory, properties) .createConnectionFactory( diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQConnectionFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQConnectionFactory.java index 6b6b36dd7b..d39c162f03 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQConnectionFactory.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQConnectionFactory.java @@ -47,6 +47,7 @@ class SpringBootHornetQConnectionFactory extends HornetQConnectionFactory { this.properties = properties; } + @Override public Connection createConnection() throws JMSException { String user = this.properties.getUser(); if (StringUtils.hasText(user)) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQXAConnectionFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQXAConnectionFactory.java index 91431ddd02..a94658d26b 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQXAConnectionFactory.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jms/hornetq/SpringBootHornetQXAConnectionFactory.java @@ -47,6 +47,7 @@ class SpringBootHornetQXAConnectionFactory extends HornetQXAConnectionFactory { this.properties = properties; } + @Override public Connection createConnection() throws JMSException { String user = this.properties.getUser(); if (StringUtils.hasText(user)) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java index 95b8471c73..ade1e5be94 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java @@ -209,7 +209,8 @@ public class MongoProperties { } String host = this.host == null ? "localhost" : this.host; int port = determinePort(environment); - return new MongoClient(Collections.singletonList(new ServerAddress(host, port)), + return new MongoClient( + Collections.singletonList(new ServerAddress(host, port)), credentials, options); } // The options and credentials are in the URI diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java index 65f4d5bba6..7fbf20ab4f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java @@ -226,14 +226,13 @@ public class WebMvcAutoConfiguration { @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "spring.mvc", name = "locale") public LocaleResolver localeResolver() { - if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { + if (this.mvcProperties + .getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } - else { - AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); - localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); - return localeResolver; - } + AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); + localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); + return localeResolver; } @Bean diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java index 690f7d98a5..0817991039 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcProperties.java @@ -42,7 +42,8 @@ public class WebMvcProperties { private DefaultMessageCodesResolver.Format messageCodesResolverFormat; /** - * Locale to use. By default, this locale is overridden by the "Accept-Language" header. + * Locale to use. By default, this locale is overridden by the "Accept-Language" + * header. */ private Locale locale; @@ -261,8 +262,8 @@ public class WebMvcProperties { FIXED, /** - * Use the "Accept-Language" header or the configured locale if the header - * is not set. + * Use the "Accept-Language" header or the configured locale if the header is not + * set. */ ACCEPT_HEADER diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java index d63b8575ba..9307714b15 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java @@ -92,7 +92,8 @@ public class MongoAutoConfigurationTests { MongoClient mongo = this.context.getBean(MongoClient.class); MongoClientOptions options = mongo.getMongoClientOptions(); assertThat(options.isSslEnabled()).isTrue(); - assertThat(options.getSocketFactory()).isSameAs(this.context.getBean("mySocketFactory")); + assertThat(options.getSocketFactory()) + .isSameAs(this.context.getBean("mySocketFactory")); } @Configuration @@ -110,7 +111,8 @@ public class MongoAutoConfigurationTests { @Bean public MongoClientOptions mongoClientOptions() { - return MongoClientOptions.builder().sslEnabled(true).socketFactory(mySocketFactory()).build(); + return MongoClientOptions.builder().sslEnabled(true) + .socketFactory(mySocketFactory()).build(); } @Bean diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index f4af8b5306..ad059ec16e 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -2637,20 +2637,21 @@ and http://hibernate.org/orm/documentation/[Hibernate] reference documentation. [NOTE] ==== As of Hibernate 5.2, the `hibernate-entitymanager` module has been merged in -`hibernate-core`. If you need to downgrade, you'll have to add `hibernate-entitymanager` -yourself, something like: - -```xml - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.hibernate - hibernate-entitymanager - ${hibernate.version} - -``` +`hibernate-core`. If you need to downgrade, you'll need to directly add the +dependency yourself, for example: + +[source,xml,indent=0] +---- + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + +---- As Hibernate does not bundle the `hibernate-entitymanager` and `hibernate-java8` artifacts anymore, Spring Boot doesn't provide dependency management for them. @@ -3364,6 +3365,7 @@ configured: To take full control over the registration, define a `JestClient` bean. + [[boot-features-connecting-to-elasticsearch]] [[boot-features-connecting-to-elasticsearch-spring-data]] ==== Connecting to Elasticsearch using Spring Data diff --git a/spring-boot-samples/spring-boot-sample-jetty-jsp/src/main/java/sample/jetty/jsp/SampleJettyJspApplication.java b/spring-boot-samples/spring-boot-sample-jetty-jsp/src/main/java/sample/jetty/jsp/SampleJettyJspApplication.java index 880531aabd..fae369a65f 100644 --- a/spring-boot-samples/spring-boot-sample-jetty-jsp/src/main/java/sample/jetty/jsp/SampleJettyJspApplication.java +++ b/spring-boot-samples/spring-boot-sample-jetty-jsp/src/main/java/sample/jetty/jsp/SampleJettyJspApplication.java @@ -19,7 +19,7 @@ package sample.jetty.jsp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.context.web.SpringBootServletInitializer; +import org.springframework.boot.web.support.SpringBootServletInitializer; @SpringBootApplication public class SampleJettyJspApplication extends SpringBootServletInitializer { diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java index fed7366cf5..47ea136121 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/ConfigurationMetadataAnnotationProcessor.java @@ -172,12 +172,15 @@ public class ConfigurationMetadataAnnotationProcessor extends AbstractProcessor Element returns = this.processingEnv.getTypeUtils() .asElement(element.getReturnType()); if (returns instanceof TypeElement) { - ItemMetadata group = ItemMetadata.newGroup(prefix, this.typeUtils.getType(returns), + ItemMetadata group = ItemMetadata.newGroup(prefix, + this.typeUtils.getType(returns), this.typeUtils.getType(element.getEnclosingElement()), element.toString()); if (this.metadataCollector.hasSimilarGroup(group)) { this.processingEnv.getMessager().printMessage(Kind.ERROR, - "Duplicate `@ConfigurationProperties` definition for prefix '" + prefix + "'", element); + "Duplicate `@ConfigurationProperties` definition for prefix '" + + prefix + "'", + element); } else { this.metadataCollector.add(group); diff --git a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/DoubleRegistrationProperties.java b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/DoubleRegistrationProperties.java index d03030e10e..e80493165e 100644 --- a/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/DoubleRegistrationProperties.java +++ b/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/specific/DoubleRegistrationProperties.java @@ -19,8 +19,7 @@ package org.springframework.boot.configurationsample.specific; import org.springframework.boot.configurationsample.ConfigurationProperties; /** - * Test that the same type can be registered several times if the prefix is - * different. + * Test that the same type can be registered several times if the prefix is different. * * @author Stephane Nicoll */ diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JasperInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JasperInitializer.java index 813d15620e..57847b15b6 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JasperInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JasperInitializer.java @@ -31,13 +31,19 @@ import org.eclipse.jetty.webapp.WebAppContext; import org.springframework.util.ClassUtils; /** - * Jetty {@link AbstractLifeCycle} to initialize jasper. + * Jetty {@link AbstractLifeCycle} to initialize Jasper. * * @author Vladimir Tsanev + * @author Phillip Webb */ -public class JasperInitializer extends AbstractLifeCycle { +class JasperInitializer extends AbstractLifeCycle { + + private static final String[] INITIALIZER_CLASSES = { + "org.eclipse.jetty.apache.jsp.JettyJasperInitializer", + "org.apache.jasper.servlet.JasperInitializer" }; private final WebAppContext context; + private final ServletContainerInitializer initializer; JasperInitializer(WebAppContext context) { @@ -45,24 +51,17 @@ public class JasperInitializer extends AbstractLifeCycle { this.initializer = newInitializer(); } - private static ServletContainerInitializer newInitializer() { - try { + private ServletContainerInitializer newInitializer() { + for (String className : INITIALIZER_CLASSES) { try { - return (ServletContainerInitializer) ClassUtils - .forName("org.eclipse.jetty.apache.jsp.JettyJasperInitializer", - null) - .newInstance(); + Class initializerClass = ClassUtils.forName(className, null); + return (ServletContainerInitializer) initializerClass.newInstance(); } catch (Exception ex) { - // try the original initializer - return (ServletContainerInitializer) ClassUtils - .forName("org.apache.jasper.servlet.JasperInitializer", null) - .newInstance(); + // Ignore } } - catch (Exception ex) { - return null; - } + return null; } @Override @@ -71,22 +70,14 @@ public class JasperInitializer extends AbstractLifeCycle { return; } try { - URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() { - @Override - public URLStreamHandler createURLStreamHandler(String protocol) { - if ("war".equals(protocol)) { - return new WarUrlStreamHandler(); - } - return null; - } - }); + URL.setURLStreamHandlerFactory(new WarUrlStreamHandlerFactory()); } catch (Error ex) { // Ignore } ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(this.context.getClassLoader()); try { + Thread.currentThread().setContextClassLoader(this.context.getClassLoader()); try { setExtendedListenerTypes(true); this.initializer.onStartup(null, this.context.getServletContext()); @@ -109,23 +100,36 @@ public class JasperInitializer extends AbstractLifeCycle { } } + /** + * {@link URLStreamHandlerFactory} to support {@literal war} protocol. + */ + private static class WarUrlStreamHandlerFactory implements URLStreamHandlerFactory { + + @Override + public URLStreamHandler createURLStreamHandler(String protocol) { + if ("war".equals(protocol)) { + return new WarUrlStreamHandler(); + } + return null; + } + + } + /** * {@link URLStreamHandler} for {@literal war} protocol compatible with jasper's * {@link URL urls} produced by * {@link org.apache.tomcat.util.scan.JarFactory#getJarEntryURL(URL, String)}. */ - static class WarUrlStreamHandler extends URLStreamHandler { + private static class WarUrlStreamHandler extends URLStreamHandler { @Override protected void parseURL(URL u, String spec, int start, int limit) { String path = "jar:" + spec.substring("war:".length()); - int separator = path.indexOf("*/"); if (separator >= 0) { path = path.substring(0, separator) + "!/" + path.substring(separator + 2); } - setURL(u, u.getProtocol(), "", -1, null, null, path, null, null); } @@ -133,12 +137,13 @@ public class JasperInitializer extends AbstractLifeCycle { protected URLConnection openConnection(URL u) throws IOException { return new WarURLConnection(u); } + } /** * {@link URLConnection} to support {@literal war} protocol. */ - static class WarURLConnection extends URLConnection { + private static class WarURLConnection extends URLConnection { private final URLConnection connection; @@ -160,6 +165,7 @@ public class JasperInitializer extends AbstractLifeCycle { connect(); return this.connection.getInputStream(); } + } } diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/SslStoreProviderUrlStreamHandlerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/SslStoreProviderUrlStreamHandlerFactory.java new file mode 100644 index 0000000000..2539fa8e29 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/SslStoreProviderUrlStreamHandlerFactory.java @@ -0,0 +1,113 @@ +/* + * Copyright 2012-2016 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 org.springframework.boot.context.embedded.tomcat; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.security.KeyStore; + +import org.springframework.boot.context.embedded.SslStoreProvider; + +/** + * A {@link URLStreamHandlerFactory} that provides a {@link URLStreamHandler} for + * accessing an {@link SslStoreProvider}'s key store and trust store from a URL. + * + * @author Andy Wilkinson + */ +class SslStoreProviderUrlStreamHandlerFactory implements URLStreamHandlerFactory { + + private static final String PROTOCOL = "springbootssl"; + + private static final String KEY_STORE_PATH = "keyStore"; + + static final String KEY_STORE_URL = PROTOCOL + ":" + KEY_STORE_PATH; + + private static final String TRUST_STORE_PATH = "trustStore"; + + static final String TRUST_STORE_URL = PROTOCOL + ":" + TRUST_STORE_PATH; + + private final SslStoreProvider sslStoreProvider; + + SslStoreProviderUrlStreamHandlerFactory(SslStoreProvider sslStoreProvider) { + this.sslStoreProvider = sslStoreProvider; + } + + @Override + public URLStreamHandler createURLStreamHandler(String protocol) { + if (PROTOCOL.equals(protocol)) { + return new URLStreamHandler() { + + @Override + protected URLConnection openConnection(URL url) throws IOException { + try { + if (KEY_STORE_PATH.equals(url.getPath())) { + return new KeyStoreUrlConnection(url, + SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider + .getKeyStore()); + } + if (TRUST_STORE_PATH.equals(url.getPath())) { + return new KeyStoreUrlConnection(url, + SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider + .getTrustStore()); + } + } + catch (Exception ex) { + throw new IOException(ex); + } + throw new IOException("Invalid path: " + url.getPath()); + } + }; + } + return null; + } + + private static final class KeyStoreUrlConnection extends URLConnection { + + private final KeyStore keyStore; + + private KeyStoreUrlConnection(URL url, KeyStore keyStore) { + super(url); + this.keyStore = keyStore; + } + + @Override + public void connect() throws IOException { + + } + + @Override + public InputStream getInputStream() throws IOException { + + try { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + this.keyStore.store(stream, new char[0]); + return new ByteArrayInputStream(stream.toByteArray()); + } + catch (Exception ex) { + throw new IOException(ex); + } + } + + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index e3e40a7688..32d44e1081 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -16,19 +16,11 @@ package org.springframework.boot.context.embedded.tomcat; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; import java.nio.charset.Charset; -import java.security.KeyStore; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -63,7 +55,6 @@ import org.apache.coyote.http11.AbstractHttp11Protocol; import org.apache.coyote.http11.Http11NioProtocol; import org.apache.tomcat.util.net.SSLHostConfig; -import org.springframework.beans.BeanUtils; import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.Compression; import org.springframework.boot.context.embedded.EmbeddedServletContainer; @@ -79,7 +70,6 @@ import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; import org.springframework.util.ResourceUtils; import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; @@ -702,158 +692,6 @@ public class TomcatEmbeddedServletContainerFactory return this.uriEncoding; } - /** - * A {@link URLStreamHandlerFactory} that provides a {@link URLStreamHandler} for - * accessing an {@link SslStoreProvider}'s key store and trust store from a URL. - */ - private static final class SslStoreProviderUrlStreamHandlerFactory - implements URLStreamHandlerFactory { - - private static final String PROTOCOL = "springbootssl"; - - private static final String KEY_STORE_PATH = "keyStore"; - - private static final String KEY_STORE_URL = PROTOCOL + ":" + KEY_STORE_PATH; - - private static final String TRUST_STORE_PATH = "trustStore"; - - private static final String TRUST_STORE_URL = PROTOCOL + ":" + TRUST_STORE_PATH; - - private final SslStoreProvider sslStoreProvider; - - private SslStoreProviderUrlStreamHandlerFactory( - SslStoreProvider sslStoreProvider) { - this.sslStoreProvider = sslStoreProvider; - } - - @Override - public URLStreamHandler createURLStreamHandler(String protocol) { - if (PROTOCOL.equals(protocol)) { - return new URLStreamHandler() { - - @Override - protected URLConnection openConnection(URL url) throws IOException { - try { - if (KEY_STORE_PATH.equals(url.getPath())) { - return new KeyStoreUrlConnection(url, - SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider - .getKeyStore()); - } - if (TRUST_STORE_PATH.equals(url.getPath())) { - return new KeyStoreUrlConnection(url, - SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider - .getTrustStore()); - } - } - catch (Exception ex) { - throw new IOException(ex); - } - throw new IOException("Invalid path: " + url.getPath()); - } - }; - } - return null; - } - - private static final class KeyStoreUrlConnection extends URLConnection { - - private final KeyStore keyStore; - - private KeyStoreUrlConnection(URL url, KeyStore keyStore) { - super(url); - this.keyStore = keyStore; - } - - @Override - public void connect() throws IOException { - - } - - @Override - public InputStream getInputStream() throws IOException { - - try { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - this.keyStore.store(stream, new char[0]); - return new ByteArrayInputStream(stream.toByteArray()); - } - catch (Exception ex) { - throw new IOException(ex); - } - } - - } - } - - private static class TomcatErrorPage { - - private static final String ERROR_PAGE_CLASS = "org.apache.tomcat.util.descriptor.web.ErrorPage"; - - private static final String LEGACY_ERROR_PAGE_CLASS = "org.apache.catalina.deploy.ErrorPage"; - - private final String location; - - private final String exceptionType; - - private final int errorCode; - - private final Object nativePage; - - TomcatErrorPage(ErrorPage errorPage) { - this.location = errorPage.getPath(); - this.exceptionType = errorPage.getExceptionName(); - this.errorCode = errorPage.getStatusCode(); - this.nativePage = createNativePage(errorPage); - } - - private Object createNativePage(ErrorPage errorPage) { - Object nativePage = null; - try { - if (ClassUtils.isPresent(ERROR_PAGE_CLASS, null)) { - nativePage = BeanUtils - .instantiate(ClassUtils.forName(ERROR_PAGE_CLASS, null)); - } - else if (ClassUtils.isPresent(LEGACY_ERROR_PAGE_CLASS, null)) { - nativePage = BeanUtils.instantiate( - ClassUtils.forName(LEGACY_ERROR_PAGE_CLASS, null)); - } - } - catch (ClassNotFoundException ex) { - // Swallow and continue - } - catch (LinkageError ex) { - // Swallow and continue - } - return nativePage; - } - - public void addToContext(Context context) { - Assert.state(this.nativePage != null, - "Neither Tomcat 7 nor 8 detected so no native error page exists"); - if (ClassUtils.isPresent(ERROR_PAGE_CLASS, null)) { - org.apache.tomcat.util.descriptor.web.ErrorPage errorPage = (org.apache.tomcat.util.descriptor.web.ErrorPage) this.nativePage; - errorPage.setLocation(this.location); - errorPage.setErrorCode(this.errorCode); - errorPage.setExceptionType(this.exceptionType); - context.addErrorPage(errorPage); - } - else { - callMethod(this.nativePage, "setLocation", this.location, String.class); - callMethod(this.nativePage, "setErrorCode", this.errorCode, int.class); - callMethod(this.nativePage, "setExceptionType", this.exceptionType, - String.class); - callMethod(context, "addErrorPage", this.nativePage, - this.nativePage.getClass()); - } - } - - private void callMethod(Object target, String name, Object value, Class type) { - Method method = ReflectionUtils.findMethod(target.getClass(), name, type); - ReflectionUtils.invokeMethod(method, target, value); - } - - } - /** * {@link LifecycleListener} that stores an empty merged web.xml. This is critical for * Jasper to prevent warnings about missing web.xml files and to enable EL. diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatErrorPage.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatErrorPage.java new file mode 100644 index 0000000000..86ac295f1d --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatErrorPage.java @@ -0,0 +1,102 @@ +/* + * Copyright 2012-2016 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 org.springframework.boot.context.embedded.tomcat; + +import java.lang.reflect.Method; + +import org.apache.catalina.Context; + +import org.springframework.beans.BeanUtils; +import org.springframework.boot.web.servlet.ErrorPage; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; + +/** + * Tomcat specific management for an {@link ErrorPage}. + * + * @author Dave Syer + * @author Phillip Webb + */ +class TomcatErrorPage { + + private static final String ERROR_PAGE_CLASS = "org.apache.tomcat.util.descriptor.web.ErrorPage"; + + private static final String LEGACY_ERROR_PAGE_CLASS = "org.apache.catalina.deploy.ErrorPage"; + + private final String location; + + private final String exceptionType; + + private final int errorCode; + + private final Object nativePage; + + TomcatErrorPage(ErrorPage errorPage) { + this.location = errorPage.getPath(); + this.exceptionType = errorPage.getExceptionName(); + this.errorCode = errorPage.getStatusCode(); + this.nativePage = createNativePage(errorPage); + } + + private Object createNativePage(ErrorPage errorPage) { + Object nativePage = null; + try { + if (ClassUtils.isPresent(ERROR_PAGE_CLASS, null)) { + nativePage = BeanUtils + .instantiate(ClassUtils.forName(ERROR_PAGE_CLASS, null)); + } + else if (ClassUtils.isPresent(LEGACY_ERROR_PAGE_CLASS, null)) { + nativePage = BeanUtils + .instantiate(ClassUtils.forName(LEGACY_ERROR_PAGE_CLASS, null)); + } + } + catch (ClassNotFoundException ex) { + // Swallow and continue + } + catch (LinkageError ex) { + // Swallow and continue + } + return nativePage; + } + + public void addToContext(Context context) { + Assert.state(this.nativePage != null, + "Neither Tomcat 7 nor 8 detected so no native error page exists"); + if (ClassUtils.isPresent(ERROR_PAGE_CLASS, null)) { + org.apache.tomcat.util.descriptor.web.ErrorPage errorPage = (org.apache.tomcat.util.descriptor.web.ErrorPage) this.nativePage; + errorPage.setLocation(this.location); + errorPage.setErrorCode(this.errorCode); + errorPage.setExceptionType(this.exceptionType); + context.addErrorPage(errorPage); + } + else { + callMethod(this.nativePage, "setLocation", this.location, String.class); + callMethod(this.nativePage, "setErrorCode", this.errorCode, int.class); + callMethod(this.nativePage, "setExceptionType", this.exceptionType, + String.class); + callMethod(context, "addErrorPage", this.nativePage, + this.nativePage.getClass()); + } + } + + private void callMethod(Object target, String name, Object value, Class type) { + Method method = ReflectionUtils.findMethod(target.getClass(), name, type); + ReflectionUtils.invokeMethod(method, target, value); + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java b/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java index 3fd6ab396b..fcc92a5095 100644 --- a/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java +++ b/spring-boot/src/main/java/org/springframework/boot/json/GsonJsonParser.java @@ -33,10 +33,9 @@ import com.google.gson.reflect.TypeToken; */ public class GsonJsonParser implements JsonParser { - private static final TypeToken> LIST_TYPE = new TypeToken>() { - }; - private static final TypeToken> MAP_TYPE = new TypeToken>() { - }; + private static final TypeToken MAP_TYPE = new MapTypeToken(); + + private static final TypeToken LIST_TYPE = new ListTypeToken(); private Gson gson = new GsonBuilder().create(); @@ -62,4 +61,12 @@ public class GsonJsonParser implements JsonParser { throw new IllegalArgumentException("Cannot parse JSON"); } + private static final class MapTypeToken extends TypeToken> { + + } + + private static final class ListTypeToken extends TypeToken> { + + } + } diff --git a/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java b/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java index 298d5d73db..c7a7c162da 100644 --- a/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java +++ b/spring-boot/src/main/java/org/springframework/boot/json/JacksonJsonParser.java @@ -30,10 +30,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; */ public class JacksonJsonParser implements JsonParser { - private static final TypeReference> LIST_TYPE = new TypeReference>() { - }; - private static final TypeReference> MAP_TYPE = new TypeReference>() { - }; + private static final TypeReference MAP_TYPE = new MapTypeReference(); + + private static final TypeReference LIST_TYPE = new ListTypeReference(); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -57,4 +56,12 @@ public class JacksonJsonParser implements JsonParser { } } + private static class MapTypeReference extends TypeReference> { + + }; + + private static class ListTypeReference extends TypeReference> { + + }; + } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/scan/TestEntityScanTests.java b/spring-boot/src/test/java/org/springframework/boot/context/scan/TestEntityScanTests.java index d49e0df778..7f60ced3f2 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/scan/TestEntityScanTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/scan/TestEntityScanTests.java @@ -79,12 +79,10 @@ public class TestEntityScanTests { @Test public void valueAndBasePackagesThrows() throws Exception { this.thrown.expect(AnnotationConfigurationException.class); - this.thrown.expectMessage(allOf( - containsString("'value'"), - containsString("'basePackages'"), - containsString("com.mycorp.entity"), + this.thrown.expectMessage(allOf(containsString("'value'"), + containsString("'basePackages'"), containsString("com.mycorp.entity"), containsString("com.mycorp"))); - new AnnotationConfigApplicationContext(ValueAndBasePackages.class); + this.context = new AnnotationConfigApplicationContext(ValueAndBasePackages.class); } @Test diff --git a/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java index 4c450f0289..6fb6194459 100644 --- a/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/ServletComponentScanRegistrarTests.java @@ -78,12 +78,10 @@ public class ServletComponentScanRegistrarTests { @Test public void packagesConfiguredWithBothValueAndBasePackages() { this.thrown.expect(AnnotationConfigurationException.class); - this.thrown.expectMessage(allOf( - containsString("'value'"), - containsString("'basePackages'"), - containsString("com.example.foo"), + this.thrown.expectMessage(allOf(containsString("'value'"), + containsString("'basePackages'"), containsString("com.example.foo"), containsString("com.example.bar"))); - new AnnotationConfigApplicationContext(ValueAndBasePackages.class); + this.context = new AnnotationConfigApplicationContext(ValueAndBasePackages.class); } @Test