non proxied spring beans now refresh as expected

git-svn-id: https://svn.apache.org/repos/asf/myfaces/extensions/scripting/trunk@1401687 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/CompilationAwareRefreshableBeanFactory.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/CompilationAwareRefreshableBeanFactory.java
new file mode 100644
index 0000000..4f84472
--- /dev/null
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/CompilationAwareRefreshableBeanFactory.java
@@ -0,0 +1,131 @@
+/*
+ * 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.myfaces.extensions.scripting.spring.bean;
+
+import org.apache.myfaces.extensions.scripting.core.common.util.ReflectUtil;
+import org.apache.myfaces.extensions.scripting.core.engine.ThrowAwayClassloader;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.CannotLoadBeanClassException;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.DecoratingClassLoader;
+import org.springframework.util.ClassUtils;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class CompilationAwareRefreshableBeanFactory extends DefaultListableBeanFactory
+{
+    public CompilationAwareRefreshableBeanFactory(BeanFactory parentBeanFactory)
+    {
+        super(parentBeanFactory);
+    }
+
+    public CompilationAwareRefreshableBeanFactory()
+    {
+    }
+
+    /**
+     * We have to set our throw away classloader
+     * here so that it is picked up by spring
+     *
+     * @param beanClassLoader
+     */
+    @Override
+    public void setBeanClassLoader(ClassLoader beanClassLoader)
+    {
+        if (!(beanClassLoader instanceof ThrowAwayClassloader))
+        {
+            super.setBeanClassLoader(new ThrowAwayClassloader(beanClassLoader));
+        } else
+        {
+            super.setBeanClassLoader(beanClassLoader);
+        }
+    }
+
+    @Override
+    protected Class resolveBeanClass(RootBeanDefinition mbd, String beanName)
+    {
+        //TODO drop the check whether the class has been loaded before
+        //and then resolve the class from the classloader
+
+        return super.resolveBeanClass(mbd, beanName);
+    }
+
+    @Override
+    protected Class resolveBeanClass(RootBeanDefinition beanDefinition, String beanName, Class[] typesToMatch) throws CannotLoadBeanClassException
+    {
+        try
+        {
+            // Note that this implementation doesn't check if the bean class has
+            // already been resolved previously (i.e. there's no check whether
+            // mbd.getBeanClass() is null). In doing so, it's possible to
+            // reload recompiled Class files.
+
+            if (typesToMatch != null)
+            {
+                ClassLoader tempClassLoader = getTempClassLoader();
+                if (tempClassLoader != null)
+                {
+                    if (tempClassLoader instanceof DecoratingClassLoader)
+                    {
+                        DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
+                        for (int i = 0; i < typesToMatch.length; i++)
+                        {
+                            dcl.excludeClass(typesToMatch[i].getName());
+                        }
+                    }
+                    String className = beanDefinition.getBeanClassName();
+                    return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
+                }
+            }
+
+            Class retVal = beanDefinition.resolveBeanClass(getBeanClassLoader());
+            try
+            {
+                //spring caches the constructor, we have to set it anew
+                //this imposes a limitation to () constructors but
+                //I guess we can live with it
+                Constructor ctor = retVal.getConstructor();
+                ReflectUtil.setField(beanDefinition,"resolvedConstructorOrFactoryMethod", ctor, true);
+            }
+            catch (NoSuchMethodException e)
+            {
+                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+            }
+
+            return retVal;
+        }
+        catch (ClassNotFoundException ex)
+        {
+            throw new CannotLoadBeanClassException(
+                    beanDefinition.getResourceDescription(), beanName, beanDefinition.getBeanClassName(), ex);
+        }
+        catch (LinkageError err)
+        {
+            throw new CannotLoadBeanClassException(
+                    beanDefinition.getResourceDescription(), beanName, beanDefinition.getBeanClassName(), err);
+        }
+    }
+}
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/RefreshableBeanAttribute.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/RefreshableBeanAttribute.java
new file mode 100644
index 0000000..23f4698
--- /dev/null
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/RefreshableBeanAttribute.java
@@ -0,0 +1,113 @@
+/*
+ * 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.myfaces.extensions.scripting.spring.bean;
+
+import org.springframework.core.Conventions;
+
+/**
+ * <p>An attribute that will be attached to those bean definitions that are refreshable, i.e. this
+ * class contains some of the required metadata that you'll have to access if you want to decide
+ * whether a bean definition has to be refreshed or not. Note that this attribute, however, is
+ * only capable of determining whether a bean definition has to be refreshed, sometimes you'll
+ * actually have to refresh bean instances as well.</p>
+ */
+public class RefreshableBeanAttribute
+{
+
+    /**
+     * <p>The name of the bean definition metadata attribute that refers to an instance
+     * of this class, i.e. use this attribute name if you want to obtain all information
+     * regarding the last time that the bean definition has been refreshed.</p>
+     */
+    public static final String REFRESHABLE_BEAN_ATTRIBUTE =
+            Conventions.getQualifiedAttributeName(RefreshableBeanAttribute.class, "refreshableBeanAttribute");
+
+    /**
+     * <p>The timestamp in milliseconds of the last time that the bean
+     * definition that this attribute belongs to has been requested to
+     * refresh itself.</p>
+     */
+    private long refreshRequested;
+
+    /**
+     * <p>The timestamp in milliseconds of the last time that the bean
+     * definition that this attribute belongs to has been actually
+     * refreshed.</p>
+     */
+    private long refreshExecuted;
+
+    /**
+     * <p>By calling this method the user is able to request another refresh. Note that
+     * this doesn't cause the bean factory to refresh the bean definition immediately,
+     * but rather it just signals a request. The bean definition will be refreshed once
+     * the bean factory has to deal with the next bean request (i.e. a call to
+     * getBean()).</p>
+     */
+    public void requestRefresh()
+    {
+        refreshRequested = System.currentTimeMillis();
+    }
+
+    /**
+     * <p>Returns the timestamp in milliseconds of the last time that a refresh operation
+     * has been requested.</p>
+     *
+     * @return the timestamp in milliseconds of the last refresh request
+     */
+    public long getRequestedRefreshDate()
+    {
+        return refreshRequested;
+    }
+
+    /**
+     * <p>By calling this method the user indicates that the according bean definition
+     * has just been refreshed, which means that the method #{@link #requiresRefresh()}
+     * will return <code>false</code> until the user requests the next refresh.</p>
+     */
+    public void executedRefresh()
+    {
+        refreshExecuted = System.currentTimeMillis();
+    }
+
+    /**
+     * <p>Returns the timestamp in milliseconds of the last time that a refresh operation
+     * has been executed.</p>
+     *
+     * @return the timestamp in milliseconds of the last executed refresh operation
+     */
+    public long getExecutedRefreshDate()
+    {
+        return refreshExecuted;
+    }
+
+    /**
+     * <p>Determines whether a refresh is required, i.e. whether the user has requested
+     * another refresh operation by calling {@link #requestRefresh()} recently. Note that
+     * a call to this method only determines whether the bean definition on its own has
+     * to be refreshed (i.e. it doesn't even consider a particular bean instance).</p>
+     *
+     * @return whether a refresh call is required
+     */
+    public boolean requiresRefresh()
+    {
+        return getExecutedRefreshDate() < getRequestedRefreshDate();
+    }
+
+}
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/RefreshableBeanFactory.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/RefreshableBeanFactory.java
new file mode 100644
index 0000000..82ef31c
--- /dev/null
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/bean/RefreshableBeanFactory.java
@@ -0,0 +1,65 @@
+/*
+ * 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.myfaces.extensions.scripting.spring.bean;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+
+/**
+ *
+ */
+public interface RefreshableBeanFactory extends ConfigurableListableBeanFactory
+{
+
+    /**
+     * <p>Requests a refresh operation for the definition of the bean with the given name. However,
+     * note that this doesn't necessarily mean that the bean definition gets refreshed immediatedly.
+     * Calling this method just ensures that the bean factory uses a refreshed bean definition by
+     * the next time you access the bean with the given name again.</p>
+     *
+     * @param name the name of the bean to refresh
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *          if there is no bean with the given name
+     * @throws org.springframework.beans.factory.BeanDefinitionStoreException
+     *          in case of an invalid bean definition
+     */
+    public void refreshBeanDefinition(String name) throws BeansException;
+
+    /**
+     * <p>Requests a refresh operation for definitions of beans with the given type. Again this
+     * doesn't necessarily mean that those bean definitions get refreshed immediately as calling
+     * this method just ensures that the bean factory uses a refreshed bean definition the next
+     * time you access one of those beans again.</p>
+     *
+     * @param className            the type that you want to refresh beans for
+     * @param includeNonSingletons whether to include prototype or scoped beans too
+     *                             or just singletons (also applies to FactoryBeans)
+     * @param allowEagerInit       whether to initialize <i>lazy-init singletons</i> and
+     *                             <i>objects created by FactoryBeans</i> (or by factory methods with a
+     *                             "factory-bean" reference) for the type check
+     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+     *          if there is no bean with the given name
+     * @throws org.springframework.beans.factory.BeanDefinitionStoreException
+     *          in case of an invalid bean definition
+     */
+    public void refreshBeanDefinitionsOfType(String className, boolean includeNonSingletons, boolean allowEagerInit)
+            throws BeansException;
+
+}
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoader.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoader.java
index f5ef082..00ffc8f 100644
--- a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoader.java
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoader.java
@@ -23,6 +23,8 @@
 import org.apache.myfaces.extensions.scripting.jsf.startup.StartupServletContextPluginChainLoader;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextException;
+import org.springframework.web.context.ConfigurableWebApplicationContext;
 import org.springframework.web.context.ContextLoader;
 import org.springframework.web.context.WebApplicationContext;
 
@@ -42,7 +44,14 @@
     protected WebApplicationContext createWebApplicationContext(
             ServletContext servletContext, ApplicationContext parent) throws BeansException
     {
-        WebApplicationContext retVal = super.createWebApplicationContext(servletContext, parent);
+        ConfigurableWebApplicationContext wac = new CompilationAwareXmlWebApplicationContext();
+
+        wac.setParent(parent);
+        wac.setServletContext(servletContext);
+        wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
+        customizeContext(servletContext, wac);
+        wac.refresh();
+
         //we now init the scripting system
         try
         {
@@ -50,8 +59,9 @@
             //after the container is kickstarted
             if (servletContext.getAttribute(RELOADING_LISTENER) == null)
             {
+                //probably already started
                 StartupServletContextPluginChainLoader.startup(servletContext);
-                servletContext.setAttribute(RELOADING_LISTENER, new ReloadingListener());
+                servletContext.setAttribute(RELOADING_LISTENER, new ReloadingListener(wac));
                 WeavingContext.getInstance().addListener((ReloadingListener) servletContext.getAttribute(RELOADING_LISTENER));
             }
         }
@@ -59,6 +69,21 @@
         {
             e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
         }
-        return retVal;
+
+        Class contextClass = determineContextClass(servletContext);
+        if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass))
+        {
+            throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
+                    "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
+        }
+
+        return wac;
     }
+
+    @Override
+    public void closeWebApplicationContext(ServletContext servletContext)
+    {
+        super.closeWebApplicationContext(servletContext);
+    }
+
 }
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoaderListener.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoaderListener.java
index 89414ac..fc843d6 100644
--- a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoaderListener.java
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareContextLoaderListener.java
@@ -22,6 +22,8 @@
 import org.springframework.web.context.ContextLoader;
 import org.springframework.web.context.ContextLoaderListener;
 
+import javax.servlet.ServletContextEvent;
+
 /**
  * @author Werner Punz (latest modification by $Author$)
  * @version $Revision$ $Date$
@@ -29,15 +31,40 @@
 
 public class CompilationAwareContextLoaderListener extends ContextLoaderListener
 {
+
+    public CompilationAwareContextLoaderListener()
+    {
+        super();
+    }
+
+    @Override
+    public void contextInitialized(ServletContextEvent event)
+    {
+        super.contextInitialized(event);
+    }
+
+    @Override
+    public ContextLoader getContextLoader()
+    {
+        return super.getContextLoader();
+    }
+
+    @Override
+    public void contextDestroyed(ServletContextEvent event)
+    {
+        super.contextDestroyed(event);
+    }
+
     /**
-        * <p>Creates the context loader to use. Note that actually the context loader
-        * starts up the web application context, this listener just delgates
-        * to it.</p>
-        *
-        * @return the context loader to use to start up the web appplication context
-        */
-       @Override
-       protected ContextLoader createContextLoader() {
-           return new CompilationAwareContextLoader();
-       }
+     * <p>Creates the context loader to use. Note that actually the context loader
+     * starts up the web application context, this listener just delgates
+     * to it.</p>
+     *
+     * @return the context loader to use to start up the web appplication context
+     */
+    @Override
+    protected ContextLoader createContextLoader()
+    {
+        return new CompilationAwareContextLoader();
+    }
 }
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareXmlWebApplicationContext.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareXmlWebApplicationContext.java
new file mode 100644
index 0000000..fcadf75
--- /dev/null
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/CompilationAwareXmlWebApplicationContext.java
@@ -0,0 +1,57 @@
+/*
+ * 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.myfaces.extensions.scripting.spring.context;
+
+import org.apache.myfaces.extensions.scripting.spring.bean.CompilationAwareRefreshableBeanFactory;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+
+/**
+ * @author Werner Punz (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+
+public class CompilationAwareXmlWebApplicationContext extends XmlWebApplicationContext
+{
+    public CompilationAwareXmlWebApplicationContext()
+    {
+        super();
+    }
+
+    /**
+     * Create an internal bean factory for this context.
+     * Called for each {@link #refresh()} attempt.
+     * <p>The default implementation creates a
+     * {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
+     * with the {@link #getInternalParentBeanFactory() internal bean factory} of this
+     * context's parent as parent bean factory. Can be overridden in subclasses,
+     * for example to customize DefaultListableBeanFactory's settings.
+     *
+     * @return the bean factory for this context
+     * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
+     * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowEagerClassLoading
+     * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowCircularReferences
+     * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
+     */
+    protected DefaultListableBeanFactory createBeanFactory()
+    {
+        return new CompilationAwareRefreshableBeanFactory(getInternalParentBeanFactory());
+    }
+}
diff --git a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/ReloadingListener.java b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/ReloadingListener.java
index d928341..23da7f1 100644
--- a/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/ReloadingListener.java
+++ b/extscript-core-root/extscript-spring/src/main/java/org/apache/myfaces/extensions/scripting/spring/context/ReloadingListener.java
@@ -21,12 +21,7 @@
 
 import org.apache.myfaces.extensions.scripting.core.api.eventhandling.WeavingEvent;
 import org.apache.myfaces.extensions.scripting.core.api.eventhandling.WeavingEventListener;
-import org.apache.myfaces.extensions.scripting.core.api.eventhandling.events.RefreshBeginEvent;
-import org.apache.myfaces.extensions.scripting.core.api.eventhandling.events.TaintedEvent;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletContextEvent;
-import javax.servlet.http.HttpServletRequest;
+import org.springframework.web.context.ConfigurableWebApplicationContext;
 
 /**
  * @author Werner Punz (latest modification by $Author$)
@@ -35,6 +30,13 @@
 
 public class ReloadingListener implements WeavingEventListener
 {
+    ConfigurableWebApplicationContext appContext = null;
+
+    public ReloadingListener(ConfigurableWebApplicationContext applicationContext)
+    {
+        appContext = applicationContext;
+    }
+
     @Override
     public void onEvent(WeavingEvent evt)
     {
diff --git a/extscript-examples/spring-example/src/main/java/org/apache/myfaces/extension/scripting/spring/example/Greeter.java b/extscript-examples/spring-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/extension/scripting/spring/example/Greeter.java
similarity index 100%
rename from extscript-examples/spring-example/src/main/java/org/apache/myfaces/extension/scripting/spring/example/Greeter.java
rename to extscript-examples/spring-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/extension/scripting/spring/example/Greeter.java
diff --git a/extscript-examples/spring-example/src/main/java/org/apache/myfaces/extension/scripting/spring/example/Person.java b/extscript-examples/spring-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/extension/scripting/spring/example/Person.java
similarity index 100%
rename from extscript-examples/spring-example/src/main/java/org/apache/myfaces/extension/scripting/spring/example/Person.java
rename to extscript-examples/spring-example/src/main/webapp/WEB-INF/java/org/apache/myfaces/extension/scripting/spring/example/Person.java
diff --git a/extscript-examples/spring-example/src/main/webapp/WEB-INF/web.xml b/extscript-examples/spring-example/src/main/webapp/WEB-INF/web.xml
index 41ac8a4..b5d0c7a 100644
--- a/extscript-examples/spring-example/src/main/webapp/WEB-INF/web.xml
+++ b/extscript-examples/spring-example/src/main/webapp/WEB-INF/web.xml
@@ -24,6 +24,15 @@
          version="3.0">
 
     <context-param>
+        <description>
+            Initializes the plugins for our scripting handlers
+        </description>
+        <param-name>org.apache.myfaces.FACES_INIT_PLUGINS</param-name>
+        <param-value>org.apache.myfaces.extensions.scripting.jsf.startup.StartupServletContextPluginChainLoader
+        </param-value>
+    </context-param>
+
+    <context-param>
         <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
         <param-value>server</param-value>
     </context-param>