Skip to content

Commit

Permalink
Relax ConfigurableWebEnvironment signatures
Browse files Browse the repository at this point in the history
ConfigurableWebEnvironment was introduced in 3.2.0.M1 with SPR-9439 in
order to break a cyclic dependency. At the same time, certain signatures
such as AbstractRefreshableWebApplicationContext#getEnviroment and
GenericWebApplicationContext#getEnvironment were updated to take
advantage of covariant return types and return this newer, more narrow
type and providing cast-free calls to ConfigurableWebEnvironment methods
where necessary. Similar changes were made to HttpServletBean in
3.2.0.M2 with SPR-9763.

Narrowing #getEnvironment signatures in this fashion required enforcing
at the #setEnvironment level that any Environment instance provided
(explicitly or via the EnvironmentAware callback) must be an instance of
ConfigurableWebEnvironment. This is a reasonable assertion in typical
web application scenarios, but as SPR-10138 demonstrates, there are
valid use cases in which one may want or need to inject a non-web
ConfigurableEnvironment variant, e.g. during automated unit/integration
testing.

On review, it was never strictly necessary to narrow #getEnvironment
signatures, although doing so did provided convenience and type safety.
In order to maintain as flexible and backward-compatible an arrangement
as possible, this commit relaxes these #getEnvironment signatures back
to their original, pre-3.2 state. Namely, they now return
ConfigurableEnvironment as opposed to ConfigurableWebEnvironment, and in
accordance, all instanceof assertions have been removed or relaxed to
ensure that injected Environment instances are of type
ConfigurableEnvironment.

These changes have been verified against David Winterfeldt's Spring by
Example spring-rest-services project, as described at SPR-10138.

Issue: SPR-10138, SPR-9763, SPR-9439
  • Loading branch information
cbeams committed Jan 22, 2013
1 parent d9a4fb4 commit 3cdb866
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 55 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -71,11 +71,6 @@ public interface ConfigurableWebApplicationContext extends WebApplicationContext
*/
ServletConfig getServletConfig();

/**
* Return the {@link ConfigurableWebEnvironment} used by this web application context.
*/
ConfigurableWebEnvironment getEnvironment();

/**
* Set the namespace for this web application context,
* to be used for building a default context config location.
Expand Down
Expand Up @@ -38,6 +38,7 @@
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -490,7 +491,10 @@ protected void customizeContext(ServletContext servletContext, ConfigurableWebAp
initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
}

applicationContext.getEnvironment().initPropertySources(servletContext, null);
ConfigurableEnvironment env = applicationContext.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(servletContext, null);
}

Collections.sort(initializerInstances, new AnnotationAwareOrderComparator());
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,7 +27,6 @@
import org.springframework.ui.context.Theme;
import org.springframework.ui.context.ThemeSource;
import org.springframework.ui.context.support.UiApplicationContextUtils;
import org.springframework.util.Assert;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ConfigurableWebEnvironment;
import org.springframework.web.context.ServletConfigAware;
Expand Down Expand Up @@ -157,15 +156,6 @@ protected ConfigurableEnvironment createEnvironment() {
return new StandardServletEnvironment();
}

@Override
public ConfigurableWebEnvironment getEnvironment() {
ConfigurableEnvironment env = super.getEnvironment();
Assert.isInstanceOf(ConfigurableWebEnvironment.class, env,
"ConfigurableWebApplicationContext environment must be of type " +
"ConfigurableWebEnvironment");
return (ConfigurableWebEnvironment) env;
}

/**
* Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
*/
Expand Down Expand Up @@ -212,7 +202,11 @@ protected void onRefresh() {
@Override
protected void initPropertySources() {
super.initPropertySources();
this.getEnvironment().initPropertySources(this.servletContext, this.servletConfig);
ConfigurableEnvironment env = this.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(
this.servletContext, this.servletConfig);
}
}

public Theme getTheme(String themeName) {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -147,15 +147,6 @@ protected ConfigurableEnvironment createEnvironment() {
return new StandardServletEnvironment();
}

@Override
public ConfigurableWebEnvironment getEnvironment() {
ConfigurableEnvironment env = super.getEnvironment();
Assert.isInstanceOf(ConfigurableWebEnvironment.class, env,
"ConfigurableWebApplicationContext environment must be of type " +
"ConfigurableWebEnvironment");
return (ConfigurableWebEnvironment) env;
}

/**
* Register ServletContextAwareProcessor.
* @see ServletContextAwareProcessor
Expand Down Expand Up @@ -202,7 +193,11 @@ protected void onRefresh() {
@Override
protected void initPropertySources() {
super.initPropertySources();
this.getEnvironment().initPropertySources(this.servletContext, null);
ConfigurableEnvironment env = this.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(
this.servletContext, null);
}
}

public Theme getTheme(String themeName) {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,9 +27,7 @@
import org.springframework.ui.context.Theme;
import org.springframework.ui.context.ThemeSource;
import org.springframework.ui.context.support.UiApplicationContextUtils;
import org.springframework.util.Assert;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ConfigurableWebEnvironment;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.context.ServletContextAware;

Expand Down Expand Up @@ -169,15 +167,6 @@ protected ConfigurableEnvironment createEnvironment() {
return new StandardServletEnvironment();
}

@Override
public ConfigurableWebEnvironment getEnvironment() {
ConfigurableEnvironment env = super.getEnvironment();
Assert.isInstanceOf(ConfigurableWebEnvironment.class, env,
"ConfigurableWebApplication environment must be of type " +
"ConfigurableWebEnvironment");
return (ConfigurableWebEnvironment) env;
}

/**
* Initialize the theme capability.
*/
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,11 +39,13 @@
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.ConfigurableWebEnvironment;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
Expand Down Expand Up @@ -638,7 +640,10 @@ protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicati
// the context is refreshed; do it eagerly here to ensure servlet property sources
// are in place for use in any post-processing or initialization that occurs
// below prior to #refresh
wac.getEnvironment().initPropertySources(getServletContext(), getServletConfig());
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(getServletContext(), getServletConfig());
}

postProcessWebApplicationContext(wac);

Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -27,24 +27,23 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceEditor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ConfigurableWebEnvironment;
import org.springframework.web.context.support.StandardServletEnvironment;
import org.springframework.web.context.support.ServletContextResourceLoader;
import org.springframework.web.context.support.StandardServletEnvironment;

/**
* Simple extension of {@link javax.servlet.http.HttpServlet} which treats
Expand Down Expand Up @@ -91,7 +90,7 @@ public abstract class HttpServletBean extends HttpServlet
*/
private final Set<String> requiredProperties = new HashSet<String>();

private ConfigurableWebEnvironment environment;
private ConfigurableEnvironment environment;


/**
Expand Down Expand Up @@ -187,19 +186,19 @@ protected void initServletBean() throws ServletException {
/**
* {@inheritDoc}
* @throws IllegalArgumentException if environment is not assignable to
* {@code ConfigurableWebEnvironment}.
* {@code ConfigurableEnvironment}.
*/
public void setEnvironment(Environment environment) {
Assert.isInstanceOf(ConfigurableWebEnvironment.class, environment);
this.environment = (ConfigurableWebEnvironment)environment;
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
this.environment = (ConfigurableEnvironment) environment;
}

/**
* {@inheritDoc}
* <p>If {@code null}, a new environment will be initialized via
* {@link #createEnvironment()}.
*/
public ConfigurableWebEnvironment getEnvironment() {
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = this.createEnvironment();
}
Expand All @@ -210,7 +209,7 @@ public ConfigurableWebEnvironment getEnvironment() {
* Create and return a new {@link StandardServletEnvironment}. Subclasses may override
* in order to configure the environment or specialize the environment type returned.
*/
protected ConfigurableWebEnvironment createEnvironment() {
protected ConfigurableEnvironment createEnvironment() {
return new StandardServletEnvironment();
}

Expand Down
Expand Up @@ -833,7 +833,7 @@ public void testDispatcherServletContextRefresh() throws ServletException {

public void testEnvironmentOperations() {
DispatcherServlet servlet = new DispatcherServlet();
ConfigurableWebEnvironment defaultEnv = servlet.getEnvironment();
ConfigurableEnvironment defaultEnv = servlet.getEnvironment();
assertThat(defaultEnv, notNullValue());
ConfigurableEnvironment env1 = new StandardServletEnvironment();
servlet.setEnvironment(env1); // should succeed
Expand Down

0 comments on commit 3cdb866

Please sign in to comment.