Skip to content

Commit 126e87e

Browse files
wilkinsonaphilwebb
authored andcommitted
Fix appending of JDBC parameters to SQL Server JDBC URL
Fixes gh-41146
1 parent 43cd241 commit 126e87e

File tree

5 files changed

+75
-10
lines changed

5 files changed

+75
-10
lines changed

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/jdbc/JdbcUrlBuilder.java

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -68,20 +68,33 @@ public String build(RunningService service, String database) {
6868

6969
private String urlFor(RunningService service, String database) {
7070
Assert.notNull(service, "Service must not be null");
71-
String parameters = getParameters(service);
7271
StringBuilder url = new StringBuilder("jdbc:%s://%s:%d".formatted(this.driverProtocol, service.host(),
7372
service.ports().get(this.containerPort)));
7473
if (StringUtils.hasLength(database)) {
7574
url.append("/");
7675
url.append(database);
7776
}
78-
url.append(parameters);
77+
String parameters = getParameters(service);
78+
if (StringUtils.hasLength(parameters)) {
79+
appendParameters(url, parameters);
80+
}
7981
return url.toString();
8082
}
8183

84+
/**
85+
* Appends to the given {@code url} the given {@code parameters}.
86+
* <p>
87+
* The default implementation appends a {@code ?} followed by the {@code parameters}.
88+
* @param url the url
89+
* @param parameters the parameters
90+
* @since 3.2.7
91+
*/
92+
protected void appendParameters(StringBuilder url, String parameters) {
93+
url.append("?").append(parameters);
94+
}
95+
8296
private String getParameters(RunningService service) {
83-
String parameters = service.labels().get(PARAMETERS_LABEL);
84-
return (StringUtils.hasLength(parameters)) ? "?" + parameters : "";
97+
return service.labels().get(PARAMETERS_LABEL);
8598
}
8699

87100
}

spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/sqlserver/SqlServerJdbcDockerComposeConnectionDetailsFactory.java

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,7 +47,7 @@ protected JdbcConnectionDetails getDockerComposeConnectionDetails(DockerComposeC
4747
static class SqlServerJdbcDockerComposeConnectionDetails extends DockerComposeConnectionDetails
4848
implements JdbcConnectionDetails {
4949

50-
private static final JdbcUrlBuilder jdbcUrlBuilder = new JdbcUrlBuilder("sqlserver", 1433);
50+
private static final JdbcUrlBuilder jdbcUrlBuilder = new SqlServerJdbcUrlBuilder("sqlserver", 1433);
5151

5252
private final SqlServerEnvironment environment;
5353

@@ -56,7 +56,7 @@ static class SqlServerJdbcDockerComposeConnectionDetails extends DockerComposeCo
5656
SqlServerJdbcDockerComposeConnectionDetails(RunningService service) {
5757
super(service);
5858
this.environment = new SqlServerEnvironment(service.env());
59-
this.jdbcUrl = disableEncryptionIfNecessary(jdbcUrlBuilder.build(service, ""));
59+
this.jdbcUrl = disableEncryptionIfNecessary(jdbcUrlBuilder.build(service));
6060
}
6161

6262
private String disableEncryptionIfNecessary(String jdbcUrl) {
@@ -86,6 +86,19 @@ public String getJdbcUrl() {
8686
return this.jdbcUrl;
8787
}
8888

89+
private static final class SqlServerJdbcUrlBuilder extends JdbcUrlBuilder {
90+
91+
private SqlServerJdbcUrlBuilder(String driverProtocol, int containerPort) {
92+
super(driverProtocol, containerPort);
93+
}
94+
95+
@Override
96+
protected void appendParameters(StringBuilder url, String parameters) {
97+
url.append(";").append(parameters);
98+
}
99+
100+
}
101+
89102
}
90103

91104
}

spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/jdbc/JdbcUrlBuilderTests.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -67,6 +67,20 @@ void buildWhenHasParamsLabelBuildsUrl() {
6767
assertThat(url).isEqualTo("jdbc:mydb://myhost:456/mydb?foo=bar");
6868
}
6969

70+
@Test
71+
void buildWithCustomAppendParametersWhenHasParamsLabelBuildsUrl() {
72+
RunningService service = mockService(456, Map.of("org.springframework.boot.jdbc.parameters", "foo=bar"));
73+
String url = new JdbcUrlBuilder("mydb", 1234) {
74+
75+
@Override
76+
protected void appendParameters(StringBuilder url, String parameters) {
77+
url.append(";").append(parameters);
78+
}
79+
80+
}.build(service, "mydb");
81+
assertThat(url).isEqualTo("jdbc:mydb://myhost:456/mydb;foo=bar");
82+
}
83+
7084
@Test
7185
void buildWhenServiceIsNullThrowsException() {
7286
assertThatIllegalArgumentException().isThrownBy(() -> this.builder.build(null, "mydb"))

spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/sqlserver/SqlServerJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,27 @@
4040
disabledReason = "The SQL server image has no ARM support")
4141
class SqlServerJdbcDockerComposeConnectionDetailsFactoryIntegrationTests {
4242

43-
@SuppressWarnings("unchecked")
4443
@DockerComposeTest(composeFile = "mssqlserver-compose.yaml", image = TestImage.SQL_SERVER)
4544
void runCreatesConnectionDetailsThatCanBeUsedToAccessDatabase(JdbcConnectionDetails connectionDetails)
4645
throws ClassNotFoundException, LinkageError {
4746
assertThat(connectionDetails.getUsername()).isEqualTo("SA");
4847
assertThat(connectionDetails.getPassword()).isEqualTo("verYs3cret");
4948
assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:sqlserver://");
49+
checkDatabaseAccess(connectionDetails);
50+
}
51+
52+
@DockerComposeTest(composeFile = "mssqlserver-with-jdbc-parameters-compose.yaml", image = TestImage.SQL_SERVER)
53+
void runWithJdbcParametersCreatesConnectionDetailsThatCanBeUsedToAccessDatabase(
54+
JdbcConnectionDetails connectionDetails) throws ClassNotFoundException {
55+
assertThat(connectionDetails.getUsername()).isEqualTo("SA");
56+
assertThat(connectionDetails.getPassword()).isEqualTo("verYs3cret");
57+
assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:sqlserver://")
58+
.contains(";sendStringParametersAsUnicode=false;");
59+
checkDatabaseAccess(connectionDetails);
60+
}
61+
62+
@SuppressWarnings("unchecked")
63+
private void checkDatabaseAccess(JdbcConnectionDetails connectionDetails) throws ClassNotFoundException {
5064
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
5165
dataSource.setUrl(connectionDetails.getJdbcUrl());
5266
dataSource.setUsername(connectionDetails.getUsername());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
services:
2+
database:
3+
image: '{imageName}'
4+
ports:
5+
- '1433'
6+
environment:
7+
- 'MSSQL_PID=express'
8+
- 'MSSQL_SA_PASSWORD=verYs3cret'
9+
- 'ACCEPT_EULA=yes'
10+
labels:
11+
org.springframework.boot.jdbc.parameters: sendStringParametersAsUnicode=false

0 commit comments

Comments
 (0)