diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index ef0a410fb20..b6454b45b96 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -153,6 +153,7 @@ dependencies { testImplementation("ch.qos.logback:logback-classic") testImplementation("commons-fileupload:commons-fileupload") testImplementation("com.atomikos:transactions-jms") + testImplementation("com.ibm.db2:jcc") testImplementation("com.jayway.jsonpath:json-path") testImplementation("com.squareup.okhttp3:mockwebserver") testImplementation("com.sun.xml.messaging.saaj:saaj-impl") 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 ccc56ca16f5..81ef4e642dd 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 91f0f78c167..336de2b14e6 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,