mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Refactor Application startup to load DSpace configs early in boot process. Also fixes DS-3492
This commit is contained in:
@@ -14,6 +14,7 @@ import org.dspace.app.rest.filter.DSpaceRequestContextFilter;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceRelProvider;
|
||||
import org.dspace.app.rest.parameter.resolver.SearchFilterResolver;
|
||||
import org.dspace.app.rest.utils.ApplicationConfig;
|
||||
import org.dspace.app.rest.utils.DSpaceConfigurationInitializer;
|
||||
import org.dspace.app.rest.utils.DSpaceKernelInitializer;
|
||||
import org.dspace.app.util.DSpaceContextListener;
|
||||
import org.dspace.utils.servlet.DSpaceWebappServletFilter;
|
||||
@@ -22,7 +23,6 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -62,7 +62,6 @@ public class Application extends SpringBootServletInitializer {
|
||||
* This is necessary to allow us to build a deployable WAR, rather than
|
||||
* always relying on embedded Tomcat.
|
||||
* <p>
|
||||
* <p>
|
||||
* See: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file
|
||||
*
|
||||
* @param application
|
||||
@@ -70,13 +69,10 @@ public class Application extends SpringBootServletInitializer {
|
||||
*/
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
// Pass this Application class, and our initializers for DSpace Kernel and Configuration
|
||||
// NOTE: Kernel must be initialized before Configuration
|
||||
return application.sources(Application.class)
|
||||
.initializers(new DSpaceKernelInitializer());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletContextInitializer contextInitializer() {
|
||||
return servletContext -> servletContext.setInitParameter("dspace.dir", configuration.getDspaceHome());
|
||||
.initializers(new DSpaceKernelInitializer(), new DSpaceConfigurationInitializer());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +85,6 @@ public class Application extends SpringBootServletInitializer {
|
||||
@Order(2)
|
||||
protected DSpaceContextListener dspaceContextListener() {
|
||||
// This listener initializes the DSpace Context object
|
||||
// (and loads all DSpace configs)
|
||||
return new DSpaceContextListener();
|
||||
}
|
||||
|
||||
|
@@ -13,27 +13,24 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.web.config.EnableSpringDataWebSupport;
|
||||
|
||||
/**
|
||||
* This class provide extra configuration for our Spring Boot Application
|
||||
* This class provides extra configuration for our Spring Boot Application
|
||||
* <p>
|
||||
* NOTE: @ComponentScan on "org.dspace.app.configuration" provides a way for other modules or plugins
|
||||
* to "inject" their own configurations / subpaths into our Spring Boot webapp.
|
||||
* NOTE: @ComponentScan on "org.dspace.app.configuration" provides a way for other DSpace modules or plugins
|
||||
* to "inject" their own Spring configurations / subpaths into our Spring Boot webapp.
|
||||
*
|
||||
* @author Andrea Bollini (andrea.bollini at 4science.it)
|
||||
* @author Tim Donohue
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSpringDataWebSupport
|
||||
@ComponentScan( {"org.dspace.app.rest.converter", "org.dspace.app.rest.repository", "org.dspace.app.rest.utils",
|
||||
"org.dspace.app.configuration"})
|
||||
public class ApplicationConfig {
|
||||
@Value("${dspace.dir}")
|
||||
private String dspaceHome;
|
||||
|
||||
@Value("${cors.allowed-origins}")
|
||||
// Allowed CORS origins. Defaults to * (everywhere)
|
||||
// Can be overridden in DSpace configuration
|
||||
@Value("${rest.cors.allowed-origins:*}")
|
||||
private String corsAllowedOrigins;
|
||||
|
||||
public String getDspaceHome() {
|
||||
return dspaceHome;
|
||||
}
|
||||
|
||||
public String[] getCorsAllowedOrigins() {
|
||||
if (corsAllowedOrigins != null) {
|
||||
return corsAllowedOrigins.split("\\s*,\\s*");
|
||||
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.app.rest.utils;
|
||||
|
||||
import org.apache.commons.configuration2.Configuration;
|
||||
import org.apache.commons.configuration2.spring.ConfigurationPropertySource;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Utility class that will initialize the DSpace Configuration on Spring Boot startup.
|
||||
* <P>
|
||||
* NOTE: MUST be loaded after DSpaceKernelInitializer, as it requires the kernel is already initialized.
|
||||
* <P>
|
||||
* This initializer ensures that our DSpace Configuration is loaded into Spring's list of PropertySources
|
||||
* very early in the Spring Boot startup process. That is important as it allows us to use DSpace configurations
|
||||
* within @ConditionalOnProperty annotations on beans, as well as @Value annotations and XML bean definitions.
|
||||
* <P>
|
||||
* Used by org.dspace.app.rest.Application
|
||||
*/
|
||||
public class DSpaceConfigurationInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DSpaceConfigurationInitializer.class);
|
||||
|
||||
@Override
|
||||
public void initialize(final ConfigurableApplicationContext applicationContext) {
|
||||
// Load DSpace Configuration service (requires kernel already initialized)
|
||||
ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
|
||||
Configuration configuration = configurationService.getConfiguration();
|
||||
|
||||
// Create an Apache Commons Configuration Property Source from our configuration
|
||||
ConfigurationPropertySource apacheCommonsConfigPropertySource =
|
||||
new ConfigurationPropertySource(configuration.getClass().getName(), configuration);
|
||||
|
||||
// Append it to the Environment's list of PropertySources
|
||||
applicationContext.getEnvironment().getPropertySources().addLast(apacheCommonsConfigPropertySource);
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ import java.io.File;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.kernel.DSpaceKernel;
|
||||
import org.dspace.kernel.DSpaceKernelManager;
|
||||
import org.dspace.servicemanager.DSpaceKernelImpl;
|
||||
@@ -22,6 +23,7 @@ import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
/**
|
||||
* Utility class that will initialize the DSpace Kernel on Spring Boot startup.
|
||||
@@ -35,16 +37,16 @@ public class DSpaceKernelInitializer implements ApplicationContextInitializer<Co
|
||||
|
||||
@Override
|
||||
public void initialize(final ConfigurableApplicationContext applicationContext) {
|
||||
|
||||
String dspaceHome = applicationContext.getEnvironment().getProperty("dspace.dir");
|
||||
|
||||
// Check if the kernel is already started
|
||||
this.dspaceKernel = DSpaceKernelManager.getDefaultKernel();
|
||||
if (this.dspaceKernel == null) {
|
||||
DSpaceKernelImpl kernelImpl = null;
|
||||
try {
|
||||
// Load the kernel with default settings
|
||||
kernelImpl = DSpaceKernelInit.getKernel(null);
|
||||
if (!kernelImpl.isRunning()) {
|
||||
kernelImpl.start(getProvidedHome(dspaceHome)); // init the kernel
|
||||
// Determine configured DSpace home & init the Kernel
|
||||
kernelImpl.start(getDSpaceHome(applicationContext.getEnvironment()));
|
||||
}
|
||||
this.dspaceKernel = kernelImpl;
|
||||
|
||||
@@ -65,8 +67,8 @@ public class DSpaceKernelInitializer implements ApplicationContextInitializer<Co
|
||||
}
|
||||
|
||||
if (applicationContext.getParent() == null) {
|
||||
//Set the DSpace Kernel Application context as a parent of the Spring Boot context so that
|
||||
//we can auto-wire all DSpace Kernel services
|
||||
// Set the DSpace Kernel Application context as a parent of the Spring Boot context so that
|
||||
// we can auto-wire all DSpace Kernel services
|
||||
applicationContext.setParent(dspaceKernel.getServiceManager().getApplicationContext());
|
||||
|
||||
//Add a listener for Spring Boot application shutdown so that we can nicely cleanup the DSpace kernel.
|
||||
@@ -75,29 +77,35 @@ public class DSpaceKernelInitializer implements ApplicationContextInitializer<Co
|
||||
}
|
||||
|
||||
/**
|
||||
* Find DSpace's "home" directory.
|
||||
* Find DSpace's "home" directory (from current environment)
|
||||
* Initially look for JNDI Resource called "java:/comp/env/dspace.dir".
|
||||
* If not found, look for "dspace.dir" initial context parameter.
|
||||
* If not found, use value provided in "dspace.dir" in Spring Environment
|
||||
*/
|
||||
private String getProvidedHome(String dspaceHome) {
|
||||
String providedHome = null;
|
||||
private String getDSpaceHome(ConfigurableEnvironment environment) {
|
||||
// Load the "dspace.dir" property from Spring Boot's Configuration (application.properties)
|
||||
// This gives us the location of our DSpace configurations, necessary to start the kernel
|
||||
String providedHome = environment.getProperty(DSpaceConfigurationService.DSPACE_HOME);
|
||||
|
||||
String dspaceHome = null;
|
||||
try {
|
||||
// Allow ability to override home directory via JNDI
|
||||
Context ctx = new InitialContext();
|
||||
providedHome = (String) ctx.lookup("java:/comp/env/" + DSpaceConfigurationService.DSPACE_HOME);
|
||||
dspaceHome = (String) ctx.lookup("java:/comp/env/" + DSpaceConfigurationService.DSPACE_HOME);
|
||||
} catch (Exception e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
if (providedHome == null) {
|
||||
if (dspaceHome != null && !dspaceHome.equals("") &&
|
||||
!dspaceHome.equals("${" + DSpaceConfigurationService.DSPACE_HOME + "}")) {
|
||||
File test = new File(dspaceHome);
|
||||
// Otherwise, verify the 'providedHome' value is non-empty, exists and includes DSpace configs
|
||||
if (dspaceHome == null) {
|
||||
if (StringUtils.isNotBlank(providedHome) &&
|
||||
!providedHome.equals("${" + DSpaceConfigurationService.DSPACE_HOME + "}")) {
|
||||
File test = new File(providedHome);
|
||||
if (test.exists() && new File(test, DSpaceConfigurationService.DSPACE_CONFIG_PATH).exists()) {
|
||||
providedHome = dspaceHome;
|
||||
dspaceHome = providedHome;
|
||||
}
|
||||
}
|
||||
}
|
||||
return providedHome;
|
||||
return dspaceHome;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -13,28 +13,14 @@
|
||||
# For common settings see:
|
||||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
#
|
||||
#
|
||||
# TODO: Eventually would could think of "wiring" this up to use Commons Configuration as well
|
||||
# See, for example: http://stackoverflow.com/questions/25271537/remote-propertysource
|
||||
# and https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
|
||||
|
||||
########################
|
||||
# DSpace Settings
|
||||
#
|
||||
# DSpace installation directory
|
||||
# DSpace home/installation directory
|
||||
# REQUIRED to be specified in this application.properties file, as it is used to locate and initialize
|
||||
# the DSpace Kernel and all Services (including configuration). See org.dspace.app.rest.Application.getDSpaceHome()
|
||||
dspace.dir=${dspace.dir}
|
||||
#dspace.dir=d:/install/dspace7
|
||||
|
||||
########################
|
||||
# DSpace API CORS Settings
|
||||
#
|
||||
cors.allowed-origins = *
|
||||
|
||||
########################
|
||||
# Spring Boot Settings
|
||||
#
|
||||
# Testing an "application Name"
|
||||
spring.application.name = DSpace Spring Rest
|
||||
|
||||
########################
|
||||
# Spring DATA Rest settings
|
||||
@@ -75,15 +61,6 @@ server.port=8080
|
||||
# (Optional, defaults to root context)
|
||||
#server.context-path=/spring-data-rest
|
||||
|
||||
# This creates a Tomcat context-param named "dspace.dir"
|
||||
# and sets it to the value of the "dspace.dir" property (listed above)
|
||||
server.context-parameters.dspace.dir=${dspace.dir}
|
||||
|
||||
# This creates a Tomcat context-param named "dspace-config"
|
||||
# (Used by DSpaceContextListener to load the configurations)
|
||||
# This is only needed in DSpace 5 or below to initialize ConfigurationManager
|
||||
#server.context-parameters.dspace-config=${dspace.dir}/config/dspace.cfg
|
||||
|
||||
# Error handling settings
|
||||
# Always include the fullstacktrace in error pages
|
||||
# Can be set to "never" if you don't want it.
|
||||
|
@@ -1,9 +1,17 @@
|
||||
#---------------------------------------------------------------#
|
||||
#--------------------REST CONFIGURATIONS------------------------#
|
||||
#---------------------------------------------------------------#
|
||||
# These configs are used by the REST module #
|
||||
# These configs are used by the RESTv7 module #
|
||||
#---------------------------------------------------------------#
|
||||
# Allowed CORS origins. Defaults to * (everywhere)
|
||||
# Multiple allowed origin URLs may be comma separated
|
||||
# (Requires reboot of servlet container, e.g. Tomcat, to reload)
|
||||
rest.cors.allowed-origins = *
|
||||
|
||||
|
||||
#---------------------------------------------------------------#
|
||||
# These configs are used by the deprecated REST (v4-6) module #
|
||||
#---------------------------------------------------------------#
|
||||
# record stats in DSpace statistics module
|
||||
rest.stats = true
|
||||
|
||||
@@ -137,4 +145,4 @@ rest.report-regex-xml-entity = ^.*&#.*$
|
||||
rest.report-regex-non-ascii = ^.*[^\\p{ASCII}].*$
|
||||
|
||||
# The maximum number of results to return for 1 request
|
||||
rest.search.max.results = 100
|
||||
rest.search.max.results = 100
|
||||
|
Reference in New Issue
Block a user