Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #215 from tesler-platform/feature/bean-injection-b…
Browse files Browse the repository at this point in the history
…y-name-from-application-yml-support

Add support of external beans (non-tesler, e.g. spring, jpa, jackson and so on) injection by name from application.yml
  • Loading branch information
IgorNB authored Sep 21, 2021
2 parents a7952ef + 905ffbf commit 7211713
Show file tree
Hide file tree
Showing 26 changed files with 220 additions and 160 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
java-version: '11'
distribution: 'adopt'
- name: Build with Maven
run: mvn clean install -Pcoverage sonar:sonar javadoc:aggregate -Dsonar.organization=tesler-platform -Dsonar.projectKey=tesler-platform_tesler -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=$SONAR_TOKEN
run: mvn clean install -Pcoverage sonar:sonar -Dsonar.organization=tesler-platform -Dsonar.projectKey=tesler-platform_tesler -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=$SONAR_TOKEN
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Expand Down
5 changes: 5 additions & 0 deletions tesler-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
<groupId>io.tesler</groupId>
<artifactId>tesler-constgen</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*-
* #%L
* IO Tesler - Core
* %%
* Copyright (C) 2018 - 2019 Tesler Contributors
* %%
* Licensed 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.
* #L%
*/

package io.tesler.api.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@Getter
@Setter
@Validated
@ConfigurationProperties(prefix = "tesler.bean")
public class TeslerBeanProperties {

/**
* We use "dataSource" by default to ease springboot-starter-jpa (and so on) integration out of the box.
* Set "primaryDS" legacy value explicitly, if you need this.
*/
private String dataSource = "dataSource";

/**
* We use "entityManagerFactory" by default to ease springboot-starter-jpa (and so on) integration out of the box.
* Set "teslerEntityManagerFactory" legacy value explicitly, if you need this.
*/
private String entityManagerFactory = "entityManagerFactory";

}
14 changes: 13 additions & 1 deletion tesler-base/pom.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<artifactId>tesler-base</artifactId>
Expand Down Expand Up @@ -265,6 +266,17 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<doclint>none</doclint>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

package io.tesler.core.config;

import io.tesler.api.config.TeslerBeanProperties;
import io.tesler.core.metahotreload.conf.MetaHotReloadConfiguration;
import io.tesler.core.service.ResponsibilitiesService;
import io.tesler.core.service.impl.ResponsibilitiesServiceImpl;
Expand All @@ -29,6 +30,7 @@
import io.tesler.model.core.service.TeslerBaseEntityListenerDelegate;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
Expand All @@ -40,6 +42,7 @@
@ImportAutoConfiguration({
MetaHotReloadConfiguration.class
})
@EnableConfigurationProperties(TeslerBeanProperties.class)
public class CoreApplicationConfig {

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -59,19 +57,15 @@ public class BaseDAOImpl extends JpaDaoImpl implements BaseDAO {

private final List<ClassifyDataProvider> providers;

private final Database primaryDatabase;

public BaseDAOImpl(
Set<EntityManager> entityManagers,
TransactionService txService,
Optional<IPdqExtractor> pdqExtractor,
List<ClassifyDataProvider> providers,
@Qualifier("primaryDatabase") Database primaryDatabase
List<ClassifyDataProvider> providers
) {
super(entityManagers, txService);
this.pdqExtractor = pdqExtractor;
this.providers = providers;
this.primaryDatabase = primaryDatabase;
}

private Specification getPdqSearchSpec(final QueryParameters queryParameters) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package io.tesler.core.service.file;

import io.tesler.api.exception.ServerException;
import io.tesler.api.config.TeslerBeanProperties;
import io.tesler.core.exception.ClientException;
import io.tesler.model.core.dao.JpaDao;
import io.tesler.model.core.entity.FileDatasource;
Expand All @@ -35,7 +36,7 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
Expand All @@ -53,7 +54,8 @@ public class CustomSourceFileService {
private final JpaDao jpaDao;

@Autowired
public CustomSourceFileService(@Qualifier("primaryDS") DataSource dataSource, JpaDao jpaDao) {
public CustomSourceFileService(ApplicationContext applicationContext, TeslerBeanProperties teslerBeanProperties, JpaDao jpaDao) {
DataSource dataSource = applicationContext.getBean(teslerBeanProperties.getDataSource(), DataSource.class);
this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
this.jpaDao = jpaDao;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,112 +20,36 @@

package io.tesler.model.core.config;

import static org.hibernate.cfg.AvailableSettings.BATCH_FETCH_STYLE;
import static org.hibernate.cfg.AvailableSettings.BEAN_CONTAINER;
import static org.hibernate.cfg.AvailableSettings.CRITERIA_LITERAL_HANDLING_MODE;
import static org.hibernate.cfg.AvailableSettings.DEFAULT_BATCH_FETCH_SIZE;
import static org.hibernate.cfg.AvailableSettings.FORMAT_SQL;
import static org.hibernate.cfg.AvailableSettings.GENERATE_STATISTICS;
import static org.hibernate.cfg.AvailableSettings.PHYSICAL_NAMING_STRATEGY;
import static org.hibernate.cfg.AvailableSettings.STATEMENT_BATCH_SIZE;
import static org.hibernate.cfg.AvailableSettings.VALIDATE_QUERY_PARAMETERS;

import io.tesler.api.service.tx.ITransactionStatus;
import io.tesler.api.service.tx.TransactionService;
import io.tesler.model.core.api.CurrentUserAware;
import io.tesler.model.core.api.EffectiveUserAware;
import io.tesler.model.core.entity.User;
import io.tesler.model.core.hbn.ImprovedPhysicalNamingStrategy;
import io.tesler.model.core.tx.JpaTransactionManagerCustom;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.hibernate.loader.BatchFetchStyle;
import org.hibernate.query.criteria.LiteralHandlingMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.orm.hibernate5.SpringBeanContainer;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
* To support force active fields in tesler add following bean:
* <pre>{@code
*@Bean
*public PlatformTransactionManager transactionManager(
* final ApplicationContext applicationContext,
* final TeslerBeanProperties teslerBeanProperties,
* final ITransactionStatus txStatus) {
* return new TeslerJpaTransactionManagerForceActiveAware(applicationContext, teslerBeanProperties, txStatus);
*}
* }</pre>
* Tesler do not autowire this bean by name, so fill free to set any bean name you need.
* This transaction manager use EntityManagerFactory autowired by name = ${tesler.beans.entity-manager-factory} (default "entityManagerFactory")
*/
@Getter
@Setter
@EnableTransactionManagement
@Configuration
public class PersistenceJPAConfig {

@Autowired
private DefaultListableBeanFactory beanFactory;

@Bean("teslerEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("primaryDS") final DataSource primaryDS,
@Qualifier("jpaProperties") final Properties jpaProperties,
@Qualifier("vendorAdapter") final JpaVendorAdapter vendorAdapter) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(primaryDS);
em.setPackagesToScan(getPackagesToScan().toArray(new String[0]));
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(jpaProperties);
em.setPersistenceUnitName("tesler-persistence-unit");
return em;
}

protected List<String> getPackagesToScan() {
return Collections.singletonList("io.tesler");
}

@Bean("teslerTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("teslerEntityManagerFactory") final EntityManagerFactory emf,
final ITransactionStatus txStatus) {
return new JpaTransactionManagerCustom(emf, txStatus);
}

@Profile("!Debug")
@Bean("jpaProperties")
public Properties jpaProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.connection.charSet", "UTF-8");
properties.setProperty(PHYSICAL_NAMING_STRATEGY, ImprovedPhysicalNamingStrategy.class.getName());
properties.setProperty("hibernate.synonyms", String.valueOf(true));
properties.setProperty("hibernate.connection.includeSynonyms", String.valueOf(true));
//properties.setProperty(AvailableSettings.ENHANCER_ENABLE_DIRTY_TRACKING, String.valueOf(true));
properties.setProperty(FORMAT_SQL, String.valueOf(false));
properties.setProperty(GENERATE_STATISTICS, String.valueOf(false));
properties.setProperty(STATEMENT_BATCH_SIZE, String.valueOf(100));
properties.setProperty(DEFAULT_BATCH_FETCH_SIZE, String.valueOf(100));
properties.setProperty(BATCH_FETCH_STYLE, BatchFetchStyle.DYNAMIC.name());
properties.setProperty(CRITERIA_LITERAL_HANDLING_MODE, LiteralHandlingMode.BIND.name());
properties.setProperty(VALIDATE_QUERY_PARAMETERS, String.valueOf(false));
properties.put(BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
return properties;
}

@Profile("Debug")
@Bean("jpaProperties")
public Properties jpaDebugProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.connection.charSet", "UTF-8");
properties.setProperty(PHYSICAL_NAMING_STRATEGY, ImprovedPhysicalNamingStrategy.class.getName());
properties.setProperty("hibernate.synonyms", String.valueOf(true));
properties.setProperty("hibernate.connection.includeSynonyms", String.valueOf(true));
//properties.setProperty(AvailableSettings.ENHANCER_ENABLE_DIRTY_TRACKING, String.valueOf(true));
properties.setProperty(FORMAT_SQL, String.valueOf(true));
properties.setProperty(GENERATE_STATISTICS, String.valueOf(true));
properties.setProperty(STATEMENT_BATCH_SIZE, String.valueOf(100));
properties.setProperty(DEFAULT_BATCH_FETCH_SIZE, String.valueOf(100));
properties.setProperty(BATCH_FETCH_STYLE, BatchFetchStyle.DYNAMIC.name());
properties.setProperty(CRITERIA_LITERAL_HANDLING_MODE, LiteralHandlingMode.AUTO.name());
properties.setProperty(VALIDATE_QUERY_PARAMETERS, String.valueOf(false));
properties.put(BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
return properties;
}

@Bean
@TransactionScope
public CurrentUserAware<User> auditorAware(TransactionService txService, EffectiveUserAware<User> effectiveUserAware) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
@Table(name = "users") // users, а не user, т.к. это служебное слово oracle
@Getter
@Setter
public class User extends BaseEntity /*TODO>>IBORISENKO>>this should be moved to project level!!!>> implements IAccessorSupplier*/ {
public class User extends BaseEntity {

private String login;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.hibernate.event.spi.EventType.POST_INSERT;
import static org.hibernate.event.spi.EventType.POST_UPDATE;

import io.tesler.api.config.TeslerBeanProperties;
import io.tesler.model.core.listeners.hbn.change.ChangeInterceptor;
import io.tesler.model.core.listeners.hbn.flush.FlushInterceptor;
import javax.annotation.PostConstruct;
Expand All @@ -49,7 +50,7 @@
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.persister.entity.EntityPersister;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;


Expand All @@ -59,8 +60,10 @@ public class DatabaseListener implements
FlushEntityEventListener, FlushEventListener, AutoFlushEventListener {

@Autowired
@Qualifier("teslerEntityManagerFactory")
private EntityManagerFactory emf;
private ApplicationContext applicationContext;

@Autowired
private TeslerBeanProperties teslerBeanProperties;

@Autowired
private ChangeInterceptor changeInterceptor;
Expand Down Expand Up @@ -114,7 +117,10 @@ protected void init() {
}

private EventListenerRegistry getRegistry() {
SessionFactoryImplementor implementor = emf.unwrap(SessionFactoryImplementor.class);
SessionFactoryImplementor implementor = applicationContext.getBean(
teslerBeanProperties.getEntityManagerFactory(),
EntityManagerFactory.class
).unwrap(SessionFactoryImplementor.class);
return implementor.getServiceRegistry().getService(EventListenerRegistry.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@

package io.tesler.model.core.tx;

import io.tesler.api.config.TeslerBeanProperties;
import io.tesler.api.service.tx.ITransactionStatus;
import javax.persistence.EntityManagerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.TransactionDefinition;
Expand All @@ -30,11 +32,19 @@
import org.springframework.transaction.support.TransactionSynchronizationManager;


public class JpaTransactionManagerCustom extends JpaTransactionManager {
public class TeslerJpaTransactionManagerForceActiveAware extends JpaTransactionManager {

private final ITransactionStatus txStatus;

public JpaTransactionManagerCustom(EntityManagerFactory emf, ITransactionStatus txStatus) {
public TeslerJpaTransactionManagerForceActiveAware(ApplicationContext applicationContext, TeslerBeanProperties teslerBeanProperties, ITransactionStatus txStatus) {
super(applicationContext.getBean(
teslerBeanProperties.getEntityManagerFactory(),
EntityManagerFactory.class
));
this.txStatus = txStatus;
}

public TeslerJpaTransactionManagerForceActiveAware(EntityManagerFactory emf, ITransactionStatus txStatus) {
super(emf);
this.txStatus = txStatus;
}
Expand Down
Loading

0 comments on commit 7211713

Please sign in to comment.