From 25191b7d247e8d191537e4b4053a1b3e33a7d780 Mon Sep 17 00:00:00 2001
From: Adrien Kantcheff <5028967+akantcheff@users.noreply.github.com>
Date: Wed, 25 Sep 2024 11:12:56 +0200
Subject: [PATCH] feat(community-back): move hibernate interceptors and
dialects to SP (#3168)
* feat(hibernate): move hibernate properties to SP
* feat(hibernate): move hibernate interceptors to SP
* feat(hibernate): move custom data types registration to SP
* test(business-data): execute community database IT from SP
* feat(persistence): move SQLServerExtendedDialect to SP
* feat(persistence): move SQLServerOrderByBuilder to SP
* add bonita-persistence testRuntimeOnly dep
* fix(persistence): throw exception if unknown vendor
* fix(persistence): call super in default switch case
---
.../TestLocalSessionFactoryBuilder.java | 8 +-
.../engine/home/BonitaHomeServer.java | 1 -
...nita-platform-private-community.properties | 9 --
...bonita-tenant-private-community.properties | 6 -
.../bonita-business-data-impl/build.gradle | 6 -
.../datasource-dependency-mysql.xml | 32 ------
.../datasource-dependency-oracle.xml | 32 ------
.../datasource-dependency-sqlserver.xml | 32 ------
services/bonita-persistence/build.gradle | 17 +--
.../CustomDataTypesRegistration.java | 7 +-
.../HibernateConfigurationProviderImpl.java | 108 ++++++++++--------
.../HibernatePersistenceService.java | 4 -
.../engine/persistence/OracleInterceptor.java | 56 ---------
.../persistence/SQLServerExtendedDialect.java | 34 ------
.../persistence/SQLServerInterceptor.java | 30 -----
.../persistence/SQLServerOrderByBuilder.java | 46 --------
.../persistence/OracleInterceptorTest.java | 83 --------------
.../SQLServerOrderByBuilderTest.java | 89 ---------------
18 files changed, 75 insertions(+), 525 deletions(-)
delete mode 100644 bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-tenant-private-community.properties
delete mode 100644 services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-mysql.xml
delete mode 100644 services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-oracle.xml
delete mode 100644 services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-sqlserver.xml
delete mode 100644 services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/OracleInterceptor.java
delete mode 100644 services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/SQLServerExtendedDialect.java
delete mode 100644 services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/SQLServerInterceptor.java
delete mode 100644 services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/SQLServerOrderByBuilder.java
delete mode 100644 services/bonita-persistence/src/test/java/org/bonitasoft/engine/persistence/OracleInterceptorTest.java
delete mode 100644 services/bonita-persistence/src/test/java/org/bonitasoft/engine/persistence/SQLServerOrderByBuilderTest.java
diff --git a/bonita-integration-tests/bonita-query-tests/src/test/java/org/bonitasoft/engine/test/persistence/TestLocalSessionFactoryBuilder.java b/bonita-integration-tests/bonita-query-tests/src/test/java/org/bonitasoft/engine/test/persistence/TestLocalSessionFactoryBuilder.java
index 8162abeef96..36b890b6991 100644
--- a/bonita-integration-tests/bonita-query-tests/src/test/java/org/bonitasoft/engine/test/persistence/TestLocalSessionFactoryBuilder.java
+++ b/bonita-integration-tests/bonita-query-tests/src/test/java/org/bonitasoft/engine/test/persistence/TestLocalSessionFactoryBuilder.java
@@ -27,14 +27,16 @@ protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) {
//register type before loading mappings/entities, type should be present before loading JPA entities
switch (vendor) {
case ORACLE:
- sfb.setInterceptor(new OracleInterceptor());
+ // FIXME set following interceptor when this module is configured to run on all DB
+ // sfb.setInterceptor(new OracleInterceptor());
break;
case MYSQL:
case OTHER:
sfb.registerTypeOverride(XMLType.INSTANCE);
break;
case SQLSERVER:
- sfb.setInterceptor(new SQLServerInterceptor());
+ // FIXME set following interceptor when this module is configured to run on all DB
+ // sfb.setInterceptor(new SQLServerInterceptor());
sfb.registerTypeOverride(XMLType.INSTANCE);
break;
case POSTGRES:
@@ -43,7 +45,7 @@ protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) {
sfb.registerTypeOverride(new PostgresMaterializedClobType());
sfb.registerTypeOverride(PostgresXMLType.INSTANCE);
break;
- };
+ }
return super.buildSessionFactory(sfb);
}
}
diff --git a/bpm/bonita-core/bonita-home-server/src/main/java/org/bonitasoft/engine/home/BonitaHomeServer.java b/bpm/bonita-core/bonita-home-server/src/main/java/org/bonitasoft/engine/home/BonitaHomeServer.java
index 55bab6bd13b..bf2b1b1e153 100644
--- a/bpm/bonita-core/bonita-home-server/src/main/java/org/bonitasoft/engine/home/BonitaHomeServer.java
+++ b/bpm/bonita-core/bonita-home-server/src/main/java/org/bonitasoft/engine/home/BonitaHomeServer.java
@@ -107,7 +107,6 @@ public Properties getTenantProperties(long tenantId) throws IOException {
Properties allProperties = getPlatformProperties();
Properties tenantProperties = mergeProperties(getPropertiesFromClassPath(
"bonita-tenant-community.properties",
- "bonita-tenant-private-community.properties",
"bonita-tenant-sp.properties",
"bonita-tenant-sp-cluster.properties"), getConfigurationService().getTenantEngineConf(tenantId));
allProperties.putAll(tenantProperties);
diff --git a/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-platform-private-community.properties b/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-platform-private-community.properties
index 48f713a7b43..b0df05e3c1b 100644
--- a/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-platform-private-community.properties
+++ b/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-platform-private-community.properties
@@ -7,21 +7,12 @@ serverApi=org.bonitasoft.engine.api.impl.ServerAPIImpl
# Hibernate Dialects
h2.hibernate.dialect=org.hibernate.dialect.H2Dialect
-mysql.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
-oracle.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
postgres.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect
-sqlserver.hibernate.dialect=org.bonitasoft.engine.persistence.SQLServerExtendedDialect
# Hibernate Interceptors for journal (runtime database)
h2.hibernate.journal.interceptor=
-mysql.hibernate.journal.interceptor=
-oracle.hibernate.journal.interceptor=org.bonitasoft.engine.persistence.OracleInterceptor
postgres.hibernate.journal.interceptor=org.bonitasoft.engine.persistence.PostgresInterceptor
-sqlserver.hibernate.journal.interceptor=org.bonitasoft.engine.persistence.SQLServerInterceptor
# Quartz properties
h2.quartz.connection.jobstoredriver=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
-mysql.quartz.connection.jobstoredriver=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
-oracle.quartz.connection.jobstoredriver=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
postgres.quartz.connection.jobstoredriver=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
-sqlserver.quartz.connection.jobstoredriver=org.quartz.impl.jdbcjobstore.MSSQLDelegate
diff --git a/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-tenant-private-community.properties b/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-tenant-private-community.properties
deleted file mode 100644
index 9729b4a6206..00000000000
--- a/bpm/bonita-core/bonita-process-engine/src/main/resources/bonita-tenant-private-community.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-# Hibernate Dialects
-h2.hibernate.dialect=org.hibernate.dialect.H2Dialect
-mysql.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
-oracle.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
-postgres.hibernate.dialect=org.hibernate.dialect.PostgreSQL10Dialect
-sqlserver.hibernate.dialect=org.bonitasoft.engine.persistence.SQLServerExtendedDialect
\ No newline at end of file
diff --git a/services/bonita-business-data/bonita-business-data-impl/build.gradle b/services/bonita-business-data/bonita-business-data-impl/build.gradle
index 68f28ac41ab..4323a45b26c 100644
--- a/services/bonita-business-data/bonita-business-data-impl/build.gradle
+++ b/services/bonita-business-data/bonita-business-data-impl/build.gradle
@@ -33,10 +33,4 @@ dependencies {
testImplementation("com.pholser:junit-quickcheck-generators:${Deps.junitQuickCheck}")
}
-// run:
-// ./gradlew mysqlDatabaseTest
-// ./gradlew oracleDatabaseTest
-// ./gradlew sqlserverDatabaseTest
-// ./gradlew postgresDatabaseTest
-// to run tests on specific docker DB:
databaseIntegrationTest { includes '**/*Test.class' }
diff --git a/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-mysql.xml b/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-mysql.xml
deleted file mode 100644
index 3b0e51a6444..00000000000
--- a/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-mysql.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
- org.hibernate.dialect.MySQL8Dialect
- com.mysql.cj.jdbc.MysqlXADataSource
- localhost
- 3306
- bonita
- root
- root
- jdbc:mysql://${db.server.name}:${db.server.port}/${db.database.name}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true
-
-
-
-
-
-
-
- ${db.user}
- ${db.password}
- ${db.url}
-
-
-
-
-
diff --git a/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-oracle.xml b/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-oracle.xml
deleted file mode 100644
index 16f356b3df2..00000000000
--- a/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-oracle.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
- org.hibernate.dialect.Oracle12cDialect
- oracle.jdbc.xa.client.OracleXADataSource
- localhost
- 1521
- ${db.database.name:ORCLPDB1.localdomain}
- bonita
- bpm
- jdbc:oracle:thin:@//${db.server.name}:${db.server.port}/${db.instance.name}?oracle.net.disableOob=true
-
-
-
-
-
-
-
- ${db.user}
- ${db.password}
- jdbc:oracle:thin:@//${db.server.name}:${db.server.port}/${db.instance.name}?oracle.net.disableOob=true
-
-
-
-
-
diff --git a/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-sqlserver.xml b/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-sqlserver.xml
deleted file mode 100644
index e048197594e..00000000000
--- a/services/bonita-business-data/bonita-business-data-impl/src/test/resources/datasource/datasource-dependency-sqlserver.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
- org.bonitasoft.engine.persistence.SQLServerExtendedDialect
- com.microsoft.sqlserver.jdbc.SQLServerXADataSource
- localhost
- 1533
- bonita_engine
- sa
- Bonita12
- jdbc:sqlserver://${db.server.name}:${db.server.port};database=${db.database.name}
-
-
-
-
-
-
-
- ${db.user}
- ${db.password}
- ${db.url}
-
-
-
-
-
\ No newline at end of file
diff --git a/services/bonita-persistence/build.gradle b/services/bonita-persistence/build.gradle
index 5f1ac3ae559..8d179cb4a74 100644
--- a/services/bonita-persistence/build.gradle
+++ b/services/bonita-persistence/build.gradle
@@ -1,7 +1,3 @@
-plugins {
- id('bonita-tests')
-}
-
dependencies {
api libs.commonsLang
api project(':services:bonita-events')
@@ -14,16 +10,21 @@ dependencies {
api project(':services:bonita-commons')
api project(':services:bonita-lock')
api libs.slf4jApi
+
implementation(libs.javaxAnnotations)
- testImplementation "junit:junit:${Deps.junit4Version}"
- testImplementation "org.mockito:mockito-core:${Deps.mockitoVersion}"
- testImplementation "org.assertj:assertj-core:${Deps.assertjVersion}"
+
compileOnly libs.jakartaTransactionApi
annotationProcessor libs.lombok
compileOnly libs.lombok
- testRuntimeOnly libs.logback
+
+ testImplementation "junit:junit:${Deps.junit4Version}"
+ testImplementation "org.mockito:mockito-core:${Deps.mockitoVersion}"
+ testImplementation "org.assertj:assertj-core:${Deps.assertjVersion}"
testImplementation "com.github.stefanbirkner:system-rules:${Deps.systemRulesVersion}"
+
testAnnotationProcessor libs.lombok
testImplementation libs.lombok
+
+ testRuntimeOnly libs.logback
}
diff --git a/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/CustomDataTypesRegistration.java b/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/CustomDataTypesRegistration.java
index 748f1047355..4ca8b54df58 100644
--- a/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/CustomDataTypesRegistration.java
+++ b/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/CustomDataTypesRegistration.java
@@ -16,6 +16,7 @@
import java.util.HashSet;
import java.util.Set;
+import lombok.Getter;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.boot.spi.SessionFactoryBuilderFactory;
@@ -27,6 +28,7 @@ public class CustomDataTypesRegistration implements SessionFactoryBuilderFactory
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CustomDataTypesRegistration.class);
+ @Getter
private static Set typeOverrides = new HashSet<>();
@Override
@@ -39,11 +41,8 @@ public SessionFactoryBuilder getSessionFactoryBuilder(final MetadataImplementor
return defaultBuilder;
}
- static void addTypeOverride(BasicType type) {
+ public static void addTypeOverride(BasicType type) {
typeOverrides.add(type);
}
- public static Set getTypeOverrides() {
- return typeOverrides;
- }
}
diff --git a/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/HibernateConfigurationProviderImpl.java b/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/HibernateConfigurationProviderImpl.java
index 031990fc526..8e43fe9be5a 100644
--- a/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/HibernateConfigurationProviderImpl.java
+++ b/services/bonita-persistence/src/main/java/org/bonitasoft/engine/persistence/HibernateConfigurationProviderImpl.java
@@ -13,7 +13,7 @@
**/
package org.bonitasoft.engine.persistence;
-import static org.bonitasoft.engine.services.Vendor.*;
+import static org.bonitasoft.engine.services.Vendor.POSTGRES;
import java.util.ArrayList;
import java.util.Collections;
@@ -23,6 +23,7 @@
import javax.persistence.SharedCacheMode;
+import lombok.Getter;
import org.bonitasoft.engine.services.Vendor;
import org.hibernate.Interceptor;
import org.hibernate.SessionFactory;
@@ -30,11 +31,11 @@
import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.SessionFactoryBuilder;
-import org.hibernate.boot.registry.BootstrapServiceRegistry;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.mapping.PersistentClass;
+import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.BasicType;
/**
@@ -47,9 +48,12 @@ public class HibernateConfigurationProviderImpl implements HibernateConfiguratio
private final HibernateResourcesConfigurationProvider hibernateResourcesConfigurationProvider;
protected final Properties properties;
private final List mappingExclusions;
- private Vendor vendor;
+ @Getter
+ protected Vendor vendor;
+ @Getter
private SessionFactory sessionFactory;
- private List> mappedClasses = new ArrayList<>();
+ @Getter
+ private final List> mappedClasses = new ArrayList<>();
public HibernateConfigurationProviderImpl(final Properties properties,
final HibernateResourcesConfigurationProvider hibernateResourcesConfigurationProvider,
@@ -76,27 +80,45 @@ public Map getCacheQueries() {
@Override
public void bootstrap(Properties extraHibernateProperties) {
- BootstrapServiceRegistryBuilder bootstrapRegistryBuilder = new BootstrapServiceRegistryBuilder();
- BootstrapServiceRegistry bootstrapRegistry = bootstrapRegistryBuilder.build();
- StandardServiceRegistryBuilder standardRegistryBuilder = new StandardServiceRegistryBuilder(bootstrapRegistry);
+ StandardServiceRegistryBuilder standardRegistryBuilder = new StandardServiceRegistryBuilder(
+ new BootstrapServiceRegistryBuilder().build());
Properties allProps = gatherAllProperties(extraHibernateProperties, standardRegistryBuilder);
- this.vendor = Vendor.fromHibernateDialectProperty(allProps.getProperty("hibernate.dialect"));
StandardServiceRegistry standardRegistry = standardRegistryBuilder.build();
+
+ this.vendor = Vendor.fromHibernateDialectProperty(allProps.getProperty("hibernate.dialect"));
+ setCustomHibernateDataTypesAndProperties();
+
+ Metadata metadata = buildHibernateMetadata(standardRegistry);
+
+ this.sessionFactory = applyInterceptors(metadata, allProps).build();
+
+ for (PersistentClass entityBinding : metadata.getEntityBindings()) {
+ mappedClasses.add(entityBinding.getMappedClass());
+ }
+ }
+
+ /**
+ * Set custom Hibernate data types using {@link CustomDataTypesRegistration} and set Hibernate system properties.
+ */
+ protected void setCustomHibernateDataTypesAndProperties() {
switch (vendor) {
- case ORACLE:
- case SQLSERVER:
- case MYSQL:
- System.setProperty("hibernate.dialect.storage_engine", "innodb");
- case OTHER:
- CustomDataTypesRegistration.addTypeOverride(new XMLType());
- break;
- case POSTGRES:
+ case POSTGRES -> {
CustomDataTypesRegistration.addTypeOverride(new PostgresMaterializedBlobType());
CustomDataTypesRegistration.addTypeOverride(new PostgresMaterializedClobType());
CustomDataTypesRegistration.addTypeOverride(new PostgresXMLType());
- break;
+ }
+ case OTHER -> CustomDataTypesRegistration.addTypeOverride(new XMLType());
+ default -> throw new IllegalStateException("Unsupported vendor: " + vendor);
}
+ }
+ /**
+ * Build the hibernate metadata from the provided resources and entities.
+ *
+ * @param standardRegistry the standard registry of services needed to create metadata sources
+ * @return the hibernate metadata
+ */
+ private Metadata buildHibernateMetadata(ServiceRegistry standardRegistry) {
MetadataSources metadataSources = new MetadataSources(standardRegistry) {
@Override
@@ -116,31 +138,33 @@ public MetadataBuilder getMetadataBuilder() {
for (Class entity : hibernateResourcesConfigurationProvider.getEntities()) {
metadataSources.addAnnotatedClass(entity);
}
+ return metadataSources.buildMetadata();
+ }
- Metadata metadata = metadataSources.buildMetadata();
+ /**
+ * Apply interceptors to a new session factory.
+ *
+ * @param metadata the hibernate metadata
+ * @param allProps the hibernate properties
+ * @return a new session factory builder
+ * @throws IllegalStateException if an interceptor class is unknown or cannot be instantiated
+ */
+ protected SessionFactoryBuilder applyInterceptors(Metadata metadata, Properties allProps)
+ throws IllegalStateException {
SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
final String className = allProps.getProperty("hibernate.interceptor");
if (className != null && !className.isEmpty()) {
try {
- final Interceptor interceptor = (Interceptor) Class.forName(className).newInstance();
- sessionFactoryBuilder.applyInterceptor(interceptor);
- } catch (final ClassNotFoundException | IllegalAccessException | InstantiationException cnfe) {
- throw new IllegalStateException("Unknown interceptor class " + className, cnfe);
+ sessionFactoryBuilder.applyInterceptor(
+ (Interceptor) Class.forName(className).getDeclaredConstructor().newInstance());
+ } catch (final ReflectiveOperationException e) {
+ throw new IllegalStateException("Unknown interceptor class " + className, e);
}
}
if (vendor == POSTGRES) {
sessionFactoryBuilder.applyInterceptor(new PostgresInterceptor());
}
- if (vendor == SQLSERVER) {
- sessionFactoryBuilder.applyInterceptor(new SQLServerInterceptor());
- }
- if (vendor == ORACLE) {
- sessionFactoryBuilder.applyInterceptor(new OracleInterceptor());
- }
- this.sessionFactory = sessionFactoryBuilder.build();
- for (PersistentClass entityBinding : metadata.getEntityBindings()) {
- mappedClasses.add(entityBinding.getMappedClass());
- }
+ return sessionFactoryBuilder;
}
protected void applyCacheMode(MetadataBuilder metadataBuilder) {
@@ -150,12 +174,8 @@ protected void applyCacheMode(MetadataBuilder metadataBuilder) {
protected Properties gatherAllProperties(Properties extraHibernateProperties,
StandardServiceRegistryBuilder standardRegistryBuilder) {
Properties allProps = new Properties();
- for (Map.Entry