Author: hlship
Date: Mon May  7 18:24:01 2007
New Revision: 536037

URL: http://svn.apache.org/viewvc?view=rev&rev=536037
Log:
Support a more seamless approach to integrating Tapestry with Spring.

Added:
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/TapestrySpringFilter.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringFilterTest.java
Removed:
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringBean.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringModule.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringObjectProvider.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/SampleBean.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/SpringModuleTest.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/SpringObjectProviderTest.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/example/testapp/services/AppModule.java
Modified:
    tapestry/tapestry5/branches/hlship-20070503/tapestry-core/.classpath
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/TapestryFilter.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/src/site/apt/index.apt
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/support/new-project.rb
    tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/   (props 
changed)
    tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/.classpath
    tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/pom.xml
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringMessages.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/resources/org/apache/tapestry/spring/SpringStrings.properties
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/site/apt/index.apt
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringIntegrationTest.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/example/testapp/pages/Start.java
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/Start.html
    
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/web.xml

Modified: tapestry/tapestry5/branches/hlship-20070503/tapestry-core/.classpath
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-core/.classpath?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- tapestry/tapestry5/branches/hlship-20070503/tapestry-core/.classpath 
(original)
+++ tapestry/tapestry5/branches/hlship-20070503/tapestry-core/.classpath Mon 
May  7 18:24:01 2007
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="lib" path="src/main/resources"/>
-       <classpathentry kind="src" path="src/test/java"/>
-       <classpathentry kind="lib" path="src/test/resources"/>
-       <classpathentry kind="lib" path="src/test/conf"/>
-       <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-       <classpathentry kind="con" 
path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
-       <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src/main/java"/>
+       <classpathentry kind="lib" path="src/main/resources"/>
+       <classpathentry kind="src" output="bin-test" path="src/test/java"/>
+       <classpathentry kind="lib" path="src/test/resources"/>
+       <classpathentry kind="lib" path="src/test/conf"/>
+       <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+       <classpathentry kind="con" 
path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/TapestryFilter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/TapestryFilter.java?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/TapestryFilter.java
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/TapestryFilter.java
 Mon May  7 18:24:01 2007
@@ -32,13 +32,11 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.tapestry.internal.ServletContextSymbolProvider;
 import org.apache.tapestry.internal.TapestryAppInitializer;
-import org.apache.tapestry.ioc.IOCUtilities;
 import org.apache.tapestry.ioc.Registry;
-import org.apache.tapestry.ioc.RegistryBuilder;
+import org.apache.tapestry.ioc.def.ModuleDef;
 import org.apache.tapestry.ioc.services.SymbolProvider;
 import org.apache.tapestry.services.HttpServletRequestHandler;
 import org.apache.tapestry.services.ServletApplicationInitializer;
-import org.apache.tapestry.services.TapestryModule;
 
 /**
  * The TapestryFilter is responsible for intercepting all requests into the 
web application. It
@@ -72,7 +70,7 @@
         SymbolProvider provider = new ServletContextSymbolProvider(context);
 
         TapestryAppInitializer appInitializer = new 
TapestryAppInitializer(provider, filterName,
-                "servlet");
+                "servlet", provideExtraModuleDefs(context));
 
         _registry = appInitializer.getRegistry();
 
@@ -97,17 +95,12 @@
     }
 
     /**
-     * Adds additional modules to the builder. This implementation adds any 
modules identified by
-     * [EMAIL PROTECTED] IOCUtilities#addDefaultModules(RegistryBuilder)}. 
Most subclasses will invoke this
-     * implementation, and add additional modules to the RegistryBuilder 
besides.
-     * [EMAIL PROTECTED] org.apache.tapestry.ioc.services.TapestryIOCModule} 
and [EMAIL PROTECTED] TapestryModule} will
-     * already have been added, as will an application module if present.
-     * 
-     * @param builder
+     * Overridden in subclasses to provide additional module definitions 
beyond those normally
+     * located. This implementation returns an empty array.
      */
-    protected void addModules(RegistryBuilder builder)
+    protected ModuleDef[] provideExtraModuleDefs(ServletContext context)
     {
-        IOCUtilities.addDefaultModules(builder);
+        return new ModuleDef[0];
     }
 
     public final void doFilter(ServletRequest request, ServletResponse 
response, FilterChain chain)
@@ -129,6 +122,7 @@
 
     /** Shuts down and discards the registry. */
     public final void destroy()
+    
     {
         _registry.shutdown();
 

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java
 Mon May  7 18:24:01 2007
@@ -21,9 +21,12 @@
 import org.apache.tapestry.ioc.Registry;
 import org.apache.tapestry.ioc.RegistryBuilder;
 import org.apache.tapestry.ioc.def.ContributionDef;
+import org.apache.tapestry.ioc.def.ModuleDef;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.services.SymbolProvider;
+import org.apache.tapestry.services.Alias;
 import org.apache.tapestry.services.TapestryModule;
+import org.apache.tapestry.test.pagelevel.PageTester;
 
 /**
  * This class is used to build the [EMAIL PROTECTED] Registry}. The Registry 
contains
@@ -59,13 +62,27 @@
                 appName, aliasMode);
     }
 
-    public TapestryAppInitializer(SymbolProvider appProvider, String appName, 
String aliasMode)
+    public TapestryAppInitializer(SymbolProvider appProvider, String appName, 
String aliasMode,
+            ModuleDef... moduleDefs)
     {
-        this(appProvider, appName, aliasMode, null);
+        this(appProvider, appName, aliasMode, null, moduleDefs);
     }
 
+    /**
+     * @param appProvider
+     *            provides symbols for the application (normally, from the 
ServletContext init
+     *            parameters)
+     * @param appName
+     *            the name of the application (i.e., the name of the 
application servlet)
+     * @param aliasMode
+     *            the mode, used by the [EMAIL PROTECTED] Alias} service, 
normally "servlet"
+     * @param serviceOverrides
+     *            specific service overrides (used by [EMAIL PROTECTED] 
PageTester}
+     * @param moduleDefs
+     *            additional module definitions to be mixed in to those 
automatically located
+     */
     public TapestryAppInitializer(SymbolProvider appProvider, String appName, 
String aliasMode,
-            Map<String, Object> serviceOverrides)
+            Map<String, Object> serviceOverrides, ModuleDef... moduleDefs)
     {
         _appProvider = appProvider;
 
@@ -77,12 +94,12 @@
 
         _startTime = System.currentTimeMillis();
 
-        _registry = createRegistry();
+        _registry = createRegistry(moduleDefs);
 
         _registryCreatedTime = System.currentTimeMillis();
     }
 
-    private Registry createRegistry()
+    private Registry createRegistry(ModuleDef... moduleDefs)
     {
         RegistryBuilder builder = new RegistryBuilder();
 
@@ -108,14 +125,21 @@
 
         addModules(builder);
 
-        addSyntheticModules(builder);
+        // Add any explicitly provided module defs
+
+        for (ModuleDef def : moduleDefs)
+            builder.add(def);
+
+        // Add a synthetic module that contributes symbol sources.
+
+        addSyntheticSymbolSourceModule(builder);
 
         overrideServices(builder);
 
         return builder.build();
     }
 
-    private void addSyntheticModules(RegistryBuilder builder)
+    private void addSyntheticSymbolSourceModule(RegistryBuilder builder)
     {
         ContributionDef symbolSourceContribution = new 
SyntheticSymbolSourceContributionDef(
                 "ServletContext", _appProvider, "before:ApplicationDefaults");

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-core/src/main/java/org/apache/tapestry/test/pagelevel/PageTester.java
 Mon May  7 18:24:01 2007
@@ -114,7 +114,7 @@
                 InternalConstants.TAPESTRY_APP_PACKAGE_PARAM, appPackage);
 
         _registry = new TapestryAppInitializer(provider, appName, "test",
-                addDefaultOverrides(serviceOverrides)).getRegistry();
+                addDefaultOverrides(serviceOverrides), null).getRegistry();
 
         _localizationSetter = _registry.getService("LocalizationSetter", 
LocalizationSetter.class);
 

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/src/site/apt/index.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-project/src/site/apt/index.apt?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/src/site/apt/index.apt
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/src/site/apt/index.apt
 Mon May  7 18:24:01 2007
@@ -94,6 +94,9 @@
   
 New and Noteworthy
 
+  The {{{tapestry-spring/tapestry-spring}} module has also been simplified, to 
make
+  Spring beans look like Tapestry IoC services. It's all now quite seamless.
+
   The {{{tapestry-ioc/}tapestry-ioc}} module has been simplified, removing the 
concept
   of module ids and namespaces, as well as private services, and borrowing a 
lot of cool
   ideas from {{{http://code.google.com/p/google-guice/}Guice}}. The goal is to 
make the container

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/support/new-project.rb
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-project/support/new-project.rb?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/support/new-project.rb
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-project/support/new-project.rb
 Mon May  7 18:24:01 2007
@@ -6,7 +6,7 @@
 $artifact = nil
 $package = nil
 $version = "1.0.0-SNAPSHOT"
-$archetypeVersion = "5.0.4-SNAPSHOT"
+$archetypeVersion = "5.0.4"
 $offline = false
 
 $opts = OptionParser.new do |opts|

Propchange: tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon May  7 18:24:01 2007
@@ -3,3 +3,4 @@
 temp-testng-customsuite.xml
 cobertura.ser
 null
+bin-test

Modified: tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/.classpath
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/.classpath?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/.classpath 
(original)
+++ tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/.classpath Mon 
May  7 18:24:01 2007
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="src" path="src/test/java"/>
+       <classpathentry kind="src" output="bin-test" path="src/test/java"/>
        <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="con" 
path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
        <classpathentry kind="lib" path="src/main/resources"/>

Modified: tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/pom.xml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/pom.xml?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/pom.xml 
(original)
+++ tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/pom.xml Mon May 
 7 18:24:01 2007
@@ -31,6 +31,10 @@
       <version>1.2.8</version>
       <scope>provided</scope>
     </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.easymock</groupId>
@@ -67,19 +71,6 @@
           </execution>
         </executions>
       </plugin>
-
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <configuration>
-          <archive>
-            <manifestEntries>
-              
<Tapestry-Module-Classes>org.apache.tapestry.spring.SpringModule</Tapestry-Module-Classes>
-            </manifestEntries>
-          </archive>
-        </configuration>
-      </plugin>
-
     </plugins>
   </build>
   <reporting>
@@ -115,15 +106,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-report-plugin</artifactId>
-      </plugin>
-
-      <plugin>
-        <groupId>org.apache.tapestry</groupId>
-        <artifactId>tapestry-component-report</artifactId>
-        <version>5.0.2</version>
-        <configuration>
-          <rootPackage>org.apache.tapestry.corelib</rootPackage>
-        </configuration>
       </plugin>
     </plugins>
   </reporting>

Added: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java?view=auto&rev=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java
 (added)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java
 Mon May  7 18:24:01 2007
@@ -0,0 +1,151 @@
+package org.apache.tapestry.internal.spring;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry.ioc.IOCConstants;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
+import org.apache.tapestry.ioc.def.ContributionDef;
+import org.apache.tapestry.ioc.def.DecoratorDef;
+import org.apache.tapestry.ioc.def.ModuleDef;
+import org.apache.tapestry.ioc.def.ServiceDef;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import org.springframework.beans.factory.BeanFactoryUtils;
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * A wrapper that converts a Spring [EMAIL PROTECTED] WebApplicationContext} 
into a set of service definitions,
+ * compatible with Tapestry 5 IoC, for the beans defined in the context, as 
well as the context
+ * itself.
+ */
+public class SpringModuleDef implements ModuleDef
+{
+    private static final String CONTEXT_SERVICE_ID = 
WebApplicationContext.class.getSimpleName();
+
+    private final WebApplicationContext _context;
+
+    private final Map<String, ServiceDef> _serviceDefs = 
CollectionFactory.newCaseInsensitiveMap();
+
+    public SpringModuleDef(final WebApplicationContext context)
+    {
+        _context = context;
+
+        for (final String beanName : 
BeanFactoryUtils.beanNamesIncludingAncestors(_context))
+        {
+            ServiceDef serviceDef = new ServiceDef()
+            {
+                private Object getBean()
+                {
+                    return _context.getBean(beanName);
+                }
+
+                public ObjectCreator 
createServiceCreator(ServiceBuilderResources resources)
+                {
+                    return new ObjectCreator()
+                    {
+                        public Object createObject()
+                        {
+                            return getBean();
+                        }
+                    };
+                }
+
+                public String getServiceId()
+                {
+                    return beanName;
+                }
+
+                public Class getServiceInterface()
+                {
+                    return getBean().getClass();
+                }
+
+                public String getServiceScope()
+                {
+                    return IOCConstants.DEFAULT_SCOPE;
+                }
+
+                public boolean isEagerLoad()
+                {
+                    return false;
+                }
+            };
+
+            _serviceDefs.put(beanName, serviceDef);
+        }
+
+        // And add one service that is the Spring WebApplicationContext.
+
+        ServiceDef serviceDef = new ServiceDef()
+        {
+
+            public ObjectCreator createServiceCreator(ServiceBuilderResources 
resources)
+            {
+                return new ObjectCreator()
+                {
+                    public Object createObject()
+                    {
+                        return _context;
+                    }
+                };
+            }
+
+            public String getServiceId()
+            {
+                return CONTEXT_SERVICE_ID;
+            }
+
+            public Class getServiceInterface()
+            {
+                return WebApplicationContext.class;
+            }
+
+            public String getServiceScope()
+            {
+                return IOCConstants.DEFAULT_SCOPE;
+            }
+
+            public boolean isEagerLoad()
+            {
+                return false;
+            }
+        };
+
+        _serviceDefs.put(CONTEXT_SERVICE_ID, serviceDef);
+    }
+
+    public Class getBuilderClass()
+    {
+        return null;
+    }
+
+    /** Returns an empty set. */
+    public Set<ContributionDef> getContributionDefs()
+    {
+        return Collections.emptySet();
+    }
+
+    /** Returns an empty set. */
+    public Set<DecoratorDef> getDecoratorDefs()
+    {
+        return Collections.emptySet();
+    }
+
+    public String getLogName()
+    {
+        return "Spring";
+    }
+
+    public ServiceDef getServiceDef(String serviceId)
+    {
+        return _serviceDefs.get(serviceId);
+    }
+
+    public Set<String> getServiceIds()
+    {
+        return _serviceDefs.keySet();
+    }
+
+}

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringMessages.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringMessages.java?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringMessages.java
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/SpringMessages.java
 Mon May  7 18:24:01 2007
@@ -14,34 +14,21 @@
 
 package org.apache.tapestry.spring;
 
-import java.util.Collection;
-
 import org.apache.tapestry.ioc.Messages;
-import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.internal.util.MessagesImpl;
 import org.springframework.web.context.ContextLoaderListener;
 
 class SpringMessages
 {
-  private static final Messages MESSAGES = 
MessagesImpl.forClass(SpringMessages.class);
-
-  static String failureObtainingContext(Throwable cause)
-  {
-    return MESSAGES.format("failure-obtaining-context", cause);
-  }
-
-  static String missingContext()
-  {
-    return MESSAGES.format("missing-context", 
ContextLoaderListener.class.getName());
-  }
-
-  static String contextStartup(Collection<String> beanNames)
-  {
-    return MESSAGES.format("context-startup", 
InternalUtils.joinSorted(beanNames));
-  }
+    private static final Messages MESSAGES = 
MessagesImpl.forClass(SpringMessages.class);
 
-  static String beanAccessFailure(String beanName, Class beanType, Throwable 
cause)
-  {
-    return MESSAGES.format("bean-access-failure", beanName, 
beanType.getName(), cause);
-  }
+    static String failureObtainingContext(Throwable cause)
+    {
+        return MESSAGES.format("failure-obtaining-context", cause);
+    }
+
+    static String missingContext()
+    {
+        return MESSAGES.format("missing-context", 
ContextLoaderListener.class.getName());
+    }
 }

Added: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/TapestrySpringFilter.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/TapestrySpringFilter.java?view=auto&rev=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/TapestrySpringFilter.java
 (added)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/java/org/apache/tapestry/spring/TapestrySpringFilter.java
 Mon May  7 18:24:01 2007
@@ -0,0 +1,37 @@
+package org.apache.tapestry.spring;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tapestry.TapestryFilter;
+import org.apache.tapestry.internal.spring.SpringModuleDef;
+import org.apache.tapestry.ioc.def.ModuleDef;
+import org.springframework.web.context.WebApplicationContext;
+
+/**
+ * Adds a [EMAIL PROTECTED] ModuleDef} that contains all the beans defined by 
the Spring
+ * [EMAIL PROTECTED] WebApplicationContext}, as if they were Tapestry IoC 
services.
+ */
+public class TapestrySpringFilter extends TapestryFilter
+{
+
+    @Override
+    protected ModuleDef[] provideExtraModuleDefs(ServletContext context)
+    {
+        WebApplicationContext springContext = null;
+
+        try
+        {
+            springContext = (WebApplicationContext) context
+                    
.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
+        }
+        catch (Exception ex)
+        {
+            throw new 
RuntimeException(SpringMessages.failureObtainingContext(ex), ex);
+        }
+
+        if (springContext == null) throw new 
RuntimeException(SpringMessages.missingContext());
+
+        return new ModuleDef[]
+        { new SpringModuleDef(springContext) };
+    }
+}

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/resources/org/apache/tapestry/spring/SpringStrings.properties
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/resources/org/apache/tapestry/spring/SpringStrings.properties?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/resources/org/apache/tapestry/spring/SpringStrings.properties
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/main/resources/org/apache/tapestry/spring/SpringStrings.properties
 Mon May  7 18:24:01 2007
@@ -14,5 +14,3 @@
 
 failure-obtaining-context=An exception occurred obtaining the Spring 
WebApplicationContext: %s
 missing-context=The Spring WebApplicationContext is not present. The likely 
cause is that the %s listener was not declared inside the application's web.xml 
deployment descriptor.
-context-startup=Using Spring WebApplicationContext containing beans: %s
-bean-access-failure=A failure occured obtaining Spring bean '%s' (of type %s): 
%s

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/site/apt/index.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/site/apt/index.apt?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/site/apt/index.apt
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/site/apt/index.apt
 Mon May  7 18:24:01 2007
@@ -34,7 +34,20 @@
   
 * web.xml changes
   
-  The short form is that you must make a small change to your application's 
web.xml:
+  The short form is that you must make two small changes to your application's 
web.xml.
+  
+  First, a special filter is used in replace of the standard TapestryFilter:
+  
++---+
+  <filter>
+    <filter-name>app</filter-name>
+    <!-- Special filter that adds in a T5 IoC module derived from the Spring 
WebApplicationContext. -->
+    
<filter-class>org.apache.tapestry.spring.TapestrySpringFilter</filter-class>
+  </filter>
++---+  
+ 
+   Secondly, you must add the normal Spring configuration, consisting of a 
\<listener\> element,
+   and (optionally) a \<context-param\> identifying which Spring bean 
configuration file(s) to load:
  
 +---+
 <context-param>
@@ -55,30 +68,47 @@
 * Injecting beans
 
   Inside your component classes, you may use the 
-  
{{{http://tapestry.apache.org/tapestry5/tapestry-core/apidocs/org/apache/tapestry/annotations/Inject.html}Inject}}
 annotation in combination with
-  the {{{apidocs/org/apache/tapestry/spring/SpringBean.html}SpringBean}} 
annotation (to define the name of the bean).
+  
{{{http://tapestry.apache.org/tapestry5/tapestry-core/apidocs/org/apache/tapestry/annotations/Inject.html}Inject}}
 annotation.  Typically, just the field 
+  type is sufficient to identify the Spring bean to inject:
   
 +----+
   @Inject
-  @SpringBean("userDAO")
   private UserDAO _userDAO;
 +----+
 
-  This also works with parameters to service builder methods.
-
+  If you have multiple beans that implement the same interface (for instance, 
if you have wrapped your bean using a transaction interceptor), you must 
disambiguate.  The easiest way
+  to accomplish this is to add a 
+  
{{{http://tapestry.apache.org/tapestry5/tapestry-core/apidocs/org/apache/tapestry/annotations/Service.html}Service}}
+  annotation to identify the name of the
+  Spring bean:
+  
++----+
+  @Inject
+  @Service("UserDAO")
+  private UserDAO _userDAO;
++----+  
+  
+  Injection of Spring beans via service builder methods or autobuilding occurs 
just the same: the Spring beans masquerade as Tapestry IoC services and all is 
well.
+ 
 Case Insensitivity
 
-  At startup, the names of all the beans provided by the Spring application 
context is obtained and use to build a case-insensitive map.
-  When a bean is requested, it is filtered through this map to get the 
case-sensitive name required by Spring. The upshot of this is that
-  you should not have to be concerned with case: in the above example 
"Spring:UserDAO" or "SPRING:userdao" would work equally well.
+  Spring beans names are treated exactly as Tapestry IoC service ids.  Since 
service ids are case insensitive, access to Spring beans by bean name will also
+  be case insensitive.
+  
+WebApplicationContext Service
+
+  The Spring WebApplicationContext is also added as a service, in addition to 
any services defined within the context.
   
 Limitations
 
-  Case insensitivity is limited to beans whose names are available at 
application startup; it is possible to programatically add bean definitions
-  at runtime, but these will not be available case-insensitively (but using 
exactly matching case will still work).
+  The names of beans are obtained at application start up. If new beans are 
programattically added to the Spring application context at runtime,
+  these will not be visible for injection.
+  
+  Only the bean <name> is used, not any of the bean's <aliases>.
   
-  No check is made for name clashes that would occur when two beans have names 
that differ only in case.
+  No check is made for name clashes that would occur when two beans have names 
that differ only in terms of capitalization.  If you're going to go around 
naming beans "userDAO" and "UserDao",
+  you're just asking for trouble.
   
   Non-singleton beans are not handled properly. Tapestry will request the 
beans from the application context in a manner unsuitable for their lifecycle.
-  For the moment, you should consider the non-singleton beans to be 
not-injectable.  Instead, inject the tapestry.spring.WebApplicationContext 
service and
+  For the moment, you should consider the non-singleton beans to be 
not-injectable.  Instead, inject the WebApplicationContext service and
   obtain the non-singleton beans as needed.

Added: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringFilterTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringFilterTest.java?view=auto&rev=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringFilterTest.java
 (added)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringFilterTest.java
 Mon May  7 18:24:01 2007
@@ -0,0 +1,74 @@
+package org.apache.tapestry.spring;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tapestry.test.TapestryTestCase;
+import org.springframework.web.context.WebApplicationContext;
+import org.testng.annotations.Test;
+
+public class TapestrySpringFilterTest extends TapestryTestCase
+{
+    @Test
+    public void no_web_application_context_in_servlet_context() throws 
Exception
+    {
+        ServletContext context = mockServletContext();
+
+        
expect(context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE))
+                .andReturn(null);
+
+        replay();
+
+        TapestrySpringFilter filter = new TapestrySpringFilter();
+
+        try
+        {
+            filter.provideExtraModuleDefs(context);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "The Spring WebApplicationContext is not present. "
+                            + "The likely cause is that the 
org.springframework.web.context.ContextLoaderListener listener was not declared 
"
+                            + "inside the application\'s web.xml deployment 
descriptor.");
+        }
+
+        verify();
+    }
+
+    protected final ServletContext mockServletContext()
+    {
+        return newMock(ServletContext.class);
+    }
+
+    @Test
+    public void failure_obtaining_context() throws Exception
+    {
+        ServletContext context = mockServletContext();
+        Throwable t = new RuntimeException("Failure.");
+
+        
expect(context.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE))
+                .andThrow(t);
+
+        replay();
+
+        TapestrySpringFilter filter = new TapestrySpringFilter();
+
+        try
+        {
+            filter.provideExtraModuleDefs(context);
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(
+                    ex.getMessage(),
+                    "An exception occurred obtaining the Spring 
WebApplicationContext: Failure.");
+
+            assertSame(ex.getCause(), t);
+        }
+
+        verify();
+    }
+}

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringIntegrationTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringIntegrationTest.java?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringIntegrationTest.java
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/apache/tapestry/spring/TapestrySpringIntegrationTest.java
 Mon May  7 18:24:01 2007
@@ -19,14 +19,22 @@
 
 public class TapestrySpringIntegrationTest extends AbstractIntegrationTestSuite
 {
-  @Test
-  public void integration_test() throws Exception
-  {
-    open(BASE_URL);
+    @Test
+    public void integration_test() throws Exception
+    {
+        open(BASE_URL);
 
-    type("input", "paris in the springtime");
-    clickAndWait("//[EMAIL PROTECTED]'Convert']");
+        type("input", "paris in the springtime");
+        clickAndWait("//[EMAIL PROTECTED]'Convert']");
 
-    assertFieldValue("input", "PARIS IN THE SPRINGTIME");
-  }
+        assertFieldValue("input", "PARIS IN THE SPRINGTIME");
+    }
+
+    @Test
+    public void access_to_spring_context() throws Exception
+    {
+        open(BASE_URL);
+
+        assertTextPresent("[upcase]");
+    }
 }

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/example/testapp/pages/Start.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/example/testapp/pages/Start.java?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/example/testapp/pages/Start.java
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/java/org/example/testapp/pages/Start.java
 Mon May  7 18:24:01 2007
@@ -14,21 +14,26 @@
 
 package org.example.testapp.pages;
 
+import java.util.Arrays;
+
 import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.Retain;
-import org.apache.tapestry.spring.SpringBean;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.example.testapp.services.Upcase;
+import org.springframework.web.context.WebApplicationContext;
 
 public class Start
 {
     @Retain
     private String _input;
 
-    // Demonstrating case insensitivity
+    // We're matching on type here, just as we would a service provided in a 
T5 IoC module.
     @Inject
-    @SpringBean("Upcase")
     private Upcase _upcaseBean;
 
+    @Inject
+    private WebApplicationContext _context;
+
     void onSuccess()
     {
         _input = _upcaseBean.toUpperCase(_input);
@@ -42,6 +47,11 @@
     public void setInput(String input)
     {
         _input = input;
+    }
+
+    public String getSpringBeans()
+    {
+        return 
InternalUtils.join(Arrays.asList(_context.getBeanDefinitionNames()));
     }
 
 }

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/Start.html
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/Start.html?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/Start.html
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/Start.html
 Mon May  7 18:24:01 2007
@@ -13,5 +13,9 @@
       <br/>
       <input type="submit" value="Convert"/>
     </t:form>
+    
+    <p>
+      Spring beans: [${springBeans}]
+    </p>
   </body>
 </html>

Modified: 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/web.xml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/web.xml?view=diff&rev=536037&r1=536036&r2=536037
==============================================================================
--- 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/web.xml
 (original)
+++ 
tapestry/tapestry5/branches/hlship-20070503/tapestry-spring/src/test/webapp/WEB-INF/web.xml
 Mon May  7 18:24:01 2007
@@ -23,7 +23,8 @@
   </context-param>
   <filter>
     <filter-name>app</filter-name>
-    <filter-class>org.apache.tapestry.TapestryFilter</filter-class>
+    <!-- Special filter that adds in a T5 IoC module derived from the Spring 
WebApplicationContext. -->
+    
<filter-class>org.apache.tapestry.spring.TapestrySpringFilter</filter-class>
   </filter>
   <filter-mapping>
     <filter-name>app</filter-name>


Reply via email to