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. + */ [EMAIL PROTECTED]( +{ PARAMETER, FIELD }) [EMAIL PROTECTED](RUNTIME) [EMAIL PROTECTED] +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. */ [EMAIL PROTECTED](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: + ++---+ [EMAIL PROTECTED](Builtin.class) +public final class TapestryIOCModule +{ + . . . ++---+ + + This references a particular annotation class, Builtin: + ++---+ [EMAIL PROTECTED]( +{ PARAMETER, FIELD }) [EMAIL PROTECTED](RUNTIME) [EMAIL PROTECTED] +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;