You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/10/28 01:42:19 UTC

svn commit: r589241 - in /tapestry/tapestry5/trunk/tapestry-ioc/src: main/java/org/apache/tapestry/ioc/ main/java/org/apache/tapestry/ioc/annotations/ main/java/org/apache/tapestry/ioc/internal/ main/java/org/apache/tapestry/ioc/services/ site/apt/ tes...

Author: hlship
Date: Sat Oct 27 16:42:16 2007
New Revision: 589241

URL: http://svn.apache.org/viewvc?rev=589241&view=rev
Log:
TAPESTRY-1829: Allow @Marker annotation on module classes, to automatically mark all services of that module with the annotation

Added:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Builtin.java
Modified:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/module.apt
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java Sat Oct 27 16:42:16 2007
@@ -55,5 +55,16 @@
      */
     ServiceBindingOptions eagerLoad();
 
+    /**
+     * Defines the marker interface for the service, used to connect injections by type at the point
+     * of injection with a particular service implementation, based on the intersection of type and
+     * marker interface. The containing module will sometimes provide a default marker interface for
+     * all services within the module, this method allows that default to be overridden (typically a
+     * different marker annotation, but sometimes to null).
+     * 
+     * @param <T>
+     * @param marker
+     * @return this binding options, for further configuration
+     */
     <T extends Annotation> ServiceBindingOptions withMarker(Class<T> marker);
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java Sat Oct 27 16:42:16 2007
@@ -29,6 +29,9 @@
  * implementation. This allows for injection based on the combination of type and marker interface.
  * These marker interfaces should not have any values. The mere presence of the marker annotation is
  * all that is needed.
+ * <p>
+ * When applied to a module class, this sets the default marker for all services within the module
+ * (whereas the normal default marker is null).
  */
 @Target(
 { TYPE, METHOD })

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java Sat Oct 27 16:42:16 2007
@@ -84,6 +84,8 @@
 
     private final static Map<Class, ConfigurationType> PARAMETER_TYPE_TO_CONFIGURATION_TYPE = newMap();
 
+    private final Class _defaultMarker;
+
     static
     {
         PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Configuration.class, UNORDERED);
@@ -98,12 +100,16 @@
      * @param classFactory
      *            TODO
      */
-    public DefaultModuleDefImpl(Class builderClass, Logger logger, ClassFactory classFactory)
+    public DefaultModuleDefImpl(Class<?> builderClass, Logger logger, ClassFactory classFactory)
     {
         _builderClass = builderClass;
         _logger = logger;
         _classFactory = classFactory;
 
+        Marker annotation = builderClass.getAnnotation(Marker.class);
+
+        _defaultMarker = annotation != null ? annotation.value() : null;
+
         grind();
         bind();
     }
@@ -325,7 +331,10 @@
     {
         Marker annotation = method.getAnnotation(Marker.class);
 
-        return annotation == null ? null : annotation.value();
+        // Use the annotation value if present, otherwise use the module's default
+        // (from the module class's annotation, or null if no annotation there).
+
+        return annotation == null ? _defaultMarker : annotation.value();
     }
 
     public void addServiceDef(ServiceDef serviceDef)
@@ -384,7 +393,7 @@
                 return;
             }
 
-            ServiceBinderImpl binder = new ServiceBinderImpl(this, _classFactory);
+            ServiceBinderImpl binder = new ServiceBinderImpl(this, _classFactory, _defaultMarker);
 
             bindMethod.invoke(null, binder);
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java Sat Oct 27 16:42:16 2007
@@ -50,6 +50,7 @@
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.internal.util.OneShotLock;
 import org.apache.tapestry.ioc.internal.util.Orderer;
+import org.apache.tapestry.ioc.services.Builtin;
 import org.apache.tapestry.ioc.services.ClassFab;
 import org.apache.tapestry.ioc.services.ClassFabUtils;
 import org.apache.tapestry.ioc.services.ClassFactory;
@@ -61,7 +62,6 @@
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.TapestryIOCModule;
 import org.apache.tapestry.ioc.services.ThreadCleanupHub;
-import org.apache.tapestry.ioc.services.TapestryIOCModule.Builtin;
 import org.apache.tapestry.services.MasterObjectProvider;
 import org.slf4j.Logger;
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java Sat Oct 27 16:42:16 2007
@@ -41,10 +41,14 @@
 
     private final ClassFactory _classFactory;
 
-    public ServiceBinderImpl(ServiceDefAccumulator accumulator, ClassFactory classFactory)
+    private final Class _defaultMarker;
+
+    public ServiceBinderImpl(ServiceDefAccumulator accumulator, ClassFactory classFactory,
+            Class defaultMarker)
     {
         _accumulator = accumulator;
         _classFactory = classFactory;
+        _defaultMarker = defaultMarker;
     }
 
     private String _serviceId;
@@ -92,7 +96,7 @@
 
         _serviceId = null;
         _serviceInterface = null;
-        _marker = null;
+        _marker = _defaultMarker;
         _serviceImplementation = null;
         _eagerLoad = false;
         _scope = null;
@@ -138,7 +142,7 @@
 
         Marker marker = serviceImplementation.getAnnotation(Marker.class);
 
-        _marker = marker != null ? marker.value() : null;
+        _marker = marker != null ? marker.value() : _defaultMarker;
 
         return this;
     }
@@ -176,8 +180,6 @@
 
     public <T extends Annotation> ServiceBindingOptions withMarker(Class<T> marker)
     {
-        notNull(marker, "marker");
-
         _lock.check();
 
         _marker = marker;

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Builtin.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Builtin.java?rev=589241&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Builtin.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/Builtin.java Sat Oct 27 16:42:16 2007
@@ -0,0 +1,24 @@
+package org.apache.tapestry.ioc.services;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks services provided by this module that may need to be unambiguously referenced.
+ * Injecting with this marker annotation and the correct type ensure that the version defined in
+ * this module is used, even if another module provides a service with the same service
+ * interface.
+ */
+@Target(
+{ PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface Builtin
+{
+
+}
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Sat Oct 27 16:42:16 2007
@@ -14,15 +14,9 @@
 
 package org.apache.tapestry.ioc.services;
 
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import static org.apache.tapestry.ioc.IOCConstants.PERTHREAD_SCOPE;
 
 import java.io.File;
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -66,48 +60,27 @@
 /**
  * Defines the base set of services for the Tapestry IOC container.
  */
+@Marker(Builtin.class)
 public final class TapestryIOCModule
 {
-
-    /**
-     * Marks services provided by this module that may need to be unambiguously referenced.
-     * Injecting with this marker annotation and the correct type ensure that the version defined in
-     * this module is used, even if another module provides a service with the same service
-     * interface.
-     */
-    @Target(
-    { PARAMETER, FIELD })
-    @Retention(RUNTIME)
-    @Documented
-    public @interface Builtin
-    {
-
-    };
-
     public static void bind(ServiceBinder binder)
     {
-        binder.bind(LoggingDecorator.class, LoggingDecoratorImpl.class).withMarker(Builtin.class);
-        binder.bind(ChainBuilder.class, ChainBuilderImpl.class).withMarker(Builtin.class);
-        binder.bind(PropertyAccess.class, PropertyAccessImpl.class).withMarker(Builtin.class);
-        binder.bind(StrategyBuilder.class, StrategyBuilderImpl.class).withMarker(Builtin.class);
-        binder.bind(PropertyShadowBuilder.class, PropertyShadowBuilderImpl.class).withMarker(
-                Builtin.class);
-        binder.bind(PipelineBuilder.class, PipelineBuilderImpl.class).withMarker(Builtin.class);
-        binder.bind(DefaultImplementationBuilder.class, DefaultImplementationBuilderImpl.class)
-                .withMarker(Builtin.class);
-        binder.bind(ExceptionTracker.class, ExceptionTrackerImpl.class).withMarker(Builtin.class);
-        binder.bind(ExceptionAnalyzer.class, ExceptionAnalyzerImpl.class).withMarker(Builtin.class);
-        binder.bind(TypeCoercer.class, TypeCoercerImpl.class).withMarker(Builtin.class);
-        binder.bind(ThreadLocale.class, ThreadLocaleImpl.class).withMarker(Builtin.class);
-        binder.bind(SymbolSource.class, SymbolSourceImpl.class).withMarker(Builtin.class);
-        binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("ApplicationDefaults")
-                .withMarker(Builtin.class);
-        binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("FactoryDefaults")
-                .withMarker(Builtin.class);
-        binder.bind(Runnable.class, RegistryStartup.class).withId("RegistryStartup").withMarker(
-                Builtin.class);
-        binder.bind(MasterObjectProvider.class, MasterObjectProviderImpl.class).withMarker(
-                Builtin.class);
+        binder.bind(LoggingDecorator.class, LoggingDecoratorImpl.class);
+        binder.bind(ChainBuilder.class, ChainBuilderImpl.class);
+        binder.bind(PropertyAccess.class, PropertyAccessImpl.class);
+        binder.bind(StrategyBuilder.class, StrategyBuilderImpl.class);
+        binder.bind(PropertyShadowBuilder.class, PropertyShadowBuilderImpl.class);
+        binder.bind(PipelineBuilder.class, PipelineBuilderImpl.class);
+        binder.bind(DefaultImplementationBuilder.class, DefaultImplementationBuilderImpl.class);
+        binder.bind(ExceptionTracker.class, ExceptionTrackerImpl.class);
+        binder.bind(ExceptionAnalyzer.class, ExceptionAnalyzerImpl.class);
+        binder.bind(TypeCoercer.class, TypeCoercerImpl.class);
+        binder.bind(ThreadLocale.class, ThreadLocaleImpl.class);
+        binder.bind(SymbolSource.class, SymbolSourceImpl.class);
+        binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("ApplicationDefaults");
+        binder.bind(SymbolProvider.class, MapSymbolProvider.class).withId("FactoryDefaults");
+        binder.bind(Runnable.class, RegistryStartup.class).withId("RegistryStartup");
+        binder.bind(MasterObjectProvider.class, MasterObjectProviderImpl.class);
     }
 
     /**
@@ -116,7 +89,6 @@
      * proxiable services (those with explicit service interfaces) can be managed in terms of a
      * lifecycle.
      */
-    @Marker(Builtin.class)
     public static ServiceLifecycleSource build(final Map<String, ServiceLifecycle> configuration)
     {
         return new ServiceLifecycleSource()

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/module.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/module.apt?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/module.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/module.apt Sat Oct 27 16:42:16 2007
@@ -18,6 +18,8 @@
   * To <decorate> services by providing <interceptors> around them
 
   * To provide explicit code for building a service
+  
+  * To set a default <marker> for all services defined in the module
 
   []
 
@@ -264,4 +266,36 @@
   You don't <have> to define your methods as static. The use of static methods is only absolutely
   necessary in a few cases, where the constructor for a module is dependent on contributions
   from the same module (this creates a chicken-and-the-egg situation that is resolved through
-  static methods).
\ No newline at end of file
+  static methods).
+  
+Default Marker
+
+  Services are often referenced by a particular marker interface on the method or contructor parameter. Tapestry
+  will use the intersection of services with that exact marker and assignable by type to find a unique service
+  to inject.  
+  
+  Often, all services in a module should share a marker, this can be specified with a @Marker annotation
+  on the module class.  For example, the TapestryIOCModule:
+  
++---+
+@Marker(Builtin.class)
+public final class TapestryIOCModule
+{
+  . . .
++---+
+
+  This references a particular annotation class, Builtin:
+  
++---+
+@Target(
+{ PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface Builtin
+{
+
+}
++----+
+
+  The annotation can be applied to method and constructor parameters, for use within the IoC container.  It can also be applied
+  to fields, though this is specific to the Tapestry web framework.

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java?rev=589241&r1=589240&r2=589241&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java Sat Oct 27 16:42:16 2007
@@ -23,11 +23,11 @@
 
 import org.apache.tapestry.ioc.internal.ExceptionInConstructorModule;
 import org.apache.tapestry.ioc.internal.IOCInternalTestCase;
+import org.apache.tapestry.ioc.services.Builtin;
 import org.apache.tapestry.ioc.services.ServiceActivity;
 import org.apache.tapestry.ioc.services.ServiceActivityScoreboard;
 import org.apache.tapestry.ioc.services.Status;
 import org.apache.tapestry.ioc.services.TypeCoercer;
-import org.apache.tapestry.ioc.services.TapestryIOCModule.Builtin;
 import org.testng.Assert;
 import org.testng.annotations.Test;