Updated Branches: refs/heads/master 4c1de3267 -> 017961387
WICKET-5079 improved application context handling Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/01796138 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/01796138 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/01796138 Branch: refs/heads/master Commit: 01796138744f6853d5c628f104fb0b7eb7131b0e Parents: 4c1de32 Author: svenmeier <[email protected]> Authored: Wed Mar 6 14:06:30 2013 +0100 Committer: svenmeier <[email protected]> Committed: Wed Mar 6 14:06:30 2013 +0100 ---------------------------------------------------------------------- .../wicket/spring/SpringWebApplicationFactory.java | 63 ++++--- .../injection/annot/SpringComponentInjector.java | 41 ++++- .../spring/SpringWebApplicationFactoryTest.java | 147 +++++++++++++++ .../apache/wicket/spring/applicationContext.xml | 24 +++ 4 files changed, 243 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/01796138/wicket-spring/src/main/java/org/apache/wicket/spring/SpringWebApplicationFactory.java ---------------------------------------------------------------------- diff --git a/wicket-spring/src/main/java/org/apache/wicket/spring/SpringWebApplicationFactory.java b/wicket-spring/src/main/java/org/apache/wicket/spring/SpringWebApplicationFactory.java index 2e385df..9c0ad8d 100644 --- a/wicket-spring/src/main/java/org/apache/wicket/spring/SpringWebApplicationFactory.java +++ b/wicket-spring/src/main/java/org/apache/wicket/spring/SpringWebApplicationFactory.java @@ -23,6 +23,7 @@ import javax.servlet.ServletContext; import org.apache.wicket.protocol.http.IWebApplicationFactory; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WicketFilter; +import org.apache.wicket.spring.injection.annot.SpringComponentInjector; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.context.ApplicationContext; @@ -69,8 +70,9 @@ import org.springframework.web.context.support.XmlWebApplicationContext; * </pre> * * <p> - * This factory is also capable of creating an additional application context (path to which is - * specified via the {@code contextConfigLocation} filter param) and chaining it to the global one + * This factory is also capable of creating a {@link WebApplication}-specific application context + * (path to which is specified via the {@code contextConfigLocation} filter param) and chaining it + * to the global one * </p> * * <pre> @@ -95,12 +97,12 @@ import org.springframework.web.context.support.XmlWebApplicationContext; public class SpringWebApplicationFactory implements IWebApplicationFactory { - /** additional context created for this filter, if any */ - private ConfigurableWebApplicationContext additionalContext; + /** web application context created for this filter, if any */ + private ConfigurableWebApplicationContext webApplicationContext; /** - * Returns location of context config that will be used to create an additional application - * context for this application + * Returns location of context config that will be used to create a {@link WebApplication} + * -specific application context. * * @param filter * @return location of context config @@ -111,8 +113,8 @@ public class SpringWebApplicationFactory implements IWebApplicationFactory } /** - * Factory method used to create a new instance of the additional application context, by - * default an instance o {@link XmlWebApplicationContext} will be created. + * Factory method used to create a new instance of the web application context, by default an + * instance o {@link XmlWebApplicationContext} will be created. * * @return application context instance */ @@ -127,34 +129,36 @@ public class SpringWebApplicationFactory implements IWebApplicationFactory @Override public WebApplication createApplication(final WicketFilter filter) { - ServletContext sc = filter.getFilterConfig().getServletContext(); + ServletContext servletContext = filter.getFilterConfig().getServletContext(); - WebApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sc); + WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); if (getContextConfigLocation(filter) != null) { - additionalContext = createWebApplicationContext(ac, filter); + applicationContext = createWebApplicationContext(applicationContext, filter); } String beanName = filter.getFilterConfig().getInitParameter("applicationBean"); - return createApplication((additionalContext != null) ? additionalContext : ac, beanName); + return createApplication(applicationContext, beanName); } - private WebApplication createApplication(final ApplicationContext ac, final String beanName) + private WebApplication createApplication(final ApplicationContext applicationContext, + final String beanName) { + WebApplication application; + if (beanName != null) { - WebApplication application = (WebApplication)ac.getBean(beanName); + application = (WebApplication)applicationContext.getBean(beanName); if (application == null) { throw new IllegalArgumentException( "Unable to find WebApplication bean with name [" + beanName + "]"); } - return application; } else { - Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(ac, + Map<?, ?> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, WebApplication.class, false, false); if (beans.size() == 0) { @@ -166,8 +170,13 @@ public class SpringWebApplicationFactory implements IWebApplicationFactory throw new IllegalStateException("More than one bean of type [" + WebApplication.class.getName() + "] found, must have only one"); } - return (WebApplication)beans.values().iterator().next(); + application = (WebApplication)beans.values().iterator().next(); } + + // make the application context default for SpringComponentInjectors + SpringComponentInjector.setDefaultContext(application, applicationContext); + + return application; } /** @@ -178,21 +187,21 @@ public class SpringWebApplicationFactory implements IWebApplicationFactory * parent application context * @param filter * wicket filter - * @return instance of additional application context + * @return instance of web application context * @throws BeansException */ protected final ConfigurableWebApplicationContext createWebApplicationContext( final WebApplicationContext parent, final WicketFilter filter) throws BeansException { - ConfigurableWebApplicationContext wac = newApplicationContext(); - wac.setParent(parent); - wac.setServletContext(filter.getFilterConfig().getServletContext()); - wac.setConfigLocation(getContextConfigLocation(filter)); + webApplicationContext = newApplicationContext(); + webApplicationContext.setParent(parent); + webApplicationContext.setServletContext(filter.getFilterConfig().getServletContext()); + webApplicationContext.setConfigLocation(getContextConfigLocation(filter)); - postProcessWebApplicationContext(wac, filter); - wac.refresh(); + postProcessWebApplicationContext(webApplicationContext, filter); + webApplicationContext.refresh(); - return wac; + return webApplicationContext; } /** @@ -214,9 +223,9 @@ public class SpringWebApplicationFactory implements IWebApplicationFactory @Override public void destroy(final WicketFilter filter) { - if (additionalContext != null) + if (webApplicationContext != null) { - additionalContext.close(); + webApplicationContext.close(); } } } http://git-wip-us.apache.org/repos/asf/wicket/blob/01796138/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/SpringComponentInjector.java ---------------------------------------------------------------------- diff --git a/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/SpringComponentInjector.java b/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/SpringComponentInjector.java index 125590c..eb722d4 100644 --- a/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/SpringComponentInjector.java +++ b/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/SpringComponentInjector.java @@ -69,17 +69,14 @@ public class SpringComponentInjector extends Injector /** * Constructor used when spring application context is declared in the spring standard way and * can be located through - * {@link WebApplicationContextUtils#getRequiredWebApplicationContext(ServletContext)} + * {@link WebApplicationContextUtils#getRequiredWebApplicationContext(ServletContext)}. * * @param webapp * wicket web application */ public SpringComponentInjector(final WebApplication webapp) { - // locate application context through spring's default location - // mechanism and pass it on to the proper constructor - this(webapp, - WebApplicationContextUtils.getRequiredWebApplicationContext(webapp.getServletContext())); + this(webapp, getDefaultContext(webapp)); } /** @@ -163,4 +160,38 @@ public class SpringComponentInjector extends Injector } + /** + * Try to use an already pre-configured application context or locate it through Spring's default + * location mechanism. + * + * @param webapp + * @return the application context to use for injection + */ + private static ApplicationContext getDefaultContext(final WebApplication webapp) + { + ApplicationContext context = webapp.getMetaData(CONTEXT_KEY); + if (context == null) + { + context = WebApplicationContextUtils.getRequiredWebApplicationContext(webapp.getServletContext()); + } + return context; + } + + /** + * Set the default context for the given webapp. + * + * @param webapp + * web application + * @param context + * context to use as default if non is explicitely specified for the injector + */ + public static void setDefaultContext(final WebApplication webapp, ApplicationContext context) + { + Args.notNull(context, "context"); + + if (webapp.getMetaData(CONTEXT_KEY) == null) + { + webapp.setMetaData(CONTEXT_KEY, context); + } + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/01796138/wicket-spring/src/test/java/org/apache/wicket/spring/SpringWebApplicationFactoryTest.java ---------------------------------------------------------------------- diff --git a/wicket-spring/src/test/java/org/apache/wicket/spring/SpringWebApplicationFactoryTest.java b/wicket-spring/src/test/java/org/apache/wicket/spring/SpringWebApplicationFactoryTest.java new file mode 100644 index 0000000..ad1c9f5 --- /dev/null +++ b/wicket-spring/src/test/java/org/apache/wicket/spring/SpringWebApplicationFactoryTest.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.spring; + +import java.util.Enumeration; + +import javax.servlet.FilterConfig; +import javax.servlet.ServletContext; + +import org.apache.wicket.Page; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WicketFilter; +import org.apache.wicket.protocol.http.mock.MockServletContext; +import org.apache.wicket.spring.injection.annot.SpringComponentInjector; +import org.apache.wicket.util.lang.Packages; +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for {@link SpringWebApplicationFactory}. + * + * @author svenmeier + */ +public class SpringWebApplicationFactoryTest extends Assert +{ + + /** + * @throws Exception + */ + @Test + public void test() throws Exception + { + WicketFilter filter = new WicketFilter(); + + filter.init(new FilterConfigImpl()); + + assertFalse(Destroyable.instance.destroyed); + + filter.destroy(); + + assertTrue("is not destroyed", Destroyable.instance.destroyed); + } + + private class FilterConfigImpl implements FilterConfig + { + + @Override + public String getFilterName() + { + return "test"; + } + + @Override + public ServletContext getServletContext() + { + return new MockServletContext(null, null); + } + + @Override + public String getInitParameter(String name) + { + if ("applicationFactoryClassName".equals(name)) + { + // use Spring factory + return SpringWebApplicationFactory.class.getName(); + } + if ("contextConfigLocation".equals(name)) + { + // use application-specific context + return "classpath:" + Packages.absolutePath(getClass(), "applicationContext.xml"); + } + return null; + } + + @Override + public Enumeration<?> getInitParameterNames() + { + throw new UnsupportedOperationException(); + } + } + + /** + * Application configured in the application context. + */ + public static class Application extends WebApplication + { + @Override + public Class<? extends Page> getHomePage() + { + throw new UnsupportedOperationException(); + } + + @Override + protected void init() + { + super.init(); + + try + { + new SpringComponentInjector(this); + } + catch (Exception ex) + { + fail("does not work with application-specific context"); + } + } + } + + /** + * A destroyable bean defined in the application context. + */ + public static class Destroyable + { + static Destroyable instance; + + boolean destroyed; + + /** + */ + public Destroyable() + { + instance = this; + } + + /** + * Called by Spring. + */ + public void destroy() + { + destroyed = true; + } + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/01796138/wicket-spring/src/test/java/org/apache/wicket/spring/applicationContext.xml ---------------------------------------------------------------------- diff --git a/wicket-spring/src/test/java/org/apache/wicket/spring/applicationContext.xml b/wicket-spring/src/test/java/org/apache/wicket/spring/applicationContext.xml new file mode 100644 index 0000000..d1a961d --- /dev/null +++ b/wicket-spring/src/test/java/org/apache/wicket/spring/applicationContext.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> + +<beans> + <bean class="org.apache.wicket.spring.SpringWebApplicationFactoryTest$Application" /> + + <bean id="watcher" class="org.apache.wicket.spring.SpringWebApplicationFactoryTest$Destroyable" destroy-method="destroy" /> +</beans>
