net.relaysoft.commons.data.conf.DataServiceAutoConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of data-manager-spring-boot-starter Show documentation
Show all versions of data-manager-spring-boot-starter Show documentation
Spring Boot starter library for Relaysoft Data Manager
package net.relaysoft.commons.data.conf;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Properties;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import net.relaysoft.commons.data.manager.DataManager;
import net.relaysoft.commons.data.manager.FileDataManager;
import net.relaysoft.commons.data.manager.InMemoryDataManager;
import net.relaysoft.commons.data.services.DataCacheService;
import net.relaysoft.commons.data.services.DataSecurityService;
import net.relaysoft.commons.data.services.DataService;
import net.relaysoft.commons.data.services.DefaultDataService;
import net.relaysoft.commons.data.services.SimpleDataSecurityService;
import net.relaysoft.commons.data.services.SimpleInMemoryDataCacheService;
/**
* Data service auto configuration will initialize ready {@link DataService} bean based on configured properties. It resolves data manager
* for the service with following order. First it tries to locate data manager bean either based on configured component name or class.
* Second it just tries with possible default data manger bean which implements {@link DataManager} interface. Third it tries to create new
* data manager POJO instance based on configured class name. If none of above matches to any data manager available for the service then
* default in-memory data manager instance is created and bound to data service bean.
*
* To configure data service bean with data manager bean:
*
* relaysoft.data.manger.name = <data manager bean qualified name or class name>
*
* It is also possible to configure data manager related cache and security service when using POJO data manager. By default simple
* in-memory cache and security service instances are used. Also if bean data manager does not override cache or security services it uses
* default ones.
*
* To configure cache and security services with data manager instance:
*
* relaysoft.data.manger.cache.name = <cache service class name>
* relaysoft.data.manger.security.name = <security service class name>
*
* To override used data security and cache services with bean data manager:
*
* {@literal @}Component
* public class MyDataManager extends AbstractDataManager implements DataManager {
*
* {@literal @}Autowired
* private DataCacheService cacheService;
*
* {@literal @}Autowired
* private DataSecurityService securityService;
*
* ...
*
* {@literal @}Override
* protected DataCacheService getDataCacheService() {
* return cacheService;
* }
*
* {@literal @}Override
* protected DataSecurityService getDataSecurityService() {
* return securityService;
* }
*
* ...
* }
*
*
* @author relaysoft.net
*
*/
@Configuration
@ConditionalOnClass(DefaultDataService.class)
@EnableConfigurationProperties(DataManagerProperties.class)
public class DataServiceAutoConfiguration {
public static final String PROPERTY_DATA_MANAGER_NAME = DefaultDataService.PROPERTY_DATA_MANAGER_NAME;
public static final String PROPERTY_DATA_MANAGER_INSTANCE_ID = DefaultDataService.PROPERTY_DATA_MANAGER_INSTANCE_ID;
protected static final String FILE_DATA_MANAGER = DefaultDataService.FILE_DATA_MANAGER;
protected static final String IN_MEMORY_DATA_MANAGER = DefaultDataService.IN_MEMORY_DATA_MANAGER;
@Autowired
private ApplicationContext context;
@Autowired
private DataManagerProperties dataManagerProperties;
@Autowired
private Environment env;
private Logger logger = LoggerFactory.getLogger(DataServiceAutoConfiguration.class);
@Bean
@ConditionalOnMissingBean
public DataService dataService() {
DataManager dataManager = getBeanDataManager();
return new DefaultDataService(dataManager != null ? dataManager : getPojoDataManager(false));
}
/**
* Try to find bean data manager component for the data service.
*
* @return Data manager bean or null
.
*/
private DataManager getBeanDataManager() {
DataManager dataManager = null;
String name = dataManagerProperties.getName() != null ? dataManagerProperties.getName() :
System.getProperty(PROPERTY_DATA_MANAGER_NAME);
if(name != null){
dataManager = resolveDataManagerBeanFromName(name);
dataManager = dataManager != null ? dataManager : resolveDataManagerBeanFromClass(name);
}
dataManager = dataManager != null ? dataManager : resolveDataManagerDefaultBean();
return dataManager;
}
private Constructor> getConstructor(String className, Class>... parameterTypes)
throws NoSuchMethodException, ClassNotFoundException{
if(parameterTypes != null && parameterTypes.length > 0){
return Class.forName(className).getConstructor(parameterTypes);
} else {
return Class.forName(className).getConstructor();
}
}
/**
* Instantiate new data cache service POJO for the data manager based on configured properties.
*
* @return Data cache service instance.
*/
private DataCacheService getPojoDataCacheService(boolean useDefaultConstructor) {
DataCacheService service = null;
String className = resolveCacheServiceClass();
if(!useDefaultConstructor){
logger.info("Creating new data cache service instance for the data manager from implementation class {}.", className);
}
try {
if(useDefaultConstructor){
@SuppressWarnings("unchecked")
Constructor constructor = (Constructor) getConstructor(className);
service = constructor.newInstance();
} else {
@SuppressWarnings("unchecked")
Constructor constructor = (Constructor) getConstructor(className, Properties.class);
service = constructor.newInstance(getProperties());
}
} catch (NoSuchMethodException e) {
if(useDefaultConstructor){
logger.error("Failed to create new cache service instance from class {}. Reason: {}", className, e);
throw new IllegalArgumentException("Failed to create new cache service instance from class " + className + ".", e);
}
return getPojoDataCacheService(true);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to create new cache service instance from class " + className + ".", e);
}
return service;
}
/**
* Instantiate new data manager POJO for the data service based on configured properties.
*
* @return Data manager instance.
*/
private DataManager getPojoDataManager(boolean useDefaultConstructor) {
DataManager dataMamager = null;
String className = resolveDataManagerPojoFromClass();
if(!useDefaultConstructor){
logger.info("Creating new data manager instance for the data service from implementation class {}.", className);
}
try {
if(useDefaultConstructor) {
@SuppressWarnings("unchecked")
Constructor constructor = (Constructor) getConstructor(className, int.class,
DataCacheService.class, DataSecurityService.class);
dataMamager = constructor.newInstance(resolveInstanceId(), getPojoDataCacheService(false),
getPojoDataSecurityService(false));
} else {
@SuppressWarnings("unchecked")
Constructor constructor = (Constructor) getConstructor(className, int.class,
DataCacheService.class, DataSecurityService.class, Properties.class);
dataMamager = constructor.newInstance(resolveInstanceId(), getPojoDataCacheService(false),
getPojoDataSecurityService(false), getProperties());
}
} catch (NoSuchMethodException e) {
if(useDefaultConstructor){
logger.error("Failed to create new data manager instance from class {}. Reason: {}", className, e);
throw new IllegalArgumentException("Failed to create new data manager instance from class " + className + ".", e);
}
return getPojoDataManager(true);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to create new data manager instance from class " + className + ".", e);
}
return dataMamager;
}
/**
* Instantiate new data security service POJO for the data manager based on configured properties.
*
* @return Data security service.
*/
private DataSecurityService getPojoDataSecurityService(boolean useDefaultConstructor) {
DataSecurityService service = null;
String className = dataManagerProperties.getSecurity() != null && dataManagerProperties.getSecurity().getName() != null
? dataManagerProperties.getSecurity().getName() :
SimpleDataSecurityService.class.getName();
if(!useDefaultConstructor){
logger.info("Creating new data security service instance for the data manager from implementation class {}.", className);
}
try {
if(useDefaultConstructor){
@SuppressWarnings("unchecked")
Constructor constructor = (Constructor) getConstructor(className);
service = constructor.newInstance();
} else {
@SuppressWarnings("unchecked")
Constructor constructor = (Constructor) getConstructor(className, Properties.class);
service = constructor.newInstance(getProperties());
}
} catch (NoSuchMethodException e) {
if(useDefaultConstructor){
logger.error("Failed to create new security service instance from class {}. Reason: {}", className, e);
throw new IllegalArgumentException("Failed to create new security service instance from class " + className + ".", e);
}
return getPojoDataSecurityService(true);
}catch (Exception e) {
throw new IllegalArgumentException("Failed to create new security service instance from class " + className + ".", e);
}
return service;
}
/**
* Get all properties from Spring configuration into {@link Properties} instance.
*
* @return Properties object containing all Spring configuration properties.
*/
private Properties getProperties(){
Properties props = new Properties();
MutablePropertySources propertySources = ((AbstractEnvironment) env).getPropertySources();
StreamSupport.stream(propertySources.spliterator(), false)
.filter(ps -> ps instanceof EnumerablePropertySource)
.map(ps -> ((EnumerablePropertySource>) ps).getPropertyNames())
.flatMap(Arrays::stream)
.forEach(propName -> props.setProperty(propName, env.getProperty(propName)));
return props;
}
/**
* Resolves class name for the cache service from configuration properties.
*
* @return Cache service class name
*/
private String resolveCacheServiceClass(){
String className = dataManagerProperties.getCache() != null && dataManagerProperties.getCache().getName() != null
? dataManagerProperties.getCache().getName() :
System.getProperty(DefaultDataService.PROPERTY_DATA_MANAGER_CACHE_SERVICE_NAME);
return className != null ? className : SimpleInMemoryDataCacheService.class.getName();
}
/**
* Try to find data manager bean based on given class name.
*
* @param className - Bean class name
* @return Data manager bean component or null
.
*/
private DataManager resolveDataManagerBeanFromClass(String className){
try{
return (DataManager) context.getBean(Class.forName(className));
} catch (NoSuchBeanDefinitionException | ClassNotFoundException e) {
logger.info("Data manager bean with class name {} cannot be found.", className);
}
return null;
}
/**
* Try to find data manager bean based on given bean qualified name.
*
* @param name - Bean qualified name
* @return Data manager bean component or null
.
*/
private DataManager resolveDataManagerBeanFromName(String name){
try{
return (DataManager) context.getBean(name);
} catch (NoSuchBeanDefinitionException e) {
logger.info("Data manager bean with name {} is not found.", name);
}
return null;
}
/**
* Resolves POJO data manager class name from configuration properties. By default returns {@link InMemoryDataManager} class name.
*
* @return Data manager class name.
*/
private String resolveDataManagerPojoFromClass(){
String className = null;
String name = dataManagerProperties.getName() != null ? dataManagerProperties.getName() :
System.getProperty(PROPERTY_DATA_MANAGER_NAME);
if(FILE_DATA_MANAGER.equals(name)) {
className = FileDataManager.class.getName();
} else if(IN_MEMORY_DATA_MANAGER.equals(name)){
className = InMemoryDataManager.class.getName();
} else {
className = name;
}
return className != null ? className : InMemoryDataManager.class.getName();
}
/**
* Try to find data manager bean which implements {@link DataManager} interface.
*
* @return Data manager bean component or null
.
*/
private DataManager resolveDataManagerDefaultBean(){
try{
return context.getBean(DataManager.class);
} catch (NoSuchBeanDefinitionException e) {
logger.info("Data manager bean is not found.");
}
return null;
}
/**
* Resolves instance ID for the data manager from configuration properties.
*
* @return Configured instance ID value or 0.
*/
private int resolveInstanceId() {
int instanceId = 0;
try {
instanceId = dataManagerProperties.getInstanceId() != null ? Integer.parseInt(dataManagerProperties.getInstanceId()) : 0;
} catch (NumberFormatException e) {
logger.warn("Failed to parse instance ID value from property '{}'. Using default instance ID value 0.",
PROPERTY_DATA_MANAGER_INSTANCE_ID);
}
return instanceId;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy