Commit c921c941 authored by Andy Wilkinson's avatar Andy Wilkinson

Improve startup failure diagnostics

A typical cause of startup failure is an incorrectly configured
classpath. Previously the classpath used to launch the application
wasn't easy for a user to discover. This made problem diagnosis
difficult. This commit adds an application listener that, in the event
of a start error, logs the thread context class loader's classpath at
INFO level. The classpath is also logged at DEBUG level when an
application starts successfully.
parent 3e6eb6fe
/*
* Copyright 2012-2013 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.listener;
import java.net.URLClassLoader;
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplicationErrorEvent;
import org.springframework.boot.SpringApplicationStartEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
/**
* A {@link SmartApplicationListener} that reacts to {@link SpringApplicationStartEvent
* start events} by logging the classpath of the thread context class loader (TCCL) at
* {@code DEBUG} level and to {@link SpringApplicationErrorEvent error events} by logging
* the TCCL's classpath at {@code INFO} level.
*
* @author Andy Wilkinson
*/
public final class ClasspathLoggingApplicationListener implements
SmartApplicationListener {
private static final int ORDER = Integer.MIN_VALUE + 12;
private final Log logger = LogFactory.getLog(getClass());
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof SpringApplicationStartEvent) {
if (this.logger.isDebugEnabled()) {
this.logger
.debug("Application started with classpath: " + getClasspath());
}
}
else if (event instanceof SpringApplicationErrorEvent) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Application failed to start with classpath: "
+ getClasspath());
}
}
}
@Override
public int getOrder() {
return ORDER;
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> type) {
return SpringApplicationStartEvent.class.isAssignableFrom(type)
|| SpringApplicationErrorEvent.class.isAssignableFrom(type);
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
return true;
}
private String getClasspath() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader instanceof URLClassLoader) {
return Arrays.toString(((URLClassLoader) classLoader).getURLs());
}
else {
return "unknown";
}
}
}
......@@ -5,9 +5,11 @@ org.springframework.boot.context.initializer.EnvironmentDelegateApplicationConte
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.context.listener.FileEncodingApplicationListener,\
org.springframework.boot.context.listener.VcapApplicationListener,\
org.springframework.boot.context.listener.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.listener.ConfigFileApplicationListener,\
org.springframework.boot.context.listener.EnvironmentDelegateApplicationListener,\
org.springframework.boot.context.listener.FileEncodingApplicationListener,\
org.springframework.boot.context.listener.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorInitializer,\
org.springframework.boot.context.listener.EnvironmentDelegateApplicationListener
org.springframework.boot.context.listener.VcapApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorInitializer
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