Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

WICKET-5079 improved application context handling

  • Loading branch information...
commit 01796138744f6853d5c628f104fb0b7eb7131b0e 1 parent 4c1de32
svenmeier authored
View
63 wicket-spring/src/main/java/org/apache/wicket/spring/SpringWebApplicationFactory.java
@@ -23,6 +23,7 @@
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 @@
* </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 @@
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 @@ protected final String getContextConfigLocation(final WicketFilter filter)
}
/**
- * 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 @@ protected ConfigurableWebApplicationContext newApplicationContext()
@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 @@ private WebApplication createApplication(final ApplicationContext ac, final Stri
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 @@ private WebApplication createApplication(final ApplicationContext ac, final Stri
* 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 @@ protected void postProcessWebApplicationContext(final ConfigurableWebApplication
@Override
public void destroy(final WicketFilter filter)
{
- if (additionalContext != null)
+ if (webApplicationContext != null)
{
- additionalContext.close();
+ webApplicationContext.close();
}
}
}
View
41 wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/SpringComponentInjector.java
@@ -69,17 +69,14 @@
/**
* 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 ApplicationContext getSpringContext()
}
+ /**
+ * 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);
+ }
+ }
}
View
147 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;
+ }
+ }
+}
View
24 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>
Please sign in to comment.
Something went wrong with that request. Please try again.