Skip to content

Commit 75b3ff4

Browse files
raedbhodrotbohm
authored andcommitted
GH-685 - Introduce spring.modulith.events.jdbc.schema to allow defining the database schema for the event_publication table.
1 parent 17c329d commit 75b3ff4

File tree

8 files changed

+337
-110
lines changed

8 files changed

+337
-110
lines changed

spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/DatabaseSchemaInitializer.java

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,78 @@
1515
*/
1616
package org.springframework.modulith.events.jdbc;
1717

18+
import java.sql.Connection;
19+
20+
import javax.sql.DataSource;
21+
1822
import org.springframework.beans.factory.InitializingBean;
23+
import org.springframework.core.io.ResourceLoader;
24+
import org.springframework.jdbc.core.JdbcTemplate;
25+
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
26+
import org.springframework.util.ObjectUtils;
1927

2028
/**
2129
* Initializes the DB schema used to store events
2230
*
2331
* @author Dmitry Belyaev
2432
* @author Björn Kieling
2533
* @author Oliver Drotbohm
34+
* @author Raed Ben Hamouda
2635
*/
27-
interface DatabaseSchemaInitializer extends InitializingBean {}
36+
class DatabaseSchemaInitializer implements InitializingBean {
37+
38+
private final DataSource dataSource;
39+
private final ResourceLoader resourceLoader;
40+
private final DatabaseType databaseType;
41+
private final JdbcTemplate jdbcTemplate;
42+
private final JdbcConfigurationProperties properties;
43+
44+
DatabaseSchemaInitializer(DataSource dataSource, ResourceLoader resourceLoader, DatabaseType databaseType,
45+
JdbcTemplate jdbcTemplate, JdbcConfigurationProperties properties) {
46+
47+
this.dataSource = dataSource;
48+
this.resourceLoader = resourceLoader;
49+
this.databaseType = databaseType;
50+
this.jdbcTemplate = jdbcTemplate;
51+
this.properties = properties;
52+
}
53+
54+
@Override
55+
public void afterPropertiesSet() throws Exception {
56+
57+
String initialSchema;
58+
try (Connection connection = dataSource.getConnection()) {
59+
60+
initialSchema = connection.getSchema();
61+
62+
String schemaName = properties.getSchema();
63+
if (!ObjectUtils.isEmpty(schemaName)) { // A schema name has been specified.
64+
65+
if (eventPublicationTableExists(jdbcTemplate, schemaName)) {
66+
return;
67+
}
68+
69+
jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS " + schemaName);
70+
jdbcTemplate.execute(databaseType.sqlStatementSetSchema(schemaName));
71+
}
72+
73+
var locator = new DatabaseSchemaLocator(resourceLoader);
74+
new ResourceDatabasePopulator(locator.getSchemaResource(databaseType)).execute(dataSource);
75+
76+
// Return to the initial schema.
77+
if (initialSchema != null) {
78+
jdbcTemplate.execute(databaseType.sqlStatementSetSchema(initialSchema));
79+
}
80+
}
81+
}
82+
83+
private boolean eventPublicationTableExists(JdbcTemplate jdbcTemplate, String schema) {
84+
String query = """
85+
SELECT COUNT(*)
86+
FROM information_schema.tables
87+
WHERE table_schema = ? AND table_name = 'EVENT_PUBLICATION'
88+
""";
89+
Integer count = jdbcTemplate.queryForObject(query, Integer.class, schema);
90+
return count != null && count > 0;
91+
}
92+
}

spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/DatabaseType.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* @author Dmitry Belyaev
2525
* @author Björn Kieling
2626
* @author Oliver Drotbohm
27+
* @author Raed Ben Hamouda
2728
*/
2829
enum DatabaseType {
2930

@@ -75,4 +76,11 @@ UUID databaseToUUID(Object id) {
7576
String getSchemaResourceFilename() {
7677
return "/schema-" + value + ".sql";
7778
}
79+
80+
String sqlStatementSetSchema(String schema) {
81+
return switch (this) {
82+
case MYSQL, H2, HSQLDB -> "SET SCHEMA " + schema;
83+
case POSTGRES -> "SET search_path TO " + schema;
84+
};
85+
}
7886
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2022-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.modulith.events.jdbc;
17+
18+
import org.springframework.boot.context.properties.ConfigurationProperties;
19+
import org.springframework.boot.context.properties.bind.ConstructorBinding;
20+
import org.springframework.boot.context.properties.bind.DefaultValue;
21+
import org.springframework.lang.Nullable;
22+
23+
/**
24+
* Configuration properties for JDBC.
25+
*
26+
* @author Raed Ben Hamouda
27+
*/
28+
@ConfigurationProperties(prefix = "spring.modulith.events.jdbc")
29+
class JdbcConfigurationProperties {
30+
31+
private final boolean schemaInitializationEnabled;
32+
private final String schema;
33+
34+
/**
35+
* Creates a new {@link JdbcConfigurationProperties} instance.
36+
*
37+
* @param schemaInitializationEnabled whether to initialize the JDBC event publication schema. Defaults to {@literal false}.
38+
* @param schema the schema name of event publication table, can be {@literal null}.
39+
*/
40+
@ConstructorBinding
41+
JdbcConfigurationProperties(@DefaultValue("false") boolean schemaInitializationEnabled, @Nullable String schema) {
42+
43+
this.schemaInitializationEnabled = schemaInitializationEnabled;
44+
this.schema = schema;
45+
}
46+
47+
/**
48+
* Whether to initialize the JDBC event publication schema.
49+
*/
50+
public boolean isSchemaInitializationEnabled() {
51+
return schemaInitializationEnabled;
52+
}
53+
54+
/**
55+
* The name of the schema where the event publication table resides.
56+
*
57+
* @return can be {@literal null}.
58+
*/
59+
public String getSchema() {
60+
return schema;
61+
}
62+
}

spring-modulith-events/spring-modulith-events-jdbc/src/main/java/org/springframework/modulith/events/jdbc/JdbcEventPublicationAutoConfiguration.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121

2222
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
24+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2425
import org.springframework.context.annotation.Bean;
2526
import org.springframework.context.annotation.Configuration;
2627
import org.springframework.core.io.ResourceLoader;
2728
import org.springframework.jdbc.core.JdbcTemplate;
28-
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
2929
import org.springframework.jdbc.support.JdbcUtils;
3030
import org.springframework.modulith.events.config.EventPublicationAutoConfiguration;
3131
import org.springframework.modulith.events.config.EventPublicationConfigurationExtension;
@@ -35,9 +35,11 @@
3535
* @author Dmitry Belyaev
3636
* @author Björn Kieling
3737
* @author Oliver Drotbohm
38+
* @author Raed Ben Hamouda
3839
*/
3940
@Configuration(proxyBeanMethods = false)
4041
@AutoConfigureBefore(EventPublicationAutoConfiguration.class)
42+
@EnableConfigurationProperties(JdbcConfigurationProperties.class)
4143
class JdbcEventPublicationAutoConfiguration implements EventPublicationConfigurationExtension {
4244

4345
@Bean
@@ -47,22 +49,17 @@ DatabaseType databaseType(DataSource dataSource) {
4749

4850
@Bean
4951
JdbcEventPublicationRepository jdbcEventPublicationRepository(JdbcTemplate jdbcTemplate,
50-
EventSerializer serializer, DatabaseType databaseType) {
52+
EventSerializer serializer, DatabaseType databaseType, JdbcConfigurationProperties properties) {
5153

52-
return new JdbcEventPublicationRepository(jdbcTemplate, serializer, databaseType);
54+
return new JdbcEventPublicationRepository(jdbcTemplate, serializer, databaseType, properties);
5355
}
5456

5557
@Bean
5658
@ConditionalOnProperty(name = "spring.modulith.events.jdbc.schema-initialization.enabled", havingValue = "true")
5759
DatabaseSchemaInitializer databaseSchemaInitializer(DataSource dataSource, ResourceLoader resourceLoader,
58-
DatabaseType databaseType) {
60+
DatabaseType databaseType, JdbcTemplate jdbcTemplate, JdbcConfigurationProperties properties) {
5961

60-
return () -> {
61-
62-
var locator = new DatabaseSchemaLocator(resourceLoader);
63-
64-
new ResourceDatabasePopulator(locator.getSchemaResource(databaseType)).execute(dataSource);
65-
};
62+
return new DatabaseSchemaInitializer(dataSource, resourceLoader, databaseType, jdbcTemplate, properties);
6663
}
6764

6865
private static String fromDataSource(DataSource dataSource) {

0 commit comments

Comments
 (0)