diff --git a/.github/workflows/crosschecks.yml b/.github/workflows/crosschecks.yml
index de1cbb3423..d146891531 100644
--- a/.github/workflows/crosschecks.yml
+++ b/.github/workflows/crosschecks.yml
@@ -36,6 +36,15 @@ jobs:
java: [ '21', '23-ea' ]
os: [ubuntu-latest, windows-latest, macos-latest]
+ services:
+ postgres:
+ image: postgres:16
+ env:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ ports:
+ - 5432:5432
+
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -61,4 +70,4 @@ jobs:
- name: Test
run: mvn -T 1C clean test '-Dinvoker.streamLogs=true' '-Dmodernizer.skip=true' '-Dianal.phase=none' '-Drat.skip=true' '-Dcheckstyle.skip=true' '-Dsass.skip=true'
- name: Verify
- run: mvn -f fit/core-reference/pom.xml verify '-Dcargo.deployable.ping.timeout=1800000' '-Dit.test=RESTITCase' '-Dinvoker.streamLogs=true' '-Dmodernizer.skip=true' '-Drat.skip=true' '-Dcheckstyle.skip=true' '-Djacoco.skip=true'
+ run: mvn -f fit/core-reference/pom.xml verify '-Dit.test=RESTITCase' '-Dinvoker.streamLogs=true' '-Dmodernizer.skip=true' '-Drat.skip=true' '-Dcheckstyle.skip=true' '-Djacoco.skip=true'
diff --git a/fit/persistence-embedded/src/main/java/org/apache/syncope/fit/persistence/embedded/EmbeddedPostgreSQLContext.java b/fit/persistence-embedded/src/main/java/org/apache/syncope/fit/persistence/embedded/EmbeddedPostgreSQLContext.java
index fbb5e4f109..30bfa6856e 100644
--- a/fit/persistence-embedded/src/main/java/org/apache/syncope/fit/persistence/embedded/EmbeddedPostgreSQLContext.java
+++ b/fit/persistence-embedded/src/main/java/org/apache/syncope/fit/persistence/embedded/EmbeddedPostgreSQLContext.java
@@ -20,39 +20,45 @@
import io.zonky.test.db.postgres.embedded.EmbeddedPostgres;
import java.io.IOException;
+import java.net.Socket;
import java.sql.Connection;
+import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
-import java.util.stream.Stream;
+import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
import org.springframework.jndi.JndiObjectFactoryBean;
+import org.springframework.util.ReflectionUtils;
public class EmbeddedPostgreSQLContext {
private static final Logger LOG = LoggerFactory.getLogger(EmbeddedPostgreSQLContext.class);
+ private static final String DEFAULT_POSTGRES_HOST = "localhost";
+
+ private static final int DEFAULT_POSTGRES_PORT = 5432;
+
+ private static final String DEFAULT_POSTGRES_USER = "postgres";
+
+ private static final String DEFAULT_POSTGRES_PASSWORD = "postgres";
+
@Value("${embedded.databases:syncope}")
private String[] embeddedDatabases;
- @ConditionalOnClass(name = "org.postgresql.Driver")
- @Bean(name = "MasterDataSource")
- public JndiObjectFactoryBean masterDataSource() {
+ private void initDatabases(final Connection conn) throws SQLException {
LOG.info("Creating embedded databases: {}", List.of(embeddedDatabases));
try {
- EmbeddedPostgres pg = EmbeddedPostgres.builder().setPort(5432).start();
-
- Stream.of(embeddedDatabases).forEach(key -> {
- try (Connection conn = pg.getPostgresDatabase().getConnection();
- Statement stmt = conn.createStatement()) {
-
+ for (String key : embeddedDatabases) {
+ try (Statement stmt = conn.createStatement()) {
ResultSet resultSet = stmt.executeQuery(
"SELECT COUNT(*) FROM pg_database WHERE datname = '" + key + "'");
resultSet.next();
@@ -73,15 +79,60 @@ public JndiObjectFactoryBean masterDataSource() {
} catch (SQLException e) {
LOG.error("While creating database {}", key, e);
}
- });
-
- JndiObjectFactoryBean masterDataSource = new JndiObjectFactoryBean();
- masterDataSource.setJndiName("java:comp/env/jdbc/syncopeMasterDataSource");
- masterDataSource.setDefaultObject(pg.getDatabase(
- "syncope", "syncope", Map.of("stringtype", "unspecified")));
- return masterDataSource;
- } catch (IOException e) {
- throw new IllegalStateException("Could not start embedded PostgreSQL", e);
+ }
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
}
}
+
+ @ConditionalOnClass(name = "org.postgresql.Driver")
+ @Bean(name = "MasterDataSource")
+ public JndiObjectFactoryBean masterDataSource(final Environment env) throws SQLException {
+ String dbhost = env.getProperty("POSTGRES_HOST", DEFAULT_POSTGRES_HOST);
+ int dbport = env.getProperty("POSTGRES_PORT", int.class, DEFAULT_POSTGRES_PORT);
+
+ Connection conn;
+ DataSource defaultMasterDS;
+ try (Socket s = new Socket(dbhost, dbport)) {
+ LOG.info("PostgreSQL instance found");
+
+ Class.forName("org.postgresql.Driver");
+ conn = DriverManager.getConnection(
+ "jdbc:postgresql://" + dbhost + ":" + dbport + "/postgres",
+ env.getProperty("POSTGRES_USER", DEFAULT_POSTGRES_USER),
+ env.getProperty("POSTGRES_PASSWORD", DEFAULT_POSTGRES_PASSWORD));
+
+ initDatabases(conn);
+
+ Class> clazz = Class.forName("org.postgresql.ds.PGSimpleDataSource");
+ defaultMasterDS = (DataSource) clazz.getConstructor().newInstance();
+ ReflectionUtils.findMethod(clazz, "setUrl", String.class).invoke(
+ defaultMasterDS,
+ "jdbc:postgresql://" + dbhost + ":" + dbport + "/syncope?stringtype=unspecified");
+ ReflectionUtils.findMethod(clazz, "setUser", String.class).invoke(defaultMasterDS, "syncope");
+ ReflectionUtils.findMethod(clazz, "setPassword", String.class).invoke(defaultMasterDS, "syncope");
+ } catch (IOException ioe) {
+ LOG.info("Starting embedded PostgreSQL");
+
+ try {
+ EmbeddedPostgres pg = EmbeddedPostgres.builder().setPort(dbport).start();
+ conn = pg.getPostgresDatabase().getConnection();
+
+ initDatabases(conn);
+
+ defaultMasterDS = pg.getDatabase("syncope", "syncope", Map.of("stringtype", "unspecified"));
+ } catch (IOException e) {
+ throw new IllegalStateException("Could not start embedded PostgreSQL", e);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected error while setting up embedded persistence", e);
+ }
+
+ JndiObjectFactoryBean masterDataSource = new JndiObjectFactoryBean();
+ masterDataSource.setJndiName("java:comp/env/jdbc/syncopeMasterDataSource");
+ masterDataSource.setDefaultObject(defaultMasterDS);
+ return masterDataSource;
+ }
}
diff --git a/pom.xml b/pom.xml
index 7a9276bd38..ef8ba14924 100644
--- a/pom.xml
+++ b/pom.xml
@@ -494,9 +494,9 @@ under the License.
9805
60000
- 10.1.28
+ 10.1.29
33.0.1.Final
- 6.2024.8
+ 6.2024.9
4.1.1
16-alpine