All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.relaysoft.commons.data.conf.DataServiceAutoConfiguration Maven / Gradle / Ivy

There is a newer version: 3.0.0
Show newest version
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