FINERACT-1724: Ability to customize the EntityManagerFactory from custom

modules
This commit is contained in:
Arnold Galovics
2022-10-20 06:39:29 +02:00
committed by Arnold Gálovics
parent f496e2ff0e
commit 3cd4db8209
2 changed files with 102 additions and 12 deletions
@@ -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. <br>
* <br>
* Multiple customizers could be registered and all of them will be picked up by the application. <br>
* <br>
* 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<String> 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<String, Object> additionalVendorProperties() {
return Collections.emptyMap();
}
/**
* Additional {@link PersistenceUnitPostProcessor} configuration in case customizations are required.
*
* @return Set of PersistenceUnitPostProcessors, not null
*/
default Set<PersistenceUnitPostProcessor> additionalPersistenceUnitPostProcessors() {
return Collections.emptySet();
}
}
@@ -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<EntityManagerFactoryCustomizer> emFactoryCustomizers;
public JPAConfig(RoutingDataSource dataSource, JpaProperties properties, ObjectProvider<JtaTransactionManager> jtaTransactionManager,
DatabaseTypeResolver databaseTypeResolver) {
DatabaseTypeResolver databaseTypeResolver, Collection<EntityManagerFactoryCustomizer> 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<String, Object> 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<String, Object> getVendorProperties() {
Map<String, Object> 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<String> 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> persistenceUnitManager,
ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers) {
EntityManagerFactoryBuilder builder = super.entityManagerFactoryBuilder(jpaVendorAdapter, persistenceUnitManager, customizers);
builder.setPersistenceUnitPostProcessors(new DatabaseSelectingPersistenceUnitPostProcessor(databaseTypeResolver));
builder.setPersistenceUnitPostProcessors(getPersistenceUnitPostProcessors());
return builder;
}
private PersistenceUnitPostProcessor[] getPersistenceUnitPostProcessors() {
Set<PersistenceUnitPostProcessor> 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<String, Object> getVendorProperties() {
return Map.of(PersistenceUnitProperties.WEAVING, "static", PersistenceUnitProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, "true",
PersistenceUnitProperties.CACHE_SHARED_DEFAULT, "false");
}
@Bean
public AuditorAware<Long> auditorAware() {
return new AuditorAwareImpl();