mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 18:14:26 +00:00
[DS-2378] Pass 2: fold SpringServiceManager into DSpaceServiceManager and simplify.
This commit is contained in:
@@ -7,35 +7,41 @@
|
||||
*/
|
||||
package org.dspace.servicemanager;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.dspace.kernel.Activator;
|
||||
import org.dspace.kernel.config.SpringLoader;
|
||||
import org.dspace.kernel.mixins.ConfigChangeListener;
|
||||
import org.dspace.kernel.mixins.InitializedService;
|
||||
import org.dspace.kernel.mixins.ServiceChangeListener;
|
||||
import org.dspace.kernel.mixins.ServiceManagerReadyAware;
|
||||
import org.dspace.kernel.mixins.ShutdownService;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.servicemanager.spring.SpringServiceManager;
|
||||
import org.dspace.servicemanager.spring.DSpaceBeanFactoryPostProcessor;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* This is the core service manager which ties together the other
|
||||
* service managers and generally handles any edge cases in the various
|
||||
* systems.
|
||||
* A service locator based on Spring.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
@@ -43,11 +49,56 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(DSpaceServiceManager.class);
|
||||
|
||||
public static final String CONFIG_PATH = "spring/spring-dspace-applicationContext.xml";
|
||||
public static final String CORE_RESOURCE_PATH = "classpath*:spring/spring-dspace-core-services.xml";
|
||||
public static final String ADDON_RESOURCE_PATH = "classpath*:spring/spring-dspace-addon-*-services.xml";
|
||||
|
||||
private final DSpaceConfigurationService configurationService;
|
||||
|
||||
private ClassPathXmlApplicationContext applicationContext;
|
||||
|
||||
protected boolean running = false;
|
||||
|
||||
private ServiceManagerSystem serviceManagerSystem;
|
||||
protected boolean developing = false;
|
||||
|
||||
protected boolean testing = false;
|
||||
|
||||
protected String[] springXmlConfigFiles = null;
|
||||
|
||||
/**
|
||||
* This holds the stack of activators. It is randomly ordered.
|
||||
*/
|
||||
private final List<Activator> activators = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
/**
|
||||
* Standard constructor.
|
||||
*
|
||||
* @param configurationService current DSpace configuration service
|
||||
*/
|
||||
public DSpaceServiceManager(DSpaceConfigurationService configurationService) {
|
||||
if (configurationService == null) {
|
||||
throw new IllegalArgumentException("Failure creating service manager: configuration service is null");
|
||||
}
|
||||
this.configurationService = configurationService;
|
||||
this.developing = configurationService.getPropertyAsType("service.manager.developing", boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* TESTING - This is for testing only.
|
||||
*
|
||||
* @param configurationService current DSpace configuration service.
|
||||
* @param springXmlConfigFiles one or more Spring XML configuration files.
|
||||
*/
|
||||
protected DSpaceServiceManager(DSpaceConfigurationService configurationService,
|
||||
String... springXmlConfigFiles) {
|
||||
if (configurationService == null) {
|
||||
throw new IllegalArgumentException("Configuration service cannot be null");
|
||||
}
|
||||
this.configurationService = configurationService;
|
||||
this.springXmlConfigFiles = springXmlConfigFiles;
|
||||
this.testing = true;
|
||||
this.developing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the service manager is running
|
||||
@@ -57,7 +108,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the service manager is running, if not throws an exception
|
||||
* Checks to see if the service manager is running.
|
||||
*
|
||||
* @throws IllegalStateException if not running
|
||||
*/
|
||||
@@ -68,39 +119,21 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* This holds the stack of activators. It is randomly ordered.
|
||||
* @return the current spring bean factory OR null if there is not one.
|
||||
*/
|
||||
private final List<Activator> activators = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
protected boolean developing = false;
|
||||
|
||||
/**
|
||||
* Standard constructor.
|
||||
*
|
||||
* @param configurationService current DSpace configuration service
|
||||
*/
|
||||
public DSpaceServiceManager(DSpaceConfigurationService configurationService) {
|
||||
if (configurationService == null) {
|
||||
throw new IllegalArgumentException("Failure creating service manager, configuration service is null");
|
||||
public ListableBeanFactory getBeanFactory() {
|
||||
if (applicationContext != null) {
|
||||
return applicationContext.getBeanFactory();
|
||||
}
|
||||
this.configurationService = configurationService;
|
||||
this.developing = configurationService.getPropertyAsType("service.manager.developing", boolean.class);
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean testing = false;
|
||||
protected String[] springXmlConfigFiles = null;
|
||||
|
||||
/**
|
||||
* TESTING - This is for testing only.
|
||||
*
|
||||
* @param configurationService current DSpace configuration service
|
||||
* @param springXmlConfigFiles one or more Spring XML configs
|
||||
* @return the parent core Spring {@link ApplicationContext}
|
||||
*/
|
||||
protected DSpaceServiceManager(DSpaceConfigurationService configurationService, String... springXmlConfigFiles) {
|
||||
this.configurationService = configurationService;
|
||||
this.springXmlConfigFiles = springXmlConfigFiles;
|
||||
this.testing = true;
|
||||
this.developing = true;
|
||||
@Override
|
||||
public ClassPathXmlApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +156,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all registered activators using this service manager.
|
||||
* De-registers all registered activators using this service manager.
|
||||
*/
|
||||
private void unregisterActivators() {
|
||||
for (Activator activator : activators) {
|
||||
@@ -143,11 +176,11 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* This will call all the services which want to be notified when the service manager is ready
|
||||
* This will call all the services which want to be notified when the service manager is ready.
|
||||
*/
|
||||
public void notifyServiceManagerReady() {
|
||||
List<ServiceManagerReadyAware> services
|
||||
= serviceManagerSystem.getServicesByType(ServiceManagerReadyAware.class);
|
||||
= getServicesByType(ServiceManagerReadyAware.class);
|
||||
for (ServiceManagerReadyAware serviceManagerReadyAware : services) {
|
||||
try {
|
||||
serviceManagerReadyAware.serviceManagerReady(this);
|
||||
@@ -159,7 +192,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a listener should be notified
|
||||
* Checks to see if a listener should be notified.
|
||||
*
|
||||
* @param implementedTypes the types implemented by the service changing
|
||||
* @param serviceChangeListener the listener
|
||||
@@ -185,21 +218,30 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down all service managers, including this one.
|
||||
* Shut down the Spring context and leave the "running" state.
|
||||
*/
|
||||
@Override
|
||||
public void shutdown() {
|
||||
unregisterActivators();
|
||||
|
||||
if (applicationContext != null) {
|
||||
try {
|
||||
serviceManagerSystem.shutdown();
|
||||
applicationContext.close();
|
||||
} catch (Exception e) {
|
||||
// shutdown failures are not great but should NOT cause an interruption of processing
|
||||
log.error("Failure shutting down service manager ({}): {}",
|
||||
serviceManagerSystem, e.getMessage(), e);
|
||||
// keep going anyway
|
||||
log.warn("Exception closing ApplicationContext: {}", e.getMessage(), e);
|
||||
}
|
||||
try {
|
||||
applicationContext.destroy();
|
||||
} catch (Exception e) {
|
||||
// keep going anyway
|
||||
log.warn("Exception destroying ApplicationContext: {}", e.getMessage(), e);
|
||||
}
|
||||
applicationContext = null;
|
||||
}
|
||||
|
||||
this.running = false; // wait til the end
|
||||
this.serviceManagerSystem = null;
|
||||
log.info("Shutdown DSpace core service manager");
|
||||
log.info("DSpace service manager is shut down.");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -219,20 +261,30 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
// have to put this at the top because otherwise initializing beans will die when they try to use the SMS
|
||||
this.running = true;
|
||||
// create the SMS and start it
|
||||
SpringServiceManager springSMS = new SpringServiceManager(this, configurationService, testing, developing,
|
||||
springXmlConfigFiles);
|
||||
try {
|
||||
springSMS.startup();
|
||||
} catch (Exception e) {
|
||||
// startup failures are deadly
|
||||
throw new IllegalStateException("failure starting up spring service manager: " + e.getMessage(), e);
|
||||
|
||||
// get all Spring config paths
|
||||
String[] allPaths = getSpringPaths(testing, springXmlConfigFiles, configurationService);
|
||||
applicationContext = new ClassPathXmlApplicationContext(allPaths, false);
|
||||
// Make sure that the Spring files from the config directory can override the Spring files from our jars
|
||||
applicationContext.setAllowBeanDefinitionOverriding(true);
|
||||
applicationContext.setAllowCircularReferences(true);
|
||||
//applicationContext.registerShutdownHook(); // this interferes with the kernel shutdown hook
|
||||
// add the config interceptors (partially done in the xml)
|
||||
applicationContext.addBeanFactoryPostProcessor(
|
||||
new DSpaceBeanFactoryPostProcessor(this, configurationService, testing));
|
||||
applicationContext.refresh();
|
||||
if (developing) {
|
||||
log.warn("Service Manager is running in developmentMode. Services will be loaded on demand only");
|
||||
// TODO find a way to set this sucker to super duper lazy mode? it is currently not actually doing it
|
||||
} else {
|
||||
applicationContext.getBeanFactory().preInstantiateSingletons();
|
||||
applicationContext.getBeanFactory().freezeConfiguration();
|
||||
}
|
||||
// add it to the list of service managers
|
||||
this.serviceManagerSystem = springSMS;
|
||||
|
||||
// now startup the activators
|
||||
registerActivators();
|
||||
@@ -246,36 +298,66 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
log.error(message, e);
|
||||
throw new RuntimeException(message, e);
|
||||
}
|
||||
|
||||
long totalTime = System.currentTimeMillis() - startTime;
|
||||
log.info("Service Manager started up in {} ms with {} services...",
|
||||
totalTime, applicationContext.getBeanDefinitionCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerService(String name, Object service) {
|
||||
checkRunning();
|
||||
if (name == null || service == null) {
|
||||
throw new IllegalArgumentException("name and service cannot be null");
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name cannot be null");
|
||||
}
|
||||
if (service == null) {
|
||||
throw new IllegalArgumentException("service cannot be null");
|
||||
}
|
||||
// register service/provider
|
||||
serviceManagerSystem.registerService(name, service);
|
||||
try {
|
||||
applicationContext.getBeanFactory().autowireBean(service);
|
||||
} catch (BeansException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e);
|
||||
}
|
||||
registerBean(name, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerServiceNoAutowire(String name, Object service) {
|
||||
checkRunning();
|
||||
if (name == null || service == null) {
|
||||
throw new IllegalArgumentException("name and service cannot be null");
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name cannot be null");
|
||||
}
|
||||
if (service == null) {
|
||||
throw new IllegalArgumentException("service cannot be null");
|
||||
}
|
||||
// register service/provider
|
||||
serviceManagerSystem.registerServiceNoAutowire(name, service);
|
||||
registerBean(name, service);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T registerServiceClass(String name, Class<T> type) {
|
||||
checkRunning();
|
||||
if (name == null || type == null) {
|
||||
throw new IllegalArgumentException("name and type cannot be null");
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name cannot be null");
|
||||
}
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("type cannot be null");
|
||||
}
|
||||
|
||||
return serviceManagerSystem.registerServiceClass(name, type);
|
||||
T service;
|
||||
try {
|
||||
service = (T) applicationContext.getBeanFactory()
|
||||
.autowire(type, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
registerBean(name, service);
|
||||
} catch (BeansException e) {
|
||||
throw new IllegalArgumentException("Invalid service class (" + type
|
||||
+ ") with name (" + name
|
||||
+ ") registration: " + e.getMessage(), e);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -285,43 +367,113 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
throw new IllegalArgumentException("name cannot be null");
|
||||
}
|
||||
|
||||
serviceManagerSystem.unregisterService(name);
|
||||
if (applicationContext.containsBean(name)) {
|
||||
try {
|
||||
Object beanInstance = applicationContext.getBean(name);
|
||||
try {
|
||||
applicationContext.getBeanFactory().destroyBean(name, beanInstance);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
// this happens if the bean was registered manually (annoyingly)
|
||||
DSpaceServiceManager.shutdownService(beanInstance);
|
||||
}
|
||||
} catch (BeansException e) {
|
||||
// nothing to do here, could not find the bean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles the common part of various types of service registrations.
|
||||
*
|
||||
* @param name name of bean
|
||||
* @param service service object
|
||||
*/
|
||||
private void registerBean(String name, Object service) {
|
||||
try {
|
||||
applicationContext.getBeanFactory().initializeBean(service, name);
|
||||
applicationContext.getBeanFactory().registerSingleton(name, service);
|
||||
} catch (BeansException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getServiceByName(String name, Class<T> type) {
|
||||
checkRunning();
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("type cannot be null");
|
||||
throw new IllegalArgumentException("Type cannot be null");
|
||||
}
|
||||
|
||||
T service = null;
|
||||
// handle special case to return the core AC
|
||||
if (ApplicationContext.class.getName().equals(name)
|
||||
&& ApplicationContext.class.isAssignableFrom(type)) {
|
||||
service = (T) getApplicationContext();
|
||||
} else {
|
||||
if (name != null) {
|
||||
// get by name and type
|
||||
try {
|
||||
service = serviceManagerSystem.getServiceByName(name, type);
|
||||
} catch (Exception e) {
|
||||
// keep going
|
||||
service = (T) applicationContext.getBean(name, type);
|
||||
} catch (BeansException e) {
|
||||
// no luck, try the fall back option
|
||||
log.info(
|
||||
"Unable to locate bean by name or id={}."
|
||||
+ " Will try to look up bean by type next."
|
||||
+ " BeansException: {}", name, e.getMessage());
|
||||
service = null;
|
||||
}
|
||||
} else {
|
||||
// try making up the name based on the type
|
||||
try {
|
||||
service = (T) applicationContext.getBean(type.getName(), type);
|
||||
} catch (BeansException e) {
|
||||
// no luck, try the fall back option
|
||||
log.info("Unable to locate bean by name or id={}."
|
||||
+ " Will try to look up bean by type next."
|
||||
+ " BeansException: {}", type.getName(), e.getMessage());
|
||||
service = null;
|
||||
}
|
||||
}
|
||||
// if still no luck then try by type only
|
||||
if (name == null
|
||||
&& service == null) {
|
||||
try {
|
||||
Map<String, T> map = applicationContext.getBeansOfType(type);
|
||||
if (map.size() == 1) {
|
||||
// only return the bean if there is exactly one
|
||||
service = (T) map.values().iterator().next();
|
||||
} else {
|
||||
log.error("Multiple beans of type {} found. Only one was expected!", type.getName());
|
||||
}
|
||||
} catch (BeansException e) {
|
||||
// I guess there are no beans of this type
|
||||
log.error(e.getMessage(), e);
|
||||
service = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableApplicationContext getApplicationContext() {
|
||||
return serviceManagerSystem.getApplicationContext();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> List<T> getServicesByType(Class<T> type) {
|
||||
checkRunning();
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("type cannot be null");
|
||||
}
|
||||
HashSet<T> set = new HashSet<>();
|
||||
|
||||
List<T> services = new ArrayList<>();
|
||||
Map<String, T> beans;
|
||||
try {
|
||||
set.addAll(serviceManagerSystem.getServicesByType(type));
|
||||
} catch (Exception e) {
|
||||
// keep going
|
||||
beans = applicationContext.getBeansOfType(type, true, true);
|
||||
services.addAll((Collection<? extends T>) beans.values());
|
||||
} catch (BeansException e) {
|
||||
throw new RuntimeException("Failed to get beans of type (" + type + "): " + e.getMessage(), e);
|
||||
}
|
||||
// put the set into a list for easier access and sort it
|
||||
List<T> services = new ArrayList<>(set);
|
||||
|
||||
Collections.sort(services, new ServiceManagerUtils.ServiceComparator());
|
||||
return services;
|
||||
}
|
||||
@@ -329,14 +481,16 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
@Override
|
||||
public List<String> getServicesNames() {
|
||||
checkRunning();
|
||||
List<String> names = new ArrayList<>();
|
||||
try {
|
||||
names.addAll(serviceManagerSystem.getServicesNames());
|
||||
} catch (Exception e) {
|
||||
// keep going
|
||||
ArrayList<String> beanNames = new ArrayList<>();
|
||||
String[] singletons = applicationContext.getBeanFactory().getSingletonNames();
|
||||
for (String singleton : singletons) {
|
||||
if (singleton.startsWith("org.springframework.context")) {
|
||||
continue; // skip the Spring standard ones
|
||||
}
|
||||
Collections.sort(names);
|
||||
return names;
|
||||
beanNames.add(singleton);
|
||||
}
|
||||
Collections.sort(beanNames);
|
||||
return beanNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -345,29 +499,24 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name cannot be null");
|
||||
}
|
||||
boolean exists = false;
|
||||
try {
|
||||
exists = serviceManagerSystem.isServiceExists(name);
|
||||
} catch (Exception e) {
|
||||
// keep going
|
||||
}
|
||||
return exists;
|
||||
return applicationContext.containsBean(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getServices() {
|
||||
checkRunning();
|
||||
Map<String, Object> services = new HashMap<>();
|
||||
try {
|
||||
for (Entry<String, Object> entry : serviceManagerSystem.getServices().entrySet()) {
|
||||
if (!services.containsKey(entry.getKey())) {
|
||||
services.put(entry.getKey(), entry.getValue());
|
||||
String[] singletons = applicationContext.getBeanFactory().getSingletonNames();
|
||||
for (String singleton : singletons) {
|
||||
if (singleton.startsWith("org.springframework.context")) {
|
||||
continue; // skip the spring standard ones
|
||||
}
|
||||
String beanName = singleton;
|
||||
Object service = applicationContext.getBeanFactory().getSingleton(beanName);
|
||||
if (service == null) {
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(
|
||||
"Failed to get list of services from service manager ({}): {}",
|
||||
serviceManagerSystem.getClass(), e.getMessage(), e);
|
||||
services.put(beanName, service);
|
||||
}
|
||||
return services;
|
||||
}
|
||||
@@ -393,8 +542,8 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
changedSettings.put(configName, configurationService.getProperty(configName));
|
||||
}
|
||||
// notify the services that implement the mixin
|
||||
List<ConfigChangeListener> configChangeListeners = serviceManagerSystem
|
||||
.getServicesByType(ConfigChangeListener.class);
|
||||
List<ConfigChangeListener> configChangeListeners
|
||||
= getServicesByType(ConfigChangeListener.class);
|
||||
for (ConfigChangeListener configChangeListener : configChangeListeners) {
|
||||
// notify this service
|
||||
try {
|
||||
@@ -497,9 +646,61 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
try {
|
||||
((ShutdownService) service).shutdown();
|
||||
} catch (Exception e) {
|
||||
log.error("Failure shutting down service: " + service, e);
|
||||
log.error("Failure shutting down service: {}", service, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the complete list of Spring configuration paths, including
|
||||
* hard-wired paths.
|
||||
*
|
||||
* @param testMode are we testing the service manager?
|
||||
* @param configPaths paths supplied at startup.
|
||||
* @param configurationService DSpace configuration source.
|
||||
* @return
|
||||
*/
|
||||
public static String[] getSpringPaths(boolean testMode, String[] configPaths,
|
||||
DSpaceConfigurationService configurationService) {
|
||||
List<String> pathList = new LinkedList<>();
|
||||
pathList.add(CONFIG_PATH);
|
||||
pathList.add(ADDON_RESOURCE_PATH);
|
||||
if (testMode) {
|
||||
log.warn("TEST Service Manager running in test mode: no core beans will be started");
|
||||
} else {
|
||||
// only load the core beans when not testing the service manager
|
||||
pathList.add(CORE_RESOURCE_PATH);
|
||||
}
|
||||
if (configPaths != null) {
|
||||
pathList.addAll(Arrays.asList(configPaths));
|
||||
}
|
||||
if (testMode) {
|
||||
log.warn("TEST Spring Service Manager running in test mode, no DSpace home Spring files will be loaded");
|
||||
} else {
|
||||
//Retrieve all our spring file locations depending on the deployed module
|
||||
String[] springLoaderClassNames = configurationService.getArrayProperty("spring.springloader.modules");
|
||||
if (springLoaderClassNames != null) {
|
||||
for (String springLoaderClassName : springLoaderClassNames) {
|
||||
try {
|
||||
Class<SpringLoader> springLoaderClass = (Class<SpringLoader>) Class
|
||||
.forName(springLoaderClassName.trim());
|
||||
String[] resourcePaths = springLoaderClass.getConstructor().newInstance()
|
||||
.getResourcePaths(configurationService);
|
||||
if (resourcePaths != null) {
|
||||
pathList.addAll(Arrays.asList(resourcePaths));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
//Ignore this exception, if we get one this just means that this module isn't loaded
|
||||
} catch (IllegalAccessException | IllegalArgumentException
|
||||
| InstantiationException | NoSuchMethodException
|
||||
| SecurityException | InvocationTargetException e) {
|
||||
log.error("Error while retrieving Spring resource paths for module: {}",
|
||||
springLoaderClassName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList.toArray(new String[pathList.size()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,8 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Register, configure, manipulate services.
|
||||
* Register, configure, manipulate, locate services.
|
||||
* See {@link DSpaceServiceManager} for a starting point.
|
||||
*/
|
||||
|
||||
package org.dspace.servicemanager;
|
||||
|
@@ -10,8 +10,6 @@ package org.dspace.servicemanager.spring;
|
||||
import org.dspace.servicemanager.ServiceManagerSystem;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
@@ -25,19 +23,17 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
*/
|
||||
public final class DSpaceBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(DSpaceBeanFactoryPostProcessor.class);
|
||||
|
||||
private ServiceManagerSystem serviceManager;
|
||||
private DSpaceConfigurationService configurationService;
|
||||
private ServiceManagerSystem parent;
|
||||
private boolean testMode = false;
|
||||
|
||||
public DSpaceBeanFactoryPostProcessor(ServiceManagerSystem parent,
|
||||
public DSpaceBeanFactoryPostProcessor(ServiceManagerSystem serviceManager,
|
||||
DSpaceConfigurationService configurationService, boolean testMode) {
|
||||
if (parent == null || configurationService == null) {
|
||||
throw new IllegalArgumentException("parent and configuration service cannot be null");
|
||||
if (configurationService == null) {
|
||||
throw new IllegalArgumentException("Configuration service cannot be null");
|
||||
}
|
||||
this.serviceManager = serviceManager;
|
||||
this.configurationService = configurationService;
|
||||
this.parent = parent;
|
||||
this.testMode = testMode;
|
||||
}
|
||||
|
||||
@@ -45,11 +41,11 @@ public final class DSpaceBeanFactoryPostProcessor implements BeanFactoryPostProc
|
||||
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org
|
||||
* .springframework.beans.factory.config.ConfigurableListableBeanFactory)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
// force config service to be registered first
|
||||
beanFactory.registerSingleton(ConfigurationService.class.getName(), configurationService);
|
||||
beanFactory.registerSingleton(ServiceManagerSystem.class.getName(), parent);
|
||||
beanFactory.registerSingleton(ServiceManagerSystem.class.getName(), serviceManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,369 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.servicemanager.spring;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dspace.kernel.config.SpringLoader;
|
||||
import org.dspace.servicemanager.DSpaceServiceManager;
|
||||
import org.dspace.servicemanager.ServiceManagerSystem;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* This is the Spring implementation of the service manager.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public final class SpringServiceManager implements ServiceManagerSystem {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SpringServiceManager.class);
|
||||
|
||||
private ClassPathXmlApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* @return the parent core Spring {@link ApplicationContext}
|
||||
*/
|
||||
@Override
|
||||
public ClassPathXmlApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current spring bean factory OR null if there is not one
|
||||
*/
|
||||
public ListableBeanFactory getBeanFactory() {
|
||||
if (applicationContext != null) {
|
||||
return applicationContext.getBeanFactory();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final ServiceManagerSystem parent;
|
||||
private final DSpaceConfigurationService configurationService;
|
||||
private boolean testMode = false;
|
||||
private boolean developmentMode = false;
|
||||
private String[] configPaths = null;
|
||||
|
||||
/**
|
||||
* For TESTING:
|
||||
* Allows adding extra spring config paths.
|
||||
*
|
||||
* @param parent parent ServiceManagerSystem
|
||||
* @param configurationService current DSpace configuration service
|
||||
* @param testMode if true then do not load the core beans
|
||||
* @param developmentMode if true then services loaded on demand only
|
||||
* @param configPaths additional spring config paths within this classloader
|
||||
*/
|
||||
public SpringServiceManager(ServiceManagerSystem parent, DSpaceConfigurationService configurationService,
|
||||
boolean testMode, boolean developmentMode, String... configPaths) {
|
||||
if (parent == null) {
|
||||
throw new IllegalArgumentException("parent SMS cannot be null");
|
||||
}
|
||||
this.parent = parent;
|
||||
if (configurationService == null) {
|
||||
throw new IllegalArgumentException("configuration service cannot be null");
|
||||
}
|
||||
this.configurationService = configurationService;
|
||||
this.testMode = testMode;
|
||||
this.developmentMode = developmentMode;
|
||||
this.configPaths = configPaths;
|
||||
}
|
||||
|
||||
public static final String configPath = "spring/spring-dspace-applicationContext.xml";
|
||||
public static final String coreResourcePath = "classpath*:spring/spring-dspace-core-services.xml";
|
||||
public static final String addonResourcePath = "classpath*:spring/spring-dspace-addon-*-services.xml";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getServiceByName(String name, Class<T> type) {
|
||||
T bean = null;
|
||||
// handle special case to return the core AC
|
||||
if (ApplicationContext.class.getName().equals(name)
|
||||
&& ApplicationContext.class.isAssignableFrom(type)) {
|
||||
bean = (T) getApplicationContext();
|
||||
} else {
|
||||
if (name != null) {
|
||||
// get by name and type
|
||||
try {
|
||||
bean = (T) applicationContext.getBean(name, type);
|
||||
} catch (BeansException e) {
|
||||
// no luck, try the fall back option
|
||||
log.info(
|
||||
"Unable to locate bean by name or id=" + name + ". Will try to look up bean by type next. " +
|
||||
"BeansException: " + e
|
||||
.getMessage());
|
||||
bean = null;
|
||||
}
|
||||
} else {
|
||||
// try making up the name based on the type
|
||||
try {
|
||||
bean = (T) applicationContext.getBean(type.getName(), type);
|
||||
} catch (BeansException e) {
|
||||
// no luck, try the fall back option
|
||||
log.info("Unable to locate bean by name or id=" + type
|
||||
.getName() + ". Will try to look up bean by type next. BeansException: " + e.getMessage());
|
||||
bean = null;
|
||||
}
|
||||
}
|
||||
// if still no luck then try by type only
|
||||
if (name == null
|
||||
&& bean == null) {
|
||||
try {
|
||||
Map<String, T> map = applicationContext.getBeansOfType(type);
|
||||
if (map.size() == 1) {
|
||||
// only return the bean if there is exactly one
|
||||
bean = (T) map.values().iterator().next();
|
||||
} else {
|
||||
log.error("Multiple beans of type " + type.getName() + " found. Only one was expected!");
|
||||
}
|
||||
} catch (BeansException e) {
|
||||
// I guess there are no beans of this type
|
||||
log.error(e.getMessage(), e);
|
||||
bean = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> List<T> getServicesByType(Class<T> type) {
|
||||
ArrayList<T> l = new ArrayList<>();
|
||||
Map<String, T> beans;
|
||||
try {
|
||||
beans = applicationContext.getBeansOfType(type, true, true);
|
||||
l.addAll((Collection<? extends T>) beans.values());
|
||||
} catch (BeansException e) {
|
||||
throw new RuntimeException("Failed to get beans of type (" + type + "): " + e.getMessage(), e);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
if (applicationContext != null) {
|
||||
try {
|
||||
applicationContext.close();
|
||||
} catch (Exception e) {
|
||||
// keep going anyway
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
applicationContext.destroy();
|
||||
} catch (Exception e) {
|
||||
// keep going anyway
|
||||
e.printStackTrace();
|
||||
}
|
||||
applicationContext = null;
|
||||
log.info("Spring Service Manager Shutdown...");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startup() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// get all spring config paths
|
||||
String[] allPaths = getSpringPaths(testMode, configPaths, configurationService);
|
||||
applicationContext = new ClassPathXmlApplicationContext(allPaths, false);
|
||||
// Make sure that the spring files from the config directoy can override the spring files from our jars
|
||||
applicationContext.setAllowBeanDefinitionOverriding(true);
|
||||
applicationContext.setAllowCircularReferences(true);
|
||||
//applicationContext.registerShutdownHook(); // this interferes with the kernel shutdown hook
|
||||
// add the config interceptors (partially done in the xml)
|
||||
applicationContext
|
||||
.addBeanFactoryPostProcessor(new DSpaceBeanFactoryPostProcessor(parent, configurationService, testMode));
|
||||
applicationContext.refresh();
|
||||
if (developmentMode) {
|
||||
log.warn("Spring Service Manager is running in developmentMode, services will be loaded on demand only");
|
||||
// TODO find a way to set this sucker to super duper lazy mode? it is currently not actually doing it
|
||||
} else {
|
||||
applicationContext.getBeanFactory().preInstantiateSingletons();
|
||||
applicationContext.getBeanFactory().freezeConfiguration();
|
||||
}
|
||||
long totalTime = System.currentTimeMillis() - startTime;
|
||||
log.info("Spring Service Manager started up in " + totalTime + " ms with " + applicationContext
|
||||
.getBeanDefinitionCount() + " services...");
|
||||
}
|
||||
|
||||
public static String[] getSpringPaths(boolean testMode, String[] configPaths,
|
||||
DSpaceConfigurationService configurationService) {
|
||||
List<String> pathList = new LinkedList<>();
|
||||
pathList.add(configPath);
|
||||
pathList.add(addonResourcePath);
|
||||
if (testMode) {
|
||||
log.warn("TEST Spring Service Manager running in test mode, no core beans will be started");
|
||||
} else {
|
||||
// only load the core beans when not testing the service manager
|
||||
pathList.add(coreResourcePath);
|
||||
}
|
||||
if (configPaths != null) {
|
||||
pathList.addAll(Arrays.asList(configPaths));
|
||||
}
|
||||
if (testMode) {
|
||||
log.warn("TEST Spring Service Manager running in test mode, no dspace home spring files will be loaded");
|
||||
} else {
|
||||
//Retrieve all our spring file locations depending on the deployed module
|
||||
String[] springLoaderClassNames = configurationService.getArrayProperty("spring.springloader.modules");
|
||||
if (springLoaderClassNames != null) {
|
||||
for (String springLoaderClassName : springLoaderClassNames) {
|
||||
try {
|
||||
Class<SpringLoader> springLoaderClass = (Class<SpringLoader>) Class
|
||||
.forName(springLoaderClassName.trim());
|
||||
String[] resourcePaths = springLoaderClass.getConstructor().newInstance()
|
||||
.getResourcePaths(configurationService);
|
||||
if (resourcePaths != null) {
|
||||
pathList.addAll(Arrays.asList(resourcePaths));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
//Ignore this exception, if we get one this just means that this module isn't loaded
|
||||
} catch (IllegalAccessException | IllegalArgumentException
|
||||
| InstantiationException | NoSuchMethodException
|
||||
| SecurityException | InvocationTargetException e) {
|
||||
log.error("Error while retrieving spring resource paths for module: {}",
|
||||
springLoaderClassName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pathList.toArray(new String[pathList.size()]);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T registerServiceClass(String name, Class<T> type) {
|
||||
if (name == null || type == null) {
|
||||
throw new IllegalArgumentException("name and type must not be null for service registration");
|
||||
}
|
||||
T service;
|
||||
try {
|
||||
service = (T) applicationContext.getBeanFactory()
|
||||
.autowire(type, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
|
||||
registerBean(name, service);
|
||||
} catch (BeansException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid service class (" + type + ") with name (" + name + ") registration: " + e.getMessage(), e);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerService(String name, Object service) {
|
||||
if (name == null || service == null) {
|
||||
throw new IllegalArgumentException("name and service must not be null for service registration");
|
||||
}
|
||||
try {
|
||||
applicationContext.getBeanFactory().autowireBean(service);
|
||||
} catch (BeansException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e);
|
||||
}
|
||||
registerBean(name, service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerServiceNoAutowire(String name, Object service) {
|
||||
if (name == null || service == null) {
|
||||
throw new IllegalArgumentException("name and service must not be null for service registration");
|
||||
}
|
||||
registerBean(name, service);
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles the common part of the 2 types of service
|
||||
* registrations.
|
||||
*
|
||||
* @param name name of bean
|
||||
* @param service service object
|
||||
*/
|
||||
private void registerBean(String name, Object service) {
|
||||
try {
|
||||
applicationContext.getBeanFactory().initializeBean(service, name);
|
||||
applicationContext.getBeanFactory().registerSingleton(name, service);
|
||||
} catch (BeansException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid service (" + service + ") with name (" + name + ") registration: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterService(String name) {
|
||||
if (applicationContext.containsBean(name)) {
|
||||
try {
|
||||
Object beanInstance = applicationContext.getBean(name);
|
||||
try {
|
||||
applicationContext.getBeanFactory().destroyBean(name, beanInstance);
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
// this happens if the bean was registered manually (annoyingly)
|
||||
DSpaceServiceManager.shutdownService(beanInstance);
|
||||
}
|
||||
} catch (BeansException e) {
|
||||
// nothing to do here, could not find the bean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getServicesNames() {
|
||||
ArrayList<String> beanNames = new ArrayList<>();
|
||||
String[] singletons = applicationContext.getBeanFactory().getSingletonNames();
|
||||
for (String singleton : singletons) {
|
||||
if (singleton.startsWith("org.springframework.context")) {
|
||||
continue; // skip the spring standard ones
|
||||
}
|
||||
beanNames.add(singleton);
|
||||
}
|
||||
Collections.sort(beanNames);
|
||||
return beanNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServiceExists(String name) {
|
||||
return applicationContext.containsBean(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getServices() {
|
||||
Map<String, Object> services = new HashMap<>();
|
||||
String[] singletons = applicationContext.getBeanFactory().getSingletonNames();
|
||||
for (String singleton : singletons) {
|
||||
if (singleton.startsWith("org.springframework.context")) {
|
||||
continue; // skip the spring standard ones
|
||||
}
|
||||
String beanName = singleton;
|
||||
Object service = applicationContext.getBeanFactory().getSingleton(beanName);
|
||||
if (service == null) {
|
||||
continue;
|
||||
}
|
||||
services.put(beanName, service);
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushConfig(Map<String, Object> settings) {
|
||||
throw new UnsupportedOperationException("Not implemented for individual service manager systems");
|
||||
}
|
||||
|
||||
}
|
@@ -9,7 +9,7 @@
|
||||
/**
|
||||
* Spring extensions and adaptors for DSpace.
|
||||
*
|
||||
* @see org.dspace.utils.DSpace for starting the kernel.
|
||||
* See {@link org.dspace.utils.DSpace} for starting the kernel.
|
||||
*/
|
||||
|
||||
package org.dspace.servicemanager.spring;
|
||||
|
@@ -23,7 +23,6 @@ import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.servicemanager.example.ConcreteExample;
|
||||
import org.dspace.servicemanager.fakeservices.FakeService1;
|
||||
import org.dspace.servicemanager.spring.SpringAnnotationBean;
|
||||
import org.dspace.servicemanager.spring.TestSpringServiceManager;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -34,6 +33,7 @@ import org.junit.Test;
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public class DSpaceServiceManagerTest {
|
||||
public static String SPRING_TEST_CONFIG_FILE = "spring/spring-test-services.xml";
|
||||
|
||||
DSpaceServiceManager dsm;
|
||||
DSpaceConfigurationService configurationService;
|
||||
@@ -46,7 +46,7 @@ public class DSpaceServiceManagerTest {
|
||||
configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz");
|
||||
configurationService.loadConfig("fakeBean.fakeParam", "beckyz");
|
||||
|
||||
dsm = new DSpaceServiceManager(configurationService, TestSpringServiceManager.SPRING_TEST_CONFIG_FILE);
|
||||
dsm = new DSpaceServiceManager(configurationService, SPRING_TEST_CONFIG_FILE);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -256,7 +256,7 @@ public class DSpaceServiceManagerTest {
|
||||
public void testPushConfig() {
|
||||
dsm.startup();
|
||||
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("some.test.thing", "A value");
|
||||
dsm.pushConfig(properties);
|
||||
|
||||
@@ -298,7 +298,7 @@ public class DSpaceServiceManagerTest {
|
||||
assertEquals(1, service.getTriggers());
|
||||
|
||||
// now we do a config change
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("azeckoski.FakeService1.something", "THING");
|
||||
dsm.pushConfig(properties);
|
||||
assertEquals("config:THING", service.getSomething());
|
||||
@@ -317,10 +317,12 @@ public class DSpaceServiceManagerTest {
|
||||
|
||||
public int value = 0;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
value++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
value++;
|
||||
}
|
||||
|
@@ -1,229 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.servicemanager.spring;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.servicemanager.MockServiceManagerSystem;
|
||||
import org.dspace.servicemanager.SampleAnnotationBean;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.servicemanager.example.ConcreteExample;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Testing the spring based service manager
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public class TestSpringServiceManager {
|
||||
|
||||
public static String SPRING_TEST_CONFIG_FILE = "spring/spring-test-services.xml";
|
||||
|
||||
SpringServiceManager ssm;
|
||||
DSpaceConfigurationService configurationService;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
configurationService = new DSpaceConfigurationService();
|
||||
configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz");
|
||||
configurationService.loadConfig("fakeBean.fakeParam", "beckyz");
|
||||
|
||||
ssm = new SpringServiceManager(new MockServiceManagerSystem(ssm), configurationService, true, true,
|
||||
SPRING_TEST_CONFIG_FILE);
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown() {
|
||||
if (ssm != null) {
|
||||
ssm.shutdown();
|
||||
}
|
||||
ssm = null;
|
||||
configurationService = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.dspace.servicemanager.spring.SpringServiceManager#startup()}.
|
||||
*/
|
||||
@Test
|
||||
public void testStartup() {
|
||||
// testing we can start this up with null config
|
||||
configurationService.clear();
|
||||
ssm.startup();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartupWithConfig() {
|
||||
// testing we can start this up a real config
|
||||
ssm.startup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.dspace.servicemanager.spring.SpringServiceManager#shutdown()}.
|
||||
*/
|
||||
@Test
|
||||
public void testShutdown() {
|
||||
ssm.startup();
|
||||
ssm.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.dspace.servicemanager.spring.SpringServiceManager#getServiceByName(java.lang.String, java.lang.Class)}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetServiceByName() {
|
||||
configurationService.clear(); // no config
|
||||
ssm.startup();
|
||||
|
||||
ConcreteExample concrete = ssm.getServiceByName(ConcreteExample.class.getName(), ConcreteExample.class);
|
||||
assertNotNull(concrete);
|
||||
assertEquals("azeckoski", concrete.getName());
|
||||
concrete = null;
|
||||
|
||||
SampleAnnotationBean sab = ssm
|
||||
.getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class);
|
||||
assertNotNull(sab);
|
||||
assertEquals(null, sab.getSampleValue());
|
||||
sab = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetServiceByNameConfig() {
|
||||
ssm.startup();
|
||||
|
||||
ConcreteExample concrete = ssm.getServiceByName(ConcreteExample.class.getName(), ConcreteExample.class);
|
||||
assertNotNull(concrete);
|
||||
assertEquals("azeckoski", concrete.getName());
|
||||
concrete = null;
|
||||
|
||||
SampleAnnotationBean sab = ssm
|
||||
.getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class);
|
||||
assertNotNull(sab);
|
||||
assertEquals("beckyz", sab.getSampleValue());
|
||||
sab = null;
|
||||
|
||||
SpringAnnotationBean spr = ssm
|
||||
.getServiceByName(SpringAnnotationBean.class.getName(), SpringAnnotationBean.class);
|
||||
assertNotNull(spr);
|
||||
assertEquals("azeckoski", spr.getConcreteName());
|
||||
assertEquals("aaronz", spr.getExampleName());
|
||||
assertEquals(null, spr.getSampleValue());
|
||||
spr = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.dspace.servicemanager.spring.SpringServiceManager#getServicesByType(java.lang.Class)}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetServicesByType() {
|
||||
ssm.startup();
|
||||
|
||||
List<ConcreteExample> l = ssm.getServicesByType(ConcreteExample.class);
|
||||
assertNotNull(l);
|
||||
assertEquals(1, l.size());
|
||||
assertEquals("azeckoski", l.get(0).getName());
|
||||
l = null;
|
||||
|
||||
List<SampleAnnotationBean> l2 = ssm.getServicesByType(SampleAnnotationBean.class);
|
||||
assertNotNull(l2);
|
||||
assertEquals(1, l2.size());
|
||||
l2 = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.dspace.servicemanager.spring.SpringServiceManager#registerServiceClass(java.lang.String, java.lang.Class)}.
|
||||
*/
|
||||
@Test
|
||||
public void testRegisterServiceClass() {
|
||||
ssm.startup();
|
||||
|
||||
SampleAnnotationBean sab = ssm.registerServiceClass("newAnnote", SampleAnnotationBean.class);
|
||||
assertNotNull(sab);
|
||||
sab = null;
|
||||
|
||||
List<SampleAnnotationBean> l = ssm.getServicesByType(SampleAnnotationBean.class);
|
||||
assertNotNull(l);
|
||||
assertEquals(2, l.size());
|
||||
l = null;
|
||||
|
||||
try {
|
||||
ssm.registerService("fakey", (Class<?>) null);
|
||||
fail("should have thrown exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertNotNull(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.dspace.servicemanager.spring.SpringServiceManager#registerService(java.lang.String, java.lang.Object)}.
|
||||
*/
|
||||
@Test
|
||||
public void testRegisterService() {
|
||||
ssm.startup();
|
||||
|
||||
String name = "myNewService";
|
||||
ssm.registerService(name, "AZ");
|
||||
String service = ssm.getServiceByName(name, String.class);
|
||||
assertNotNull(service);
|
||||
assertEquals("AZ", service);
|
||||
|
||||
try {
|
||||
ssm.registerService("fakey", (Object) null);
|
||||
fail("should have thrown exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertNotNull(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterService() {
|
||||
ssm.startup();
|
||||
|
||||
String name = "myNewService";
|
||||
ssm.registerService(name, "AZ");
|
||||
String service = ssm.getServiceByName(name, String.class);
|
||||
assertNotNull(service);
|
||||
assertEquals("AZ", service);
|
||||
|
||||
ssm.unregisterService(name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetServicesNames() {
|
||||
ssm.startup();
|
||||
|
||||
List<String> names = ssm.getServicesNames();
|
||||
assertNotNull(names);
|
||||
assertTrue(names.size() >= 3);
|
||||
names = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsServiceExists() {
|
||||
ssm.startup();
|
||||
|
||||
String name = ConcreteExample.class.getName();
|
||||
boolean exists = ssm.isServiceExists(name);
|
||||
assertTrue(exists);
|
||||
|
||||
exists = ssm.isServiceExists("XXXXXXXXXXXXXXX");
|
||||
assertFalse(exists);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user