Merge branch '1.5.x'

pull/8103/merge
Phillip Webb 8 years ago
commit 17451c5e7a

@ -1,18 +1,19 @@
open_source_license.txt
open_source_licenses.txt
Spring Boot CLI
==================================================================
GoPivotal makes available all content in this download ("Content").
Pivotal makes available all content in this download ("Content").
Unless otherwise indicated below, the Content is provided to you under
the terms and conditions of the Eclipse Public License Version 1.0 ("EPL").
A copy of the EPL is available in the file called license.txt. For
purposes of the EPL, "Program" will mean the Content.
the terms and conditions of the Apache License 2.0 (the "License"). A
copy of the license is available in the file called LICENSE.txt or you
may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
The following copyright statements and licenses apply to various open
source software packages (or portions thereof) that are distributed with
this Content.
this content.
=================================================================
@ -28,16 +29,43 @@ associated with each component.
SECTION 1: BSD-STYLE, MIT-STYLE, OR SIMILAR STYLE LICENSES
>>> antlr:antlr:2.7.7
>>> net.sf.jopt-simple:jopt-simple:4.5
>>> org.ow2.asm:asm:4.1
>>> JLine (jline:jline)
>>> JOpt Simple (net.sf.jopt-simple:jopt-simple)
>>> ASM 4.0 (org.ow2.asm:asm)
SECTION 2: Apache License, V2.0
>>> org.codehaus.groovy:groovy:2.1
>>> org.apache.ivy:ivy:2.3.0
>>> JSON library from Android SDK (com.vaadin.external.google:android-json)
>>> Apache Commons Codec (commons-codec:commons-codec)
>>> Apache HttpClient (org.apache.httpcomponents:httpclient)
>>> Apache HttpCore (org.apache.httpcomponents:httpcore)
>>> Plexus Cipher: encryption/decryption Component (org.sonatype.plexus:plexus-cipher)
>>> Plexus Security Dispatcher Component (org.sonatype.plexus:plexus-sec-dispatcher)
>>> Apache Commons Logging (commons-logging:commons-logging)
>>> Apache Groovy (org.codehaus.groovy:groovy)
>>> Maven Aether Provider (org.apache.maven:maven-aether-provider)
>>> Maven Model (org.apache.maven:maven-model)
>>> Maven Model Builder (org.apache.maven:maven-model-builder)
>>> Maven Repository Metadata Model (org.apache.maven:maven-repository-metadata)
>>> Maven Settings (org.apache.maven:maven-settings)
>>> Maven Settings Builder (org.apache.maven:maven-settings-builder)
>>> Plexus :: Component Annotations (org.codehaus.plexus:plexus-component-annotations)
>>> Plexus Common Utilities (org.codehaus.plexus:plexus-utils)
>>> Plexus Component API (org.codehaus.plexus:plexus-component-api)
>>> Plexus Interpolation API (org.codehaus.plexus:plexus-interpolation)
SECTION 3: Eclipse Public License, Version 1.0
>>> Aether API (org.eclipse.aether:aether-api)
>>> Aether Connector Basic (org.eclipse.aether:aether-connector-basic)
>>> Aether Implementation (org.eclipse.aether:aether-impl)
>>> Aether SPI (org.eclipse.aether:aether-spi)
>>> Aether Transport File (org.eclipse.aether:aether-transport-file)
>>> Aether Transport HTTP (org.eclipse.aether:aether-transport-http)
>>> Aether Utilities (org.eclipse.aether:aether-util)
--------------- SECTION 1: BSD-STYLE, MIT-STYLE, OR SIMILAR STYLE LICENSES ----------
@ -45,38 +73,41 @@ SECTION 2: Apache License, V2.0
BSD-STYLE, MIT-STYLE, OR SIMILAR STYLE LICENSES are applicable to the following component(s).
>>> antlr:antlr:2.7.7
SOFTWARE RIGHTS
ANTLR 1989-2006 Developed by Terence Parr
Partially supported by University of San Francisco & jGuru.com
We reserve no legal rights to the ANTLR--it is fully in the
public domain. An individual or company may do whatever
they wish with source code distributed with ANTLR or the
code generated by ANTLR, including the incorporation of
ANTLR, or its output, into commerical software.
>>> JLine (jline:jline)
We encourage users to develop software with ANTLR. However,
we do ask that credit is given to us for developing
ANTLR. By "credit", we mean that if you use ANTLR or
incorporate any source code into one of your programs
(commercial product, research project, or otherwise) that
you acknowledge this fact somewhere in the documentation,
research report, etc... If you like ANTLR and have
developed a nice tool with the output, please mention that
you developed it using ANTLR. In addition, we ask that the
headers remain intact in our source code. As long as these
guidelines are kept, we expect to continue enhancing this
system and expect to make other tools available as they are
completed.
Copyright (c) 2002-2006, Marc Prud'hommeaux <mwp1@cornell.edu>
All rights reserved.
The primary ANTLR guy:
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with
the distribution.
Neither the name of JLine nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
Terence Parr
parrt@cs.usfca.edu
parrt@antlr.org
>>> net.sf.jopt-simple:jopt-simple:4.5
@ -103,7 +134,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
>>> org.ow2.asm:asm:4.1
>>> org.ow2.asm:asm
Copyright (c) 2000-2011 INRIA, France Telecom
All rights reserved.
@ -136,12 +167,28 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
--------------- SECTION 2: Apache License, V2.0 ----------
Apache License, V2.0 is applicable to the following component(s).
>>> org.codehaus.groovy:groovy:2.1
>>> org.apache.httpcomponents:httpclient
>>> org.apache.httpcomponents:httpcore
>>> org.sonatype.plexus:plexus-cipher
>>> org.sonatype.plexus:plexus-sec-dispatcher
>>> commons-logging:commons-logging
>>> org.codehaus.groovy:groovy
>>> org.apache.maven:maven-aether-provider
>>> org.apache.maven:maven-model
>>> org.apache.maven:maven-model-builder
>>> org.apache.maven:maven-repository-metadata
>>> org.apache.maven:maven-settings
>>> org.apache.maven:maven-settings-builder
>>> org.codehaus.plexus:plexus-component-annotations
>>> org.codehaus.plexus:plexus-utils
>>> org.codehaus.plexus:plexus-component-api
>>> org.codehaus.plexus:plexus-interpolation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -155,22 +202,58 @@ 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
>>> CGLIB 3.0 (cglib:cglib:3.0):
>>> org.apache.ivy:ivy:2.3.0
Per the LICENSE file in the CGLIB JAR distribution downloaded from
http://sourceforge.net/projects/cglib/files/cglib3/3.0/cglib-3.0.jar/download,
CGLIB 3.0 is licensed under the Apache License, version 2.0, the text of which
is included above.
Copyright (c) 2007-2013 The Apache Software Foundation
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
--------------- SECTION 3: Eclipse Public License, Version 1.0 ----------
http://www.apache.org/licenses/LICENSE-2.0
Eclipse Public License, Version 1.0 is applicable to the following component(s).
>>> org.eclipse.aether:aether-api
>>> org.eclipse.aether:aether-connector-basic
>>> org.eclipse.aether:aether-impl
>>> org.eclipse.aether:aether-spi
>>> org.eclipse.aether:aether-transport-file
>>> org.eclipse.aether:aether-transport-http
>>> org.eclipse.aether:aether-util
The Eclipse Foundation makes available all content in this plug-in ("Content").
Unless otherwise indicated below, the Content is provided to you under the terms
and conditions of the Eclipse Public License Version 1.0 ("EPL"). A copy of the
EPL is available at http://www.eclipse.org/legal/epl-v10.html.
For purposes of the EPL, "Program" will mean the Content.
If you did not receive this Content directly from the Eclipse Foundation, the
Content is being redistributed by another party ("Redistributor") and different
terms and conditions may apply to your use of any object code in the Content.
Check the Redistributor's license that was provided with the Content. If no such
license exists, contact the Redistributor. Unless otherwise indicated below, the
terms and conditions of the EPL still apply to any source code in the Content and
such source code may be obtained at http://www.eclipse.org/
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
===========================================================================
To the extent any open source subcomponents are licensed under the EPL and/or
other similar licenses that require the source code and/or modifications to
source code to be made available (as would be noted above), you may obtain a
copy of the source code corresponding to the binaries for such open source
components and modifications thereto, if any, (the "Source Files"), by
downloading the Source Files from https://github.com/spring-projects/spring-boot,
or by sending a request, with your name and address to:
Pivotal, Inc., 875 Howard St,
San Francisco, CA 94103
United States of America
or email info@pivotal.io. All such requests should clearly specify:
OPEN SOURCE FILES REQUEST
Attention General Counsel

@ -1489,11 +1489,10 @@ You can apply the same principle if you are configuring a custom JNDI `DataSourc
}
----
Spring Boot also provides a utility builder class `DataSourceBuilder` that can be used
to create one of the standard data sources (if it is on the classpath). The builder can
detect the one to use based on the ones available on the classpath and it also auto
detects the driver based on the JDBC url.
Spring Boot also provides a utility builder class `DataSourceBuilder` that can be used to
create one of the standard data sources (if it is on the classpath). The builder can
detect the one to use based on what's available on the classpath. It also auto detects the
driver based on the JDBC url.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@ -1516,7 +1515,7 @@ There is a catch however. Because the actual type of the connection pool is not
no keys are generated in the metadata for your custom `DataSource` and no completion is
available in your IDE (The `DataSource` interface doesn't expose any property). Also, if
you happen to _only_ have Hikari on the classpath, this basic setup will not work because
Hikari has no `url` parameter (but a `jdbcUrl` parameter). You should have to rewrite
Hikari has no `url` parameter (but a `jdbcUrl` parameter). You will have to rewrite
your configuration as follows:
[source,properties,indent=0]
@ -1618,6 +1617,7 @@ This final example configures two data sources on custom namespaces with the sam
than what Spring Boot would do in auto-configuration.
[[howto-use-spring-data-repositories]]
=== Use Spring Data repositories
Spring Data can create implementations for you of `@Repository` interfaces of various

@ -45,4 +45,5 @@ public class BasicDataSourceExample {
// end::configuration[]
}
}

@ -25,8 +25,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* Example configuration for configuring two data sources with what Spring Boot does
* in auto-configuration.
* Example configuration for configuring two data sources with what Spring Boot does in
* auto-configuration.
*
* @author Stephane Nicoll
*/
@ -50,9 +50,7 @@ public class CompleteTwoDataSourcesExample {
@Primary
@ConfigurationProperties("app.datasource.foo")
public DataSource fooDataSource() {
return fooDataSourceProperties()
.initializeDataSourceBuilder()
.build();
return fooDataSourceProperties().initializeDataSourceBuilder().build();
}
@Bean
@ -61,13 +59,10 @@ public class CompleteTwoDataSourcesExample {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("app.datasource.bar")
public DataSource barDataSource() {
return barDataSourceProperties()
.initializeDataSourceBuilder()
.build();
return barDataSourceProperties().initializeDataSourceBuilder().build();
}
// end::configuration[]

@ -52,10 +52,10 @@ public class ConfigurableDataSourceExample {
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource(DataSourceProperties properties) {
return (HikariDataSource) properties.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
.type(HikariDataSource.class).build();
}
// end::configuration[]
}
}

@ -43,8 +43,7 @@ public class SimpleDataSourceExample {
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() {
return (HikariDataSource) DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
.type(HikariDataSource.class).build();
}
// end::configuration[]

@ -53,18 +53,14 @@ public class SimpleTwoDataSourcesExample {
@Primary
@ConfigurationProperties("app.datasource.foo")
public DataSource fooDataSource() {
return fooDataSourceProperties()
.initializeDataSourceBuilder()
.build();
return fooDataSourceProperties().initializeDataSourceBuilder().build();
}
@Bean
@ConfigurationProperties("app.datasource.bar")
public BasicDataSource barDataSource() {
return (BasicDataSource) DataSourceBuilder.create()
.type(BasicDataSource.class)
.build();
.type(BasicDataSource.class).build();
}
// end::configuration[]

@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link BasicDataSourceExample}.
*
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)

@ -47,12 +47,10 @@ public class CompleteTwoDataSourcesExampleTests {
@Test
public void validateConfiguration() throws SQLException {
assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(2);
DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(this.context.getBean("fooDataSource")).isSameAs(dataSource);
assertThat(dataSource.getConnection().getMetaData().getURL())
.startsWith("jdbc:h2:mem:");
DataSource barDataSource = this.context.getBean("barDataSource",
DataSource.class);
assertThat(barDataSource.getConnection().getMetaData().getURL())

@ -23,8 +23,8 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
* A sample {@link SpringBootConfiguration} that only enables the auto-configuration
* for the {@link DataSource}.
* A sample {@link SpringBootConfiguration} that only enables the auto-configuration for
* the {@link DataSource}.
*
* @author Stephane Nicoll
*/

@ -38,8 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {
"app.datasource.bar.url=jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1",
@SpringBootTest(properties = { "app.datasource.bar.url=jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1",
"app.datasource.bar.max-total=42" })
@Import(SimpleTwoDataSourcesExample.SimpleDataSourcesConfiguration.class)
public class SimpleTwoDataSourcesExampleTests {
@ -50,16 +49,13 @@ public class SimpleTwoDataSourcesExampleTests {
@Test
public void validateConfiguration() throws SQLException {
assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(2);
DataSource dataSource = this.context.getBean(DataSource.class);
assertThat(this.context.getBean("fooDataSource")).isSameAs(dataSource);
assertThat(dataSource.getConnection().getMetaData().getURL())
.startsWith("jdbc:h2:mem:");
BasicDataSource barDataSource = this.context.getBean("barDataSource",
BasicDataSource.class);
assertThat(barDataSource.getUrl())
.isEqualTo("jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1");
assertThat(barDataSource.getUrl()).isEqualTo("jdbc:h2:mem:bar;DB_CLOSE_DELAY=-1");
assertThat(barDataSource.getMaxTotal()).isEqualTo(42);
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -1252,7 +1252,6 @@ public class SpringApplication {
finally {
close(context);
}
}
catch (Exception ex) {
ex.printStackTrace();

@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2017 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.
@ -17,6 +17,7 @@
package org.springframework.boot.context.config;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.BeanUtils;
@ -70,8 +71,11 @@ public class DelegatingApplicationListener
@SuppressWarnings("unchecked")
private List<ApplicationListener<ApplicationEvent>> getListeners(
ConfigurableEnvironment env) {
String classNames = env.getProperty(PROPERTY_NAME);
ConfigurableEnvironment environment) {
if (environment == null) {
return Collections.emptyList();
}
String classNames = environment.getProperty(PROPERTY_NAME);
List<ApplicationListener<ApplicationEvent>> listeners = new ArrayList<ApplicationListener<ApplicationEvent>>();
if (StringUtils.hasLength(classNames)) {
for (String className : StringUtils.commaDelimitedListToSet(classNames)) {

@ -59,6 +59,8 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
private Connector[] connectors;
private volatile boolean started;
/**
* Create a new {@link JettyEmbeddedServletContainer} instance.
* @param server the underlying Jetty server
@ -111,37 +113,43 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
@Override
public void start() throws EmbeddedServletContainerException {
this.server.setConnectors(this.connectors);
if (!this.autoStart) {
return;
}
try {
this.server.start();
for (Handler handler : this.server.getHandlers()) {
handleDeferredInitialize(handler);
synchronized (this.monitor) {
if (this.started) {
return;
}
this.server.setConnectors(this.connectors);
if (!this.autoStart) {
return;
}
Connector[] connectors = this.server.getConnectors();
for (Connector connector : connectors) {
try {
connector.start();
try {
this.server.start();
for (Handler handler : this.server.getHandlers()) {
handleDeferredInitialize(handler);
}
catch (BindException ex) {
if (connector instanceof NetworkConnector) {
throw new PortInUseException(
((NetworkConnector) connector).getPort());
Connector[] connectors = this.server.getConnectors();
for (Connector connector : connectors) {
try {
connector.start();
}
catch (BindException ex) {
if (connector instanceof NetworkConnector) {
throw new PortInUseException(
((NetworkConnector) connector).getPort());
}
throw ex;
}
throw ex;
}
this.started = true;
JettyEmbeddedServletContainer.logger
.info("Jetty started on port(s) " + getActualPortsDescription());
}
catch (EmbeddedServletContainerException ex) {
throw ex;
}
catch (Exception ex) {
throw new EmbeddedServletContainerException(
"Unable to start embedded Jetty servlet container", ex);
}
JettyEmbeddedServletContainer.logger
.info("Jetty started on port(s) " + getActualPortsDescription());
}
catch (EmbeddedServletContainerException ex) {
throw ex;
}
catch (Exception ex) {
throw new EmbeddedServletContainerException(
"Unable to start embedded Jetty servlet container", ex);
}
}
@ -197,6 +205,10 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
@Override
public void stop() {
synchronized (this.monitor) {
if (!this.started) {
return;
}
this.started = false;
try {
this.server.stop();
}

@ -62,6 +62,8 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
private final boolean autoStart;
private volatile boolean started;
/**
* Create a new {@link TomcatEmbeddedServletContainer} instance.
* @param tomcat the underlying Tomcat server
@ -174,28 +176,34 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
@Override
public void start() throws EmbeddedServletContainerException {
try {
addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
startConnector(connector);
synchronized (this.monitor) {
if (this.started) {
return;
}
try {
addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
startConnector(connector);
}
checkThatConnectorsHaveStarted();
this.started = true;
TomcatEmbeddedServletContainer.logger
.info("Tomcat started on port(s): " + getPortsDescription(true));
}
catch (ConnectorStartFailedException ex) {
stopSilently();
throw ex;
}
catch (Exception ex) {
throw new EmbeddedServletContainerException(
"Unable to start embedded Tomcat servlet container", ex);
}
finally {
Context context = findContext();
ContextBindings.unbindClassLoader(context, context.getNamingToken(),
getClass().getClassLoader());
}
checkThatConnectorsHaveStarted();
TomcatEmbeddedServletContainer.logger
.info("Tomcat started on port(s): " + getPortsDescription(true));
}
catch (ConnectorStartFailedException ex) {
stopSilently();
throw ex;
}
catch (Exception ex) {
throw new EmbeddedServletContainerException(
"Unable to start embedded Tomcat servlet container", ex);
}
finally {
Context context = findContext();
ContextBindings.unbindClassLoader(context, context.getNamingToken(),
getClass().getClassLoader());
}
}
@ -271,7 +279,11 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
@Override
public void stop() throws EmbeddedServletContainerException {
synchronized (this.monitor) {
if (!this.started) {
return;
}
try {
this.started = false;
try {
stopTomcat();
this.tomcat.destroy();

@ -88,7 +88,7 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
private Undertow undertow;
private boolean started = false;
private volatile boolean started = false;
/**
* Create a new {@link UndertowEmbeddedServletContainer} instance.
@ -144,6 +144,9 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
@Override
public void start() throws EmbeddedServletContainerException {
synchronized (this.monitor) {
if (this.started) {
return;
}
try {
if (!this.autoStart) {
return;
@ -305,16 +308,17 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine
@Override
public void stop() throws EmbeddedServletContainerException {
synchronized (this.monitor) {
if (this.started) {
try {
this.started = false;
this.manager.stop();
this.undertow.stop();
}
catch (Exception ex) {
throw new EmbeddedServletContainerException("Unable to stop undertow",
ex);
}
if (!this.started) {
return;
}
this.started = false;
try {
this.manager.stop();
this.undertow.stop();
}
catch (Exception ex) {
throw new EmbeddedServletContainerException("Unable to stop undertow",
ex);
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -16,6 +16,9 @@
package org.springframework.boot.context.event;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ApplicationContextAware;
@ -25,6 +28,7 @@ import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ErrorHandler;
/**
* {@link SpringApplicationRunListener} to publish {@link SpringApplicationEvent}s.
@ -41,7 +45,7 @@ public class EventPublishingRunListener implements SpringApplicationRunListener,
private final String[] args;
private final ApplicationEventMulticaster initialMulticaster;
private final SimpleApplicationEventMulticaster initialMulticaster;
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
@ -89,9 +93,18 @@ public class EventPublishingRunListener implements SpringApplicationRunListener,
@Override
public void finished(ConfigurableApplicationContext context, Throwable exception) {
// Listeners have been registered to the application context so we should
// use it at this point
context.publishEvent(getFinishedEvent(context, exception));
SpringApplicationEvent event = getFinishedEvent(context, exception);
if (context != null) {
// Listeners have been registered to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
if (event instanceof ApplicationFailedEvent) {
this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
}
this.initialMulticaster.multicastEvent(event);
}
}
private SpringApplicationEvent getFinishedEvent(
@ -103,4 +116,15 @@ public class EventPublishingRunListener implements SpringApplicationRunListener,
return new ApplicationReadyEvent(this.application, this.args, context);
}
private static class LoggingErrorHandler implements ErrorHandler {
private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);
@Override
public void handleError(Throwable throwable) {
logger.warn("Error calling ApplicationEventListener", throwable);
}
}
}

@ -0,0 +1,23 @@
/*
* Copyright 2012-2017 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.env;
/**
* @author pwebb
*/
public interface DunnoEnumerablePropertySource {
}

@ -0,0 +1,28 @@
/*
* Copyright 2012-2017 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.env;
/**
* @author pwebb
*/
public interface DunnoPropertySource {
boolean containsProperty(String name);
Object getProperty(String name);
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -167,7 +167,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
private static Class<?>[] EVENT_TYPES = { ApplicationStartingEvent.class,
ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class,
ContextClosedEvent.class };
ContextClosedEvent.class, ApplicationFailedEvent.class };
private static Class<?>[] SOURCE_TYPES = { SpringApplication.class,
ApplicationContext.class };

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -251,6 +251,7 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem {
super.cleanUp();
LoggerContext loggerContext = getLoggerContext();
markAsUninitialized(loggerContext);
loggerContext.getConfiguration().removeFilter(FILTER);
}
private LoggerConfig getLoggerConfig(String name) {

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -193,9 +193,11 @@ public class LogbackLoggingSystem extends Slf4JLoggingSystem {
@Override
public void cleanUp() {
markAsUninitialized(getLoggerContext());
LoggerContext context = getLoggerContext();
markAsUninitialized(context);
super.cleanUp();
getLoggerContext().getStatusManager().clear();
context.getStatusManager().clear();
context.getTurboFilterList().remove(FILTER);
}
@Override

@ -82,6 +82,7 @@ import org.mockito.InOrder;
import org.springframework.boot.ApplicationHome;
import org.springframework.boot.ApplicationTemp;
import org.springframework.boot.context.embedded.Ssl.ClientAuth;
import org.springframework.boot.testutil.InternalOutputCapture;
import org.springframework.boot.web.servlet.ErrorPage;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletContextInitializer;
@ -124,6 +125,9 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Rule
public InternalOutputCapture output = new InternalOutputCapture();
protected EmbeddedServletContainer container;
private final HttpClientContext httpClientContext = HttpClientContext.create();
@ -157,6 +161,19 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
assertThat(getResponse(getLocalUrl("/hello"))).isEqualTo("Hello World");
}
@Test
public void startCalledTwice() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory();
this.container = factory
.getEmbeddedServletContainer(exampleServletRegistration());
this.container.start();
int port = this.container.getPort();
this.container.start();
assertThat(this.container.getPort()).isEqualTo(port);
assertThat(getResponse(getLocalUrl("/hello"))).isEqualTo("Hello World");
assertThat(this.output.toString()).containsOnlyOnce("started on port");
}
@Test
public void emptyServerWhenPortIsMinusOne() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory();

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 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.
@ -42,7 +42,10 @@ import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.boot.logging.java.JavaLoggingSystem;
import org.springframework.boot.testutil.InternalOutputCapture;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.test.util.ReflectionTestUtils;
@ -85,8 +88,7 @@ public class LoggingApplicationListenerTests {
public void init() throws SecurityException, IOException {
LogManager.getLogManager().readConfiguration(
JavaLoggingSystem.class.getResourceAsStream("logging.properties"));
this.initializer.onApplicationEvent(
new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
multicastEvent(new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
new File("target/foo.log").delete();
new File(tmpDir() + "/spring.log").delete();
}
@ -354,8 +356,8 @@ public class LoggingApplicationListenerTests {
public void parseArgsDoesntReplace() throws Exception {
this.initializer.setSpringBootLogging(LogLevel.ERROR);
this.initializer.setParseArgs(false);
this.initializer.onApplicationEvent(new ApplicationStartingEvent(
this.springApplication, new String[] { "--debug" }));
multicastEvent(new ApplicationStartingEvent(this.springApplication,
new String[] { "--debug" }));
this.initializer.initialize(this.context.getEnvironment(),
this.context.getClassLoader());
this.logger.debug("testatdebug");
@ -365,7 +367,7 @@ public class LoggingApplicationListenerTests {
@Test
public void bridgeHandlerLifecycle() throws Exception {
assertThat(bridgeHandlerInstalled()).isTrue();
this.initializer.onApplicationEvent(new ContextClosedEvent(this.context));
multicastEvent(new ContextClosedEvent(this.context));
assertThat(bridgeHandlerInstalled()).isFalse();
}
@ -398,7 +400,7 @@ public class LoggingApplicationListenerTests {
TestLoggingApplicationListener listener = new TestLoggingApplicationListener();
System.setProperty(LoggingSystem.class.getName(),
TestShutdownHandlerLoggingSystem.class.getName());
listener.onApplicationEvent(
multicastEvent(listener,
new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
assertThat(listener.shutdownHook).isNull();
@ -411,7 +413,7 @@ public class LoggingApplicationListenerTests {
TestShutdownHandlerLoggingSystem.class.getName());
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
"logging.register_shutdown_hook=true");
listener.onApplicationEvent(
multicastEvent(listener,
new ApplicationStartingEvent(new SpringApplication(), NO_ARGS));
listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
assertThat(listener.shutdownHook).isNotNull();
@ -424,12 +426,12 @@ public class LoggingApplicationListenerTests {
public void closingContextCleansUpLoggingSystem() {
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
TestCleanupLoggingSystem.class.getName());
this.initializer.onApplicationEvent(
multicastEvent(
new ApplicationStartingEvent(this.springApplication, new String[0]));
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
.getField(this.initializer, "loggingSystem");
assertThat(loggingSystem.cleanedUp).isFalse();
this.initializer.onApplicationEvent(new ContextClosedEvent(this.context));
multicastEvent(new ContextClosedEvent(this.context));
assertThat(loggingSystem.cleanedUp).isTrue();
}
@ -437,16 +439,16 @@ public class LoggingApplicationListenerTests {
public void closingChildContextDoesNotCleanUpLoggingSystem() {
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
TestCleanupLoggingSystem.class.getName());
this.initializer.onApplicationEvent(
multicastEvent(
new ApplicationStartingEvent(this.springApplication, new String[0]));
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
.getField(this.initializer, "loggingSystem");
assertThat(loggingSystem.cleanedUp).isFalse();
GenericApplicationContext childContext = new GenericApplicationContext();
childContext.setParent(this.context);
this.initializer.onApplicationEvent(new ContextClosedEvent(childContext));
multicastEvent(new ContextClosedEvent(childContext));
assertThat(loggingSystem.cleanedUp).isFalse();
this.initializer.onApplicationEvent(new ContextClosedEvent(this.context));
multicastEvent(new ContextClosedEvent(this.context));
assertThat(loggingSystem.cleanedUp).isTrue();
childContext.close();
}
@ -493,17 +495,26 @@ public class LoggingApplicationListenerTests {
public void applicationFailedEventCleansUpLoggingSystem() {
System.setProperty(LoggingSystem.SYSTEM_PROPERTY,
TestCleanupLoggingSystem.class.getName());
this.initializer.onApplicationEvent(
multicastEvent(
new ApplicationStartingEvent(this.springApplication, new String[0]));
TestCleanupLoggingSystem loggingSystem = (TestCleanupLoggingSystem) ReflectionTestUtils
.getField(this.initializer, "loggingSystem");
assertThat(loggingSystem.cleanedUp).isFalse();
this.initializer
.onApplicationEvent(new ApplicationFailedEvent(this.springApplication,
new String[0], new GenericApplicationContext(), new Exception()));
multicastEvent(new ApplicationFailedEvent(this.springApplication, new String[0],
new GenericApplicationContext(), new Exception()));
assertThat(loggingSystem.cleanedUp).isTrue();
}
private void multicastEvent(ApplicationEvent event) {
multicastEvent(this.initializer, event);
}
private void multicastEvent(ApplicationListener<?> listener, ApplicationEvent event) {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.addApplicationListener(listener);
multicaster.multicastEvent(event);
}
private boolean bridgeHandlerInstalled() {
Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();

Loading…
Cancel
Save