From 72551242fd7746cded6d6da172e82d066e105579 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 29 Jul 2020 13:57:50 +0100 Subject: [PATCH] Allow XADataSource auto-config with no spring.datasource properties Fixes gh-20229 --- .../spring-boot-autoconfigure/pom.xml | 5 ++++ .../jdbc/XADataSourceAutoConfiguration.java | 23 +++++++++++++------ .../XADataSourceAutoConfigurationTests.java | 20 +++++++++++++++- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/pom.xml b/spring-boot-project/spring-boot-autoconfigure/pom.xml index 9f915f5d5b..b54887fd6e 100755 --- a/spring-boot-project/spring-boot-autoconfigure/pom.xml +++ b/spring-boot-project/spring-boot-autoconfigure/pom.xml @@ -877,6 +877,11 @@ transactions-jms test + + com.ibm.db2 + jcc + test + com.jayway.jsonpath json-path diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfiguration.java index ccc56ca16f..81ef4e642d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.boot.autoconfigure.jdbc; +import java.util.HashMap; +import java.util.Map; + import javax.sql.DataSource; import javax.sql.XADataSource; import javax.transaction.TransactionManager; @@ -28,6 +30,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.DataSourceBeanCreationException; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.bind.Bindable; import org.springframework.boot.context.properties.bind.Binder; @@ -102,11 +105,17 @@ public class XADataSourceAutoConfiguration implements BeanClassLoaderAware { } private ConfigurationPropertySource getBinderSource(DataSourceProperties dataSourceProperties) { - MapConfigurationPropertySource source = new MapConfigurationPropertySource(); - source.put("user", dataSourceProperties.determineUsername()); - source.put("password", dataSourceProperties.determinePassword()); - source.put("url", dataSourceProperties.determineUrl()); - source.putAll(dataSourceProperties.getXa().getProperties()); + Map properties = new HashMap(); + properties.putAll(dataSourceProperties.getXa().getProperties()); + properties.computeIfAbsent("user", (key) -> dataSourceProperties.determineUsername()); + properties.computeIfAbsent("password", (key) -> dataSourceProperties.determinePassword()); + try { + properties.computeIfAbsent("url", (key) -> dataSourceProperties.determineUrl()); + } + catch (DataSourceBeanCreationException ex) { + // Continue as not all XA DataSource's require a URL + } + MapConfigurationPropertySource source = new MapConfigurationPropertySource(properties); ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases(); aliases.addAliases("user", "username"); return source.withAliases(aliases); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfigurationTests.java index 91f0f78c16..336de2b14e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/XADataSourceAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -19,10 +19,14 @@ package org.springframework.boot.autoconfigure.jdbc; import javax.sql.DataSource; import javax.sql.XADataSource; +import com.ibm.db2.jcc.DB2XADataSource; import org.hsqldb.jdbc.pool.JDBCXADataSource; import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.jdbc.XADataSourceWrapper; +import org.springframework.boot.test.context.FilteredClassLoader; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -60,6 +64,20 @@ class XADataSourceAutoConfigurationTests { assertThat(dataSource.getUser()).isEqualTo("un"); } + @Test + void createNonEmbeddedFromXAProperties() { + new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(XADataSourceAutoConfiguration.class)) + .withUserConfiguration(FromProperties.class) + .withClassLoader(new FilteredClassLoader("org.h2.Driver", "org.hsqldb.jdbcDriver")) + .withPropertyValues("spring.datasource.xa.data-source-class-name:com.ibm.db2.jcc.DB2XADataSource", + "spring.datasource.xa.properties.user:test", "spring.datasource.xa.properties.password:secret") + .run((context) -> { + MockXADataSourceWrapper wrapper = context.getBean(MockXADataSourceWrapper.class); + XADataSource xaDataSource = wrapper.getXaDataSource(); + assertThat(xaDataSource).isInstanceOf(DB2XADataSource.class); + }); + } + @Test void createFromClass() throws Exception { ApplicationContext context = createContext(FromProperties.class,