Add FailureAnalyzer for Hikari

Hikari can configure both an underlying Driver or DataSource. Spring Boot
only supports the former so any attempt to trigger the creation of the
latter will lead to an exception since the auto-configuration has set
driver-specific field.

This commit adds an analyzer that intercepts such faulty scenario and
indicate that users should configure Hikari with an underlying DataSource
themselves.

Closes gh-6568
This commit is contained in:
Stephane Nicoll 2016-08-26 11:31:46 +02:00
parent 10402a651f
commit 86757efcdf
3 changed files with 131 additions and 1 deletions

View File

@ -0,0 +1,45 @@
/*
* 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.autoconfigure.jdbc;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
/**
* An {@link AbstractFailureAnalyzer} that performs analysis of a Hikari configuration
* failure caused by the use of the unsupported 'dataSourceClassName' property.
* @author Stephane Nicoll
*/
class HikariDriverConfigurationFailureAnalyzer extends AbstractFailureAnalyzer<IllegalStateException> {
static final String EXPECTED_MESSAGE = "both driverClassName and dataSourceClassName are " +
"specified, one or the other should be used";
@Override
protected FailureAnalysis analyze(Throwable rootFailure, IllegalStateException cause) {
if (!EXPECTED_MESSAGE.equals(cause.getMessage())) {
return null;
}
return new FailureAnalysis("Configuration of the Hikari connection pool failed: " +
"'dataSourceClassName' is not supported.",
"Spring Boot auto-configures only a driver and can't specify a custom " +
"DataSource. Consider configuring the Hikari DataSource in your " +
"own configuration.", cause);
}
}

View File

@ -104,7 +104,8 @@ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\

View File

@ -0,0 +1,84 @@
/*
* 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.autoconfigure.jdbc;
import com.zaxxer.hikari.HikariDataSource;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HikariDriverConfigurationFailureAnalyzer}.
*
* @author Stephane Nicoll
*/
public class HikariDriverConfigurationFailureAnalyzerTests {
@Test
public void failureAnalysisIsPerformed() {
FailureAnalysis failureAnalysis = performAnalysis(TestConfiguration.class);
assertThat(failureAnalysis).isNotNull();
assertThat(failureAnalysis.getDescription()).isEqualTo(
"Configuration of the Hikari connection pool failed: " +
"'dataSourceClassName' is not supported.");
assertThat(failureAnalysis.getAction()).contains(
"Spring Boot auto-configures only a driver");
}
@Test
public void unrelatedIllegalStateExceptionIsSkipped() {
FailureAnalysis failureAnalysis = new HikariDriverConfigurationFailureAnalyzer()
.analyze(new RuntimeException("foo", new IllegalStateException("bar")));
assertThat(failureAnalysis).isNull();
}
private FailureAnalysis performAnalysis(Class<?> configuration) {
BeanCreationException failure = createFailure(configuration);
assertThat(failure).isNotNull();
return new HikariDriverConfigurationFailureAnalyzer().analyze(failure);
}
private BeanCreationException createFailure(Class<?> configuration) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context,
"spring.datasource.type=" + HikariDataSource.class.getName(),
"spring.datasource.hikari.data-source-class-name=com.example.Foo");
context.register(configuration);
try {
context.refresh();
context.close();
return null;
}
catch (BeanCreationException ex) {
return ex;
}
}
@Configuration
@ImportAutoConfiguration(DataSourceAutoConfiguration.class)
static class TestConfiguration {
}
}