diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/jpa/EntityManagerFactoryCustomizer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/jpa/EntityManagerFactoryCustomizer.java
new file mode 100644
index 000000000..e2a77c959
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/jpa/EntityManagerFactoryCustomizer.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.infrastructure.core.config.jpa;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
+
+/**
+ * A customizer interface for the EntityManager factories. Register an implementation of this interface as a Spring
+ * bean, and it'll be picked up automatically.
+ *
+ * Multiple customizers could be registered and all of them will be picked up by the application.
+ *
+ * The order in which the customizations are applied is not guaranteed.
+ *
+ * @see JPAConfig
+ */
+public interface EntityManagerFactoryCustomizer {
+
+ /**
+ * Additional packages to scan, for example in case of custom modules.
+ *
+ * @return a Set of package names, not null
+ */
+ default Set additionalPackagesToScan() {
+ return Collections.emptySet();
+ }
+
+ /**
+ * Additional vendor properties to be passed to EclipseLink; useful in case of fine-tuning.
+ *
+ * @return a Set of vendor properties, not null
+ */
+ default Map additionalVendorProperties() {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Additional {@link PersistenceUnitPostProcessor} configuration in case customizations are required.
+ *
+ * @return Set of PersistenceUnitPostProcessors, not null
+ */
+ default Set additionalPersistenceUnitPostProcessors() {
+ return Collections.emptySet();
+ }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/jpa/JPAConfig.java
similarity index 70%
rename from fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java
rename to fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/jpa/JPAConfig.java
index 2061fdb6e..77c1f7866 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/JPAConfig.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/jpa/JPAConfig.java
@@ -17,9 +17,13 @@
* under the License.
*/
-package org.apache.fineract.infrastructure.core.config;
+package org.apache.fineract.infrastructure.core.config.jpa;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import org.apache.fineract.infrastructure.core.auditing.JpaAuditingHandlerRegistrar;
import org.apache.fineract.infrastructure.core.domain.AuditorAwareImpl;
import org.apache.fineract.infrastructure.core.persistence.DatabaseSelectingPersistenceUnitPostProcessor;
@@ -43,6 +47,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
+import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
@@ -57,11 +62,13 @@ import org.springframework.transaction.support.TransactionTemplate;
public class JPAConfig extends JpaBaseConfiguration {
private final DatabaseTypeResolver databaseTypeResolver;
+ private final Collection emFactoryCustomizers;
public JPAConfig(RoutingDataSource dataSource, JpaProperties properties, ObjectProvider jtaTransactionManager,
- DatabaseTypeResolver databaseTypeResolver) {
+ DatabaseTypeResolver databaseTypeResolver, Collection customizers) {
super(dataSource, properties, jtaTransactionManager);
this.databaseTypeResolver = databaseTypeResolver;
+ this.emFactoryCustomizers = customizers;
}
@Override
@@ -70,9 +77,27 @@ public class JPAConfig extends JpaBaseConfiguration {
@DependsOn("tenantDatabaseUpgradeService")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
Map vendorProperties = getVendorProperties();
- customizeVendorProperties(vendorProperties);
- return factoryBuilder.dataSource(getDataSource()).properties(vendorProperties).persistenceUnit("jpa-pu")
- .packages("org.apache.fineract").jta(false).build();
+ String[] packagesToScan = getPackagesToScan();
+ return factoryBuilder.dataSource(getDataSource()).properties(vendorProperties).persistenceUnit("jpa-pu").packages(packagesToScan)
+ .jta(false).build();
+ }
+
+ @Override
+ protected Map getVendorProperties() {
+ Map vendorProperties = new HashMap<>();
+ vendorProperties.put(PersistenceUnitProperties.WEAVING, "static");
+ vendorProperties.put(PersistenceUnitProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, "true");
+ vendorProperties.put(PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false");
+ emFactoryCustomizers.forEach(c -> vendorProperties.putAll(c.additionalVendorProperties()));
+ return vendorProperties;
+ }
+
+ @Override
+ protected String[] getPackagesToScan() {
+ Set packagesToScan = new HashSet<>();
+ packagesToScan.add("org.apache.fineract");
+ emFactoryCustomizers.forEach(c -> packagesToScan.addAll(c.additionalPackagesToScan()));
+ return packagesToScan.toArray(String[]::new);
}
@Override
@@ -80,21 +105,22 @@ public class JPAConfig extends JpaBaseConfiguration {
ObjectProvider persistenceUnitManager,
ObjectProvider customizers) {
EntityManagerFactoryBuilder builder = super.entityManagerFactoryBuilder(jpaVendorAdapter, persistenceUnitManager, customizers);
- builder.setPersistenceUnitPostProcessors(new DatabaseSelectingPersistenceUnitPostProcessor(databaseTypeResolver));
+ builder.setPersistenceUnitPostProcessors(getPersistenceUnitPostProcessors());
return builder;
}
+ private PersistenceUnitPostProcessor[] getPersistenceUnitPostProcessors() {
+ Set processors = new HashSet<>();
+ processors.add(new DatabaseSelectingPersistenceUnitPostProcessor(databaseTypeResolver));
+ emFactoryCustomizers.forEach(c -> processors.addAll(c.additionalPersistenceUnitPostProcessors()));
+ return processors.toArray(PersistenceUnitPostProcessor[]::new);
+ }
+
@Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
return new EclipseLinkJpaVendorAdapter();
}
- @Override
- protected Map getVendorProperties() {
- return Map.of(PersistenceUnitProperties.WEAVING, "static", PersistenceUnitProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, "true",
- PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false");
- }
-
@Bean
public AuditorAware auditorAware() {
return new AuditorAwareImpl();