Skip to content

Commit 68dfa18

Browse files
anthonydahannemeyerg
andauthored
Greg main - replaces Support for R2DBC connections in DataSource processor. #262 (#272)
* Support for R2DBC connections in DataSource processor. * Cleaning up some formatting. * Resolved style formatting issues. * Remove Greg MariadDB code * it's now handled directly in MySqlJdbcUrlCreator --------- Co-authored-by: meyerg <[email protected]>
1 parent 3466053 commit 68dfa18

File tree

3 files changed

+154
-2
lines changed

3 files changed

+154
-2
lines changed

java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/CfDataSourceEnvironmentPostProcessor.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
*/
1616
package io.pivotal.cfenv.spring.boot;
1717

18+
import java.util.Collections;
19+
import java.util.HashMap;
1820
import java.util.LinkedHashMap;
1921
import java.util.List;
2022
import java.util.Map;
21-
import java.util.stream.Collectors;
2223

2324
import org.springframework.boot.SpringApplication;
2425
import org.springframework.boot.cloud.CloudPlatform;
@@ -38,6 +39,7 @@
3839
/**
3940
* @author Mark Pollack
4041
* @author David Turanski
42+
* @author Greg Meyer
4143
*/
4244
public class CfDataSourceEnvironmentPostProcessor implements CfServiceEnablingEnvironmentPostProcessor,
4345
Ordered, ApplicationListener<ApplicationEvent> {
@@ -72,7 +74,7 @@ public void postProcessEnvironment(ConfigurableEnvironment environment,
7274

7375
List<CfJdbcService> jdbcServices = cfJdbcEnv.findJdbcServices().stream()
7476
.filter(service -> this.isEnabled(service, environment))
75-
.collect(Collectors.toList());
77+
.toList();
7678

7779
if (jdbcServices.size() > 1) {
7880
if (invocationCount == 1) {
@@ -96,6 +98,36 @@ public void postProcessEnvironment(ConfigurableEnvironment environment,
9698
properties.put("spring.datasource.driver-class-name", driverClassName);
9799
}
98100

101+
/* R2DBC processing
102+
* Split query param options and URL into two string
103+
* and move options to spring.r2dbc.properties.<option>
104+
*/
105+
106+
String[] splitJDBCUrl = cfJdbcService.getJdbcUrl().split("\\?");
107+
108+
String r2dbcUrl = splitJDBCUrl[0].replaceFirst("jdbc:", "r2dbc:");
109+
110+
properties.put("spring.r2dbc.url", r2dbcUrl);
111+
properties.put("spring.r2dbc.username", cfJdbcService.getUsername());
112+
properties.put("spring.r2dbc.password", cfJdbcService.getPassword());
113+
114+
if (splitJDBCUrl.length == 2) {
115+
Map<String, String> queryOptions = parseQueryString(splitJDBCUrl[1]);
116+
117+
if (queryOptions.size() > 0) {
118+
queryOptions.forEach((key, value) -> {
119+
120+
switch (key) {
121+
case "enabledTLSProtocols":
122+
properties.put("spring.r2dbc.properties.tlsVersion", value);
123+
break;
124+
default:
125+
properties.put(String.format("spring.r2dbc.properties.%s", key), value);
126+
}
127+
});
128+
}
129+
}
130+
99131
MutablePropertySources propertySources = environment.getPropertySources();
100132
if (propertySources.contains(
101133
CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME)) {
@@ -120,6 +152,27 @@ public void postProcessEnvironment(ConfigurableEnvironment environment,
120152
}
121153
}
122154

155+
private Map<String, String> parseQueryString(String queryParams) {
156+
157+
if (queryParams == null || queryParams.equals(""))
158+
return Collections.emptyMap();
159+
160+
Map<String, String> retVal = new HashMap<>();
161+
162+
String[] options = queryParams.split("&");
163+
for (String option : options) {
164+
165+
String[] keyValue = option.split("=");
166+
if (keyValue.length != 2 || keyValue[0].length() == 0 || keyValue[1].length() == 0) {
167+
continue;
168+
}
169+
170+
retVal.put(keyValue[0], keyValue[1]);
171+
}
172+
173+
return retVal;
174+
}
175+
123176
@Override
124177
public void onApplicationEvent(ApplicationEvent event) {
125178
if (event instanceof ApplicationPreparedEvent) {

java-cfenv-boot/src/test/java/io/pivotal/cfenv/spring/boot/DataSourceTests.java

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,14 @@
3030

3131
/**
3232
* @author Mark Pollack
33+
* @author Greg Meyer
3334
*/
3435
public class DataSourceTests extends AbstractCfEnvTests {
3536

3637
private static final String mysqlJdbcUrl = "jdbc:mysql://10.0.4.35:3306/cf_2e23d10a_8738_8c3c_66cf_13e44422698c?user=mysql_username&password=mysql_password";
3738

39+
private static final String tlsMysqlJdbcUrl = "jdbc:mysql://10.0.4.35:3306/service_instance_db?permitMysqlScheme&user=mysql_username&password=mysql_password&sslMode=VERIFY_IDENTITY&useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2&serverSslCert=/etc/ssl/certs/ca-certificates.crt";
40+
3841
private final CfDataSourceEnvironmentPostProcessor environmentPostProcessor = new CfDataSourceEnvironmentPostProcessor();
3942

4043
private final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
@@ -62,9 +65,80 @@ public void testDataSource() throws Exception {
6265
assertThat(
6366
this.context.getEnvironment().getProperty("spring.datasource.password"))
6467
.isEqualTo("mysql_password");
68+
69+
assertThat(this.context.getEnvironment().getProperty("spring.r2dbc.url"))
70+
.isEqualTo(mysqlJdbcUrl.replace("jdbc:", "r2dbc:").substring(0, mysqlJdbcUrl.indexOf("?") + 1));
71+
assertThat(
72+
this.context.getEnvironment().getProperty("spring.r2dbc.username"))
73+
.isEqualTo("mysql_username");
74+
assertThat(
75+
this.context.getEnvironment().getProperty("spring.r2dbc.password"))
76+
.isEqualTo("mysql_password");
6577

6678
} finally {
6779
System.clearProperty("VCAP_APPLICATION");
6880
}
6981
}
82+
83+
@Test
84+
public void testDataSource_r2dbcOptions() throws Exception {
85+
86+
// To make CloudPlatform test pass
87+
try {
88+
System.setProperty("VCAP_APPLICATION", "yes");
89+
90+
// To setup values used by CfEnv
91+
File file = ResourceUtils.getFile("classpath:vcap-services-tls.json");
92+
String fileContents = new String(Files.readAllBytes(file.toPath()));
93+
mockVcapServices(fileContents);
94+
95+
96+
environmentPostProcessor.postProcessEnvironment(this.context.getEnvironment(),
97+
null);
98+
assertThat(this.context.getEnvironment().getProperty("spring.datasource.url"))
99+
.isEqualTo(tlsMysqlJdbcUrl);
100+
assertThat(
101+
this.context.getEnvironment().getProperty("spring.datasource.username"))
102+
.isEqualTo("mysql_username");
103+
assertThat(
104+
this.context.getEnvironment().getProperty("spring.datasource.password"))
105+
.isEqualTo("mysql_password");
106+
107+
assertThat(this.context.getEnvironment().getProperty("spring.r2dbc.url"))
108+
.isEqualTo(tlsMysqlJdbcUrl.replace("jdbc:", "r2dbc:").substring(0, tlsMysqlJdbcUrl.indexOf("?") + 1));
109+
assertThat(
110+
this.context.getEnvironment().getProperty("spring.r2dbc.username"))
111+
.isEqualTo("mysql_username");
112+
assertThat(
113+
this.context.getEnvironment().getProperty("spring.r2dbc.password"))
114+
.isEqualTo("mysql_password");
115+
assertThat(
116+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.user"))
117+
.isEqualTo("mysql_username");
118+
assertThat(
119+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.password"))
120+
.isEqualTo("mysql_password");
121+
assertThat(
122+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.sslMode"))
123+
.isEqualTo("VERIFY_IDENTITY");
124+
assertThat(
125+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.useSSL"))
126+
.isEqualTo("true");
127+
assertThat(
128+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.requireSSL"))
129+
.isEqualTo("true");
130+
assertThat(
131+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.tlsVersion"))
132+
.isEqualTo("TLSv1.2");
133+
assertThat(
134+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.serverSslCert"))
135+
.isEqualTo("/etc/ssl/certs/ca-certificates.crt");
136+
assertThat(
137+
this.context.getEnvironment().getProperty("spring.r2dbc.properties.serverSslCert"))
138+
.isEqualTo("/etc/ssl/certs/ca-certificates.crt");
139+
140+
} finally {
141+
System.clearProperty("VCAP_APPLICATION");
142+
}
143+
}
70144
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"p-mysql": [
3+
{
4+
"credentials": {
5+
"hostname": "10.0.4.35",
6+
"port": 3306,
7+
"name": "mysql_name",
8+
"username": "mysql_username",
9+
"password": "mysql_password",
10+
"uri": "mysql://mysql_username:[email protected]:3306/service_instance_db?reconnect=true",
11+
"jdbcUrl": "jdbc:mysql://10.0.4.35:3306/service_instance_db?permitMysqlScheme&user=mysql_username&password=mysql_password&sslMode=VERIFY_IDENTITY&useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2&serverSslCert=/etc/ssl/certs/ca-certificates.crt"
12+
},
13+
"syslog_drain_url": null,
14+
"volume_mounts": [],
15+
"label": "p-mysql",
16+
"provider": null,
17+
"plan": "100mb",
18+
"name": "mysql",
19+
"tags": [
20+
"mysql",
21+
"relational"
22+
]
23+
}
24+
]
25+
}

0 commit comments

Comments
 (0)