You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2013/03/06 14:07:00 UTC

git commit: WICKET-5079 improved application context handling

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 <sv...@apache.org>
Authored: Wed Mar 6 14:06:30 2013 +0100
Committer: svenmeier <sv...@apache.org>
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>