You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/07/07 20:28:46 UTC

svn commit: r961469 - in /tapestry/tapestry5/trunk: tapestry-annotations/src/main/java/org/apache/tapestry5/ioc/annotations/ tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ tapestry...

Author: hlship
Date: Wed Jul  7 18:28:45 2010
New Revision: 961469

URL: http://svn.apache.org/viewvc?rev=961469&view=rev
Log:
TAP5-1203: Use of @Contribute annotation does not work properly with marker annotations

Added:
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/GreenMarker.java
      - copied, changed from r961468, tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java
Modified:
    tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/ioc/annotations/Local.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ContributionDef2.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalRegistry.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/configuration.apt
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule2.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule3.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/RedMarker.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule2.java

Modified: tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/ioc/annotations/Local.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/ioc/annotations/Local.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/ioc/annotations/Local.java (original)
+++ tapestry/tapestry5/trunk/tapestry-annotations/src/main/java/org/apache/tapestry5/ioc/annotations/Local.java Wed Jul  7 18:28:45 2010
@@ -1,10 +1,10 @@
-//  Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 The Apache Software Foundation
 //
 // Licensed 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
+// 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,
@@ -16,12 +16,14 @@ package org.apache.tapestry5.ioc.annotat
 
 import java.lang.annotation.*;
 
-
 /**
  * A special marker annotation which limits the search for possible services to just the <em>same</em> module containing
- * the service being injected.  Other marker annotations may also be applied.
+ * the service being injected. Other marker annotations may also be applied. It is allowed on methods to
+ * support the @Contribute annotation (used as a preferred alternative to the older naming convention for
+ * identifying contribute methods and targetted services).
  */
-@Target({ElementType.PARAMETER, ElementType.FIELD})
+@Target(
+{ ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD })
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @UseWith(AnnotationUseContext.SERVICE)

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ContributionDef2.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ContributionDef2.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ContributionDef2.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ContributionDef2.java Wed Jul  7 18:28:45 2010
@@ -4,7 +4,7 @@
 // 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
+// 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,
@@ -18,26 +18,26 @@ import java.util.Set;
 import org.apache.tapestry5.ioc.annotations.Contribute;
 
 /**
- * Extended version of {@link org.apache.tapestry5.ioc.def.ContributionDef} introduced to determine any 
- * module method annotated with {@link Contribute} as a contributor method. As of version 5.2 a contribution 
+ * Extended version of {@link org.apache.tapestry5.ioc.def.ContributionDef} introduced to determine any
+ * module method annotated with {@link Contribute} as a contributor method. As of version 5.2 a contribution
  * identifies the service contributed either by the service id or by a combination of {@link Contribute} annotation and
- * a set of marker annotations. This means that {@link #getServiceId()} may to return <code>null</code> if {@link #getServiceInterface()}
- * returns a non <code>null</code> value.
- *
+ * a set of marker annotations. This means that {@link #getServiceId()} may to return <code>null</code> if
+ * {@link #getServiceInterface()} returns a non <code>null</code> value.
+ * 
  * @since 5.2.0
- *
  */
 public interface ContributionDef2 extends ContributionDef
 {
     /**
-     * Returns an optional <em>marker annotation</em>. Marker annotations are used to disambiguate services; the
-     * combination of a marker annotation and a service type is expected to be unique.
+     * Returns an optional set of <em>marker annotation</em>. Marker annotations are used to disambiguate services; the
+     * combination of a marker annotation and a service type is expected to be unique. Note that it is not possible
+     * to identify which annotations are markers and which are not when this set is contructed, so it may include
+     * non-marker annotations.
      * 
      * @see ServiceDef#getMarkers()
-     *
      */
     Set<Class> getMarkers();
-    
+
     /**
      * Returns the service interface associated with the service to contribute into.
      * 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java Wed Jul  7 18:28:45 2010
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry5.ioc.internal;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -25,6 +26,9 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.tapestry5.func.F;
+import org.apache.tapestry5.func.Mapper;
+import org.apache.tapestry5.func.Predicate;
 import org.apache.tapestry5.ioc.AdvisorDef;
 import org.apache.tapestry5.ioc.Configuration;
 import org.apache.tapestry5.ioc.MappedConfiguration;
@@ -95,27 +99,23 @@ public class DefaultModuleDefImpl implem
     /**
      * Keyed on decorator id.
      */
-    private final Map<String, DecoratorDef> decoratorDefs = CollectionFactory
-            .newCaseInsensitiveMap();
+    private final Map<String, DecoratorDef> decoratorDefs = CollectionFactory.newCaseInsensitiveMap();
 
     private final Map<String, AdvisorDef> advisorDefs = CollectionFactory.newCaseInsensitiveMap();
 
     private final Set<ContributionDef> contributionDefs = CollectionFactory.newSet();
-    
+
     private final Set<StartupDef> startupDefs = CollectionFactory.newSet();
 
     private final Set<Class> defaultMarkers = CollectionFactory.newSet();
 
-    private final static Set<Method> OBJECT_METHODS = CollectionFactory.newSet(Object.class
-            .getMethods());
+    private final static Set<Method> OBJECT_METHODS = CollectionFactory.newSet(Object.class.getMethods());
 
     static
     {
         PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Configuration.class, ConfigurationType.UNORDERED);
-        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(OrderedConfiguration.class,
-                ConfigurationType.ORDERED);
-        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(MappedConfiguration.class,
-                ConfigurationType.MAPPED);
+        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(OrderedConfiguration.class, ConfigurationType.ORDERED);
+        PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(MappedConfiguration.class, ConfigurationType.MAPPED);
     }
 
     /**
@@ -151,8 +151,7 @@ public class DefaultModuleDefImpl implem
         methods.removeAll(OBJECT_METHODS);
         removeSyntheticMethods(methods);
 
-        boolean modulePreventsServiceDecoration = moduleClass
-                .getAnnotation(PreventServiceDecoration.class) != null;
+        boolean modulePreventsServiceDecoration = moduleClass.getAnnotation(PreventServiceDecoration.class) != null;
 
         grind(methods, modulePreventsServiceDecoration);
         bind(methods, modulePreventsServiceDecoration);
@@ -160,9 +159,8 @@ public class DefaultModuleDefImpl implem
         if (methods.isEmpty())
             return;
 
-        throw new RuntimeException(String.format(
-                "Module class %s contains unrecognized public methods: %s.", moduleClass.getName(),
-                InternalUtils.joinSorted(methods)));
+        throw new RuntimeException(String.format("Module class %s contains unrecognized public methods: %s.",
+                moduleClass.getName(), InternalUtils.joinSorted(methods)));
     }
 
     /**
@@ -171,8 +169,7 @@ public class DefaultModuleDefImpl implem
     @Override
     public String toString()
     {
-        return String.format("ModuleDef[%s %s]", moduleClass.getName(), InternalUtils
-                .joinSorted(serviceDefs.keySet()));
+        return String.format("ModuleDef[%s %s]", moduleClass.getName(), InternalUtils.joinSorted(serviceDefs.keySet()));
     }
 
     public Class getBuilderClass()
@@ -275,11 +272,10 @@ public class DefaultModuleDefImpl implem
     private void addContributionDef(Method method)
     {
         Contribute annotation = method.getAnnotation(Contribute.class);
-        		
-        
-        Class serviceInterface = annotation==null?null:annotation.value();
-        
-        String serviceId = annotation!=null?null:stripMethodPrefix(method, CONTRIBUTE_METHOD_NAME_PREFIX);
+
+        Class serviceInterface = annotation == null ? null : annotation.value();
+
+        String serviceId = annotation != null ? null : stripMethodPrefix(method, CONTRIBUTE_METHOD_NAME_PREFIX);
 
         Class returnType = method.getReturnType();
         if (!returnType.equals(void.class))
@@ -289,8 +285,7 @@ public class DefaultModuleDefImpl implem
 
         for (Class parameterType : method.getParameterTypes())
         {
-            ConfigurationType thisParameter = PARAMETER_TYPE_TO_CONFIGURATION_TYPE
-                    .get(parameterType);
+            ConfigurationType thisParameter = PARAMETER_TYPE_TO_CONFIGURATION_TYPE.get(parameterType);
 
             if (thisParameter != null)
             {
@@ -303,9 +298,8 @@ public class DefaultModuleDefImpl implem
 
         if (type == null)
             throw new RuntimeException(IOCMessages.noContributionParameter(method));
-        
-        Set<Class> markers = CollectionFactory.newSet();
-        markers.addAll(extractMarkers(method));
+
+        Set<Class> markers = extractContributionMarkers(method);
 
         ContributionDef2 def = new ContributionDefImpl(serviceId, method, classFactory, serviceInterface, markers);
 
@@ -363,8 +357,7 @@ public class DefaultModuleDefImpl implem
         Class returnType = method.getReturnType();
 
         if (!returnType.equals(void.class))
-            throw new RuntimeException(String.format("Advise method %s does not return void.",
-                    toString(method)));
+            throw new RuntimeException(String.format("Advise method %s does not return void.", toString(method)));
 
         boolean found = false;
 
@@ -379,12 +372,11 @@ public class DefaultModuleDefImpl implem
         }
 
         if (!found)
-            throw new RuntimeException(String.format(
-                    "Advise method %s must take a parameter of type %s.", toString(method),
-                    MethodAdviceReceiver.class.getName()));
+            throw new RuntimeException(String.format("Advise method %s must take a parameter of type %s.",
+                    toString(method), MethodAdviceReceiver.class.getName()));
 
-        AdvisorDef def = new AdvisorDefImpl(method, extractPatterns(advisorId, method),
-                extractConstraints(method), classFactory, advisorId);
+        AdvisorDef def = new AdvisorDefImpl(method, extractPatterns(advisorId, method), extractConstraints(method),
+                classFactory, advisorId);
 
         advisorDefs.put(advisorId, def);
 
@@ -467,15 +459,15 @@ public class DefaultModuleDefImpl implem
         };
 
         Set<Class> markers = CollectionFactory.newSet(defaultMarkers);
-        markers.addAll(extractMarkers(method));
+        markers.addAll(extractServiceDefMarkers(method));
 
-        ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, serviceId, markers, scope,
-                eagerLoad, preventDecoration, source);
+        ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, serviceId, markers, scope, eagerLoad,
+                preventDecoration, source);
 
         addServiceDef(serviceDef);
     }
 
-    private Collection<Class> extractMarkers(Method method)
+    private Collection<Class> extractServiceDefMarkers(Method method)
     {
         Marker annotation = method.getAnnotation(Marker.class);
 
@@ -485,6 +477,25 @@ public class DefaultModuleDefImpl implem
         return CollectionFactory.newList(annotation.value());
     }
 
+    @SuppressWarnings("rawtypes")
+    private Set<Class> extractContributionMarkers(Method method)
+    {
+        return F.flow(method.getAnnotations()).map(new Mapper<Annotation, Class>()
+        {
+            public Class map(Annotation value)
+            {
+                return value.annotationType();
+            };
+        }).filter(new Predicate<Class>()
+        {
+            public boolean accept(Class object)
+            {
+                return !object.equals(Contribute.class);
+
+            }
+        }).toSet();
+    }
+
     public void addServiceDef(ServiceDef serviceDef)
     {
         String serviceId = serviceDef.getServiceId();
@@ -492,8 +503,8 @@ public class DefaultModuleDefImpl implem
         ServiceDef existing = serviceDefs.get(serviceId);
 
         if (existing != null)
-            throw new RuntimeException(IOCMessages.buildMethodConflict(serviceId, serviceDef
-                    .toString(), existing.toString()));
+            throw new RuntimeException(IOCMessages.buildMethodConflict(serviceId, serviceDef.toString(),
+                    existing.toString()));
 
         serviceDefs.put(serviceId, serviceDef);
     }
@@ -514,7 +525,7 @@ public class DefaultModuleDefImpl implem
     {
         return contributionDefs;
     }
-    
+
     public Set<StartupDef> getStartupDefs()
     {
         return startupDefs;
@@ -547,8 +558,8 @@ public class DefaultModuleDefImpl implem
             if (!Modifier.isStatic(bindMethod.getModifiers()))
                 throw new RuntimeException(IOCMessages.bindMethodMustBeStatic(toString(bindMethod)));
 
-            ServiceBinderImpl binder = new ServiceBinderImpl(this, bindMethod, classFactory,
-                    defaultMarkers, modulePreventsServiceDecoration);
+            ServiceBinderImpl binder = new ServiceBinderImpl(this, bindMethod, classFactory, defaultMarkers,
+                    modulePreventsServiceDecoration);
 
             bindMethod.invoke(null, binder);
 

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalRegistry.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalRegistry.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalRegistry.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/InternalRegistry.java Wed Jul  7 18:28:45 2010
@@ -14,16 +14,23 @@
 
 package org.apache.tapestry5.ioc.internal;
 
-import org.apache.tapestry5.ioc.*;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry5.ioc.AnnotationProvider;
+import org.apache.tapestry5.ioc.ObjectLocator;
+import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.ioc.Registry;
+import org.apache.tapestry5.ioc.ServiceAdvisor;
+import org.apache.tapestry5.ioc.ServiceDecorator;
+import org.apache.tapestry5.ioc.ServiceLifecycle2;
 import org.apache.tapestry5.ioc.def.ServiceDef;
 import org.apache.tapestry5.ioc.services.ClassFab;
 import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
 import org.slf4j.Logger;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
 /**
  * Internal view of the module registry, adding additional methods needed by modules.
  */
@@ -148,4 +155,11 @@ public interface InternalRegistry extend
      * @since 5.2.0
      */
     <T> T proxy(Class<T> interfaceClass, Class<? extends T> implementationClass, ObjectLocator locator);
+
+    /**
+     * Returns a Set of Annotation classes that are used as service markers.
+     * 
+     * @since 5.2.0
+     */
+    Set<Class> getMarkerAnnotations();
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java Wed Jul  7 18:28:45 2010
@@ -296,10 +296,9 @@ public class ModuleImpl implements Modul
                     {
                         if (lifecycle.requiresProxy())
                             throw new IllegalArgumentException(
-                                    String
-                                            .format(
-                                                    "Service scope '%s' requires a proxy, but the service does not have a service interface (necessary to create a proxy). Provide a service interface or select a different service scope.",
-                                                    def.getServiceScope()));
+                                    String.format(
+                                            "Service scope '%s' requires a proxy, but the service does not have a service interface (necessary to create a proxy). Provide a service interface or select a different service scope.",
+                                            def.getServiceScope()));
 
                         return creator.createObject();
                     }
@@ -443,8 +442,8 @@ public class ModuleImpl implements Modul
         {
             insideConstructor = true;
 
-            Object[] parameterValues = InternalUtils.calculateParameters(locator, resources, constructor
-                    .getParameterTypes(), constructor.getGenericParameterTypes(),
+            Object[] parameterValues = InternalUtils.calculateParameters(locator, resources,
+                    constructor.getParameterTypes(), constructor.getGenericParameterTypes(),
                     constructor.getParameterAnnotations(), registry);
 
             Object result = constructor.newInstance(parameterValues);
@@ -527,6 +526,7 @@ public class ModuleImpl implements Modul
         }
     }
 
+    @SuppressWarnings("all")
     public Set<ContributionDef2> getContributorDefsForService(ServiceDef serviceDef)
     {
         Set<ContributionDef2> result = CollectionFactory.newSet();
@@ -541,27 +541,41 @@ public class ModuleImpl implements Modul
             }
             else
             {
-                Set<Class> markers = CollectionFactory.newSet(def.getMarkers());
+                if (!serviceDef.getServiceInterface().equals(def.getServiceInterface()))
+                    continue;
 
-                if (markers.contains(Local.class))
+                Set<Class> contributionMarkers = CollectionFactory.newSet(def.getMarkers());
+
+                if (contributionMarkers.contains(Local.class))
                 {
-                    if (moduleDef.getServiceDef(serviceDef.getServiceId()) == null)
+                    // If @Local is present, filter out services that aren't in the same module.
+                    // Don't consider @Local to be a marker annotation
+                    // for the later match, however.
+
+                    if (!isLocalServiceDef(serviceDef))
                         continue;
 
-                    markers.remove(Local.class);
+                    contributionMarkers.remove(Local.class);
                 }
 
-                if (serviceDef.getMarkers().equals(markers)
-                        && serviceDef.getServiceInterface() == def.getServiceInterface())
-                {
+                // Filter out any stray annotations that aren't used by some
+                // service, in any module, as a marker annotation.
+
+                contributionMarkers.retainAll(registry.getMarkerAnnotations());
+
+                if (serviceDef.getMarkers().containsAll(contributionMarkers))
                     result.add(def);
-                }
             }
         }
 
         return result;
     }
 
+    private boolean isLocalServiceDef(ServiceDef serviceDef)
+    {
+        return serviceDefs.containsKey(serviceDef.getServiceId());
+    }
+
     public ServiceDef2 getServiceDef(String serviceId)
     {
         return serviceDefs.get(serviceId);
@@ -571,7 +585,7 @@ public class ModuleImpl implements Modul
     {
         return moduleDef.getLoggerName();
     }
-    
+
     public Set<StartupDef> getStartupDefs()
     {
         return moduleDef.getStartupDefs();

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java Wed Jul  7 18:28:45 2010
@@ -18,10 +18,15 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.tapestry5.func.F;
+import org.apache.tapestry5.func.Flow;
+import org.apache.tapestry5.func.Mapper;
+import org.apache.tapestry5.func.Predicate;
 import org.apache.tapestry5.ioc.*;
 import org.apache.tapestry5.ioc.annotations.Local;
 import org.apache.tapestry5.ioc.def.ContributionDef;
@@ -172,8 +177,8 @@ public class RegistryImpl implements Reg
                 Module existing = serviceIdToModule.get(serviceId);
 
                 if (existing != null)
-                    throw new RuntimeException(IOCMessages.serviceIdConflict(serviceId, existing
-                            .getServiceDef(serviceId), serviceDef));
+                    throw new RuntimeException(IOCMessages.serviceIdConflict(serviceId,
+                            existing.getServiceDef(serviceId), serviceDef));
 
                 serviceIdToModule.put(serviceId, module);
 
@@ -205,60 +210,75 @@ public class RegistryImpl implements Reg
      */
     private void validateContributeDefs(Collection<ModuleDef> moduleDefs)
     {
-        Set<ContributionDef> contributionDefs = CollectionFactory.newSet();
-
         for (ModuleDef module : moduleDefs)
         {
-            contributionDefs.addAll(module.getContributionDefs());
-        }
+            Set<ContributionDef> contributionDefs = module.getContributionDefs();
 
-        for (ContributionDef cd : contributionDefs)
-        {
-            String serviceId = cd.getServiceId();
+            for (ContributionDef cd : contributionDefs)
+            {
+                String serviceId = cd.getServiceId();
 
-            ContributionDef2 cd2 = InternalUtils.toContributionDef2(cd);
+                ContributionDef2 cd2 = InternalUtils.toContributionDef2(cd);
 
-            if (cd2.getServiceId() != null)
-            {
-                if (!serviceIdToModule.containsKey(serviceId)) { throw new IllegalArgumentException(IOCMessages
-                        .contributionForNonexistentService(cd)); }
+                if (cd2.getServiceId() != null)
+                {
+                    if (!serviceIdToModule.containsKey(serviceId)) { throw new IllegalArgumentException(
+                            IOCMessages.contributionForNonexistentService(cd)); }
+                }
+                else if (!isContributionForExistentService(module, cd2)) { throw new IllegalArgumentException(
+                        IOCMessages.contributionForUnqualifiedService(cd2)); }
             }
-            else if (!isContributionForExistentService(cd2)) { throw new IllegalArgumentException(IOCMessages
-                    .contributionForUnqualifiedService(cd2)); }
         }
 
     }
 
-    private boolean isContributionForExistentService(ContributionDef2 cd)
+    /**
+     * Invoked when the contribution method didn't follow the naming convention and so doesn't identify
+     * a service by id; instead there was an @Contribute to identify the service interface.
+     */
+    @SuppressWarnings("all")
+    private boolean isContributionForExistentService(ModuleDef moduleDef, final ContributionDef2 cd)
     {
-        Set<Class> markers = CollectionFactory.newSet(cd.getMarkers());
-        markers.remove(Local.class);
+        final Set<Class> contributionMarkers = new HashSet(cd.getMarkers());
+
+        boolean localOnly = contributionMarkers.contains(Local.class);
 
-        for (Class markerClass : markers)
+        Flow<ServiceDef2> serviceDefs = localOnly ? getLocalServiceDefs(moduleDef) : F.flow(allServiceDefs);
+
+        contributionMarkers.retainAll(getMarkerAnnotations());
+        contributionMarkers.remove(Local.class);
+
+        // Match services with the correct interface AND having as markers *all* the marker annotations
+        
+        Flow<ServiceDef2> filtered = serviceDefs.filter(new Predicate<ServiceDef2>()
         {
-            boolean exists = existsServiceDefWithTypeAndMarker(cd.getServiceInterface(), markerClass);
+            public boolean accept(ServiceDef2 object)
+            {
+                return object.getServiceInterface().equals(cd.getServiceInterface());
+            }
+        }.and(new Predicate<ServiceDef2>()
+        {
+            public boolean accept(ServiceDef2 serviceDef)
+            {
+                return serviceDef.getMarkers().containsAll(contributionMarkers);
+            }
+        }));
 
-            if (!exists)
-                return false;
-        }
+        // That's a lot of logic; the good news is it will short-circuit as soon as it finds a single match,
+        // thanks to the laziness inside Flow.
 
-        return true;
+        return !filtered.isEmpty();
     }
 
-    private boolean existsServiceDefWithTypeAndMarker(Class serviceInterface, Class markerClass)
+    private Flow<ServiceDef2> getLocalServiceDefs(final ModuleDef moduleDef)
     {
-        List<ServiceDef2> serviceDefs = markerToServiceDef.get(markerClass);
-
-        if (serviceDefs == null)
-            return false;
-
-        for (ServiceDef2 serviceDef : serviceDefs)
+        return F.flow(moduleDef.getServiceIds()).map(new Mapper<String, ServiceDef2>()
         {
-            if (serviceDef.getServiceInterface() == serviceInterface)
-                return true;
-        }
-
-        return false;
+            public ServiceDef2 map(String value)
+            {
+                return InternalUtils.toServiceDef2(moduleDef.getServiceDef(value));
+            }
+        });
     }
 
     /**
@@ -283,30 +303,30 @@ public class RegistryImpl implements Reg
             proxy.eagerLoadService();
 
         getService("RegistryStartup", Runnable.class).run();
-        
+
         invokeStartups();
 
         cleanupThread();
     }
-    
+
     private void invokeStartups()
-    {   
+    {
         for (Module m : moduleToServiceDefs.keySet())
         {
             Logger logger = this.loggerSource.getLogger(m.getLoggerName());
-            
+
             for (StartupDef sd : m.getStartupDefs())
             {
                 try
                 {
                     sd.startup(m, this, this, logger);
                 }
-                catch(RuntimeException e)
+                catch (RuntimeException e)
                 {
                     logger.error(ServiceMessages.startupFailure(e));
                 }
             }
-            
+
         }
     }
 
@@ -1011,8 +1031,8 @@ public class RegistryImpl implements Reg
             }
         };
 
-        return classFactory.createProxy(interfaceClass, justInTime, String.format("<Autobuild proxy %s(%s)>",
-                implementationClass.getName(), interfaceClass.getName()));
+        return classFactory.createProxy(interfaceClass, justInTime,
+                String.format("<Autobuild proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
     }
 
     private <T> T createReloadingProxy(Class<T> interfaceClass, final Class<? extends T> implementationClass,
@@ -1023,8 +1043,8 @@ public class RegistryImpl implements Reg
 
         getService(UpdateListenerHub.class).addUpdateListener(creator);
 
-        return classFactory.createProxy(interfaceClass, creator, String.format("<Autoreload proxy %s(%s)>",
-                implementationClass.getName(), interfaceClass.getName()));
+        return classFactory.createProxy(interfaceClass, creator,
+                String.format("<Autoreload proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
     }
 
     public Object provideServiceProxy(String serviceId)
@@ -1072,4 +1092,10 @@ public class RegistryImpl implements Reg
             }
         });
     }
+
+    public Set<Class> getMarkerAnnotations()
+    {
+        return markerToServiceDef.keySet();
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/configuration.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/configuration.apt?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/configuration.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/configuration.apt Wed Jul  7 18:28:45 2010
@@ -85,7 +85,21 @@ Naming conventions vs. Annotations
 	
 	If you prefer annotations over naming conventions you can use the {{{../apidocs/org/apache/tapestry5/ioc/annotations/Contribute.html}@Contribute}}
 	annotation. As of version 5.2 this annotation that may be placed on a contributor method of a module instead of starting the methods name 
-	with "contribute". The value of the annotation is the type of the service to contribute into. The following example is an alternative for the contribution method above.
+	with "contribute". The value of the annotation is the type of the service to contribute into. 
+	
+	
+  <<Note>>: the primary reasons to use @Contribute and marker annotations is twofold:
+  
+  * There is no longer a linkage between the contribution method name and the service id, which is much more refactoring
+    safe: if you change the service interface name, or the id of the service, your method will still be invoked when
+    using @Contribute.
+    
+  * It makes it much easier for an {{{cookbook/override.html}override}} of the service to get the
+    configuration intended for the original service.
+    
+  [] 	
+	
+	The following example is an alternative for the contribution method above.
 	
 +------+
   @Contribute(FileServiceDispatcher.class)
@@ -97,11 +111,11 @@ Naming conventions vs. Annotations
 +------+
 
 	If you have several implementations of a service interface, you have to disambiguate the services. For this purpose the 
-	{{{../apidocs/org/apache/tapestry5/ioc/annotations/Marker.html}@Marker}} annotation should be placed on the contributor method.
+	marker  annotations should be placed on the contributor method.
 	
 +------+
   @Contribute(FileServiceDispatcher.class)
-  @Marker({Red.class, Blue.class})
+  @Red @Blue
   public static void arbitraryMethodName(MappedConfiguration<String,FileServicer> configuration)
   {
     configuration.add("doc", new WordFileServicer());
@@ -109,12 +123,20 @@ Naming conventions vs. Annotations
   }  
 +------+  
 
-	If the {{{../apidocs/org/apache/tapestry5/ioc/annotations/Local.html}@Local}} annotation is present, 
+  In this example, the method will only be invoked when constructing a service configuration where
+  the service itself has both the Red and Blue marker annotations.  Tapestry knows which annotations
+  are marker annotations, and which marker annotations apply to the service, via
+  the {{{../apidocs/org/apache/tapestry5/ioc/annotations/Marker.html}@Marker}} annotation on the service implementation.
+
+	If the special {{{../apidocs/org/apache/tapestry5/ioc/annotations/Local.html}@Local}} annotation is present, 
 	then contribution is made only to the configuration of a service being constructed in the same module.
+	
+  It is not impossible that the same contribution method will be invoked to contribute to the configuration
+  of multiple different services.
 
 +------+
   @Contribute(FileServiceDispatcher.class)
-  @Marker(Local.class)
+  @Local
   public static void arbitraryMethodName(MappedConfiguration<String,FileServicer> configuration)
   {
     configuration.add("doc", new WordFileServicer());

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java Wed Jul  7 18:28:45 2010
@@ -1,10 +1,10 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2010 The Apache Software Foundation
 //
 // Licensed 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
+// 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,
@@ -14,15 +14,17 @@
 
 package org.apache.tapestry5.ioc;
 
-import java.lang.annotation.Documented;
 import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.PARAMETER;
-import java.lang.annotation.Retention;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
 @Target(
-        { PARAMETER, FIELD })
+{ PARAMETER, FIELD, METHOD })
 @Retention(RUNTIME)
 @Documented
 public @interface BlueMarker

Copied: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/GreenMarker.java (from r961468, tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/GreenMarker.java?p2=tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/GreenMarker.java&p1=tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java&r1=961468&r2=961469&rev=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/BlueMarker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/GreenMarker.java Wed Jul  7 18:28:45 2010
@@ -1,10 +1,10 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2010 The Apache Software Foundation
 //
 // Licensed 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
+// 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,
@@ -14,18 +14,20 @@
 
 package org.apache.tapestry5.ioc;
 
-import java.lang.annotation.Documented;
 import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.PARAMETER;
-import java.lang.annotation.Retention;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
 @Target(
-        { PARAMETER, FIELD })
+{ PARAMETER, FIELD, METHOD })
 @Retention(RUNTIME)
 @Documented
-public @interface BlueMarker
+public @interface GreenMarker
 {
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java Wed Jul  7 18:28:45 2010
@@ -1421,20 +1421,20 @@ public class IntegrationTest extends IOC
 
         NameListHolder greek = r.getService("Greek", NameListHolder.class);
 
-        assertEquals(greek.getNames(), Arrays.asList("Alpha", "Beta", "Gamma", "Delta"));
+        assertListsEquals(greek.getNames(), "Alpha", "Beta", "Gamma", "Delta");
 
         NameListHolder anotherGreek = r.getService("AnotherGreek", NameListHolder.class);
 
-        assertEquals(anotherGreek.getNames(), Arrays.asList("Alpha", "Beta", "Gamma", "Delta", "Epsilon"));
+        assertListsEquals(anotherGreek.getNames(), "Alpha", "Beta", "Gamma", "Delta", "Epsilon");
 
         NameListHolder hebrew = r.getService("Hebrew", NameListHolder.class);
 
-        assertEquals(hebrew.getNames(), Arrays.asList("Alef", "Bet", "Gimel", "Dalet", "He", "Vav"));
+        assertListsEquals(hebrew.getNames(), "Alef", "Bet", "Gimel", "Dalet", "He", "Vav");
 
         NameListHolder2 holder = r.getService("ServiceWithEmptyConfiguration", NameListHolder2.class);
 
         assertEquals(holder.getNames(), Arrays.asList());
-        
+
         r.shutdown();
 
     }
@@ -1492,22 +1492,22 @@ public class IntegrationTest extends IOC
 
         r.shutdown();
     }
-    
+
     @Test
     public void startup_inside_module()
     {
         Registry r = buildRegistry(StartupModule2.class);
-        
+
         assertFalse(StartupModule2.staticStartupInvoked);
-        
+
         assertFalse(StartupModule2.instanceStartupInvoked);
-        
+
         r.performRegistryStartup();
 
         assertTrue(StartupModule2.staticStartupInvoked);
-        
+
         assertTrue(StartupModule2.instanceStartupInvoked);
-        
+
         r.shutdown();
 
     }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule2.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule2.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule2.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule2.java Wed Jul  7 18:28:45 2010
@@ -4,7 +4,7 @@
 // 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
+// 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,
@@ -21,7 +21,7 @@ import org.apache.tapestry5.ioc.annotati
 
 public class InvalidContributeDefModule2
 {
-    @Marker(BlueMarker.class)
+    @Marker(GreenMarker.class)
     public NameListHolder build(final List<String> configuration)
     {
 
@@ -33,14 +33,22 @@ public class InvalidContributeDefModule2
             }
         };
     }
-    
+
+    @Marker(
+    { BlueMarker.class, RedMarker.class })
+    public Runnable buildBlueRedClassSoThatTheyAreMarkerAnnotations()
+    {
+        return null;
+    }
+
     /**
      * Its a contribute method, but to a service that does not exist.
      */
     @Contribute(NameListHolder.class)
-    @Marker({BlueMarker.class,RedMarker.class})
+    @BlueMarker
+    @RedMarker
     public void provideConfiguration(OrderedConfiguration<String> configuration)
     {
-        
+
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule3.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule3.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule3.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/InvalidContributeDefModule3.java Wed Jul  7 18:28:45 2010
@@ -4,7 +4,7 @@
 // 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
+// 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,
@@ -29,18 +29,19 @@ public class InvalidContributeDefModule3
         {
             public void run()
             {
-                
+
             }
- 
+
         };
     }
+
     /**
      * Its a contribute method, but to a service that does not exist.
      */
     @Contribute(NameListHolder.class)
-    @Marker(BlueMarker.class)
+    @BlueMarker
     public void provideConfiguration(OrderedConfiguration<String> configuration)
     {
-        
+
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/RedMarker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/RedMarker.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/RedMarker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/RedMarker.java Wed Jul  7 18:28:45 2010
@@ -1,10 +1,10 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2010 The Apache Software Foundation
 //
 // Licensed 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
+// 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,
@@ -14,15 +14,17 @@
 
 package org.apache.tapestry5.ioc;
 
-import java.lang.annotation.Documented;
 import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.PARAMETER;
-import java.lang.annotation.Retention;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
 @Target(
-        { PARAMETER, FIELD })
+{ PARAMETER, FIELD, METHOD })
 @Retention(RUNTIME)
 @Documented
 public @interface RedMarker

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule.java Wed Jul  7 18:28:45 2010
@@ -4,7 +4,7 @@
 // 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
+// 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,
@@ -17,10 +17,10 @@ package org.apache.tapestry5.ioc.interna
 import java.util.List;
 
 import org.apache.tapestry5.ioc.BlueMarker;
+import org.apache.tapestry5.ioc.GreenMarker;
 import org.apache.tapestry5.ioc.NameListHolder;
 import org.apache.tapestry5.ioc.NameListHolder2;
 import org.apache.tapestry5.ioc.OrderedConfiguration;
-import org.apache.tapestry5.ioc.RedMarker;
 import org.apache.tapestry5.ioc.annotations.Contribute;
 import org.apache.tapestry5.ioc.annotations.Marker;
 
@@ -38,24 +38,24 @@ public class AlphabetModule
             }
         };
     }
-    
+
     @Contribute(NameListHolder.class)
-    @Marker(BlueMarker.class)
+    @BlueMarker
     public void provideGreekConfiguration(OrderedConfiguration<String> configuration)
     {
         configuration.add("Alpha", "Alpha", "before:*");
         configuration.add("Beta", "Beta", "after:Alpha");
     }
-    
+
     @Contribute(NameListHolder.class)
-    @Marker({RedMarker.class, BlueMarker.class})
+    @GreenMarker
     public void addToHebrew(OrderedConfiguration<String> configuration)
     {
         configuration.add("Alef", "Alef", "before:*");
         configuration.add("Bet", "Bet", "after:Alef");
         configuration.add("Gimel", "Gimel", "after:Bet");
     }
-    
+
     @Marker(BlueMarker.class)
     public NameListHolder2 buildServiceWithEmptyConfiguration(final List<String> configuration)
     {
@@ -66,6 +66,6 @@ public class AlphabetModule
                 return configuration;
             }
         };
-        
+
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule2.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule2.java?rev=961469&r1=961468&r2=961469&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule2.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AlphabetModule2.java Wed Jul  7 18:28:45 2010
@@ -4,7 +4,7 @@
 // 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
+// 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,
@@ -17,6 +17,7 @@ package org.apache.tapestry5.ioc.interna
 import java.util.List;
 
 import org.apache.tapestry5.ioc.BlueMarker;
+import org.apache.tapestry5.ioc.GreenMarker;
 import org.apache.tapestry5.ioc.NameListHolder;
 import org.apache.tapestry5.ioc.OrderedConfiguration;
 import org.apache.tapestry5.ioc.RedMarker;
@@ -26,7 +27,7 @@ import org.apache.tapestry5.ioc.annotati
 
 public class AlphabetModule2
 {
-    @Marker({BlueMarker.class, RedMarker.class})
+    @Marker(GreenMarker.class)
     public NameListHolder buildHebrew(final List<String> configuration)
     {
 
@@ -53,7 +54,7 @@ public class AlphabetModule2
     }
 
     @Contribute(NameListHolder.class)
-    @Marker(BlueMarker.class)
+    @BlueMarker
     public void extendGreekConfiguration(OrderedConfiguration<String> configuration)
     {
         configuration.add("Gamma", "Gamma", "after:Beta");
@@ -61,20 +62,21 @@ public class AlphabetModule2
     }
 
     @Contribute(NameListHolder.class)
-    @Marker({ BlueMarker.class, Local.class })
+    @BlueMarker
+    @Local
     public void contributeXyz(OrderedConfiguration<String> configuration)
     {
         configuration.add("Epsilon", "Epsilon", "after:*");
     }
-    
+
     @Contribute(NameListHolder.class)
-    @Marker({RedMarker.class, BlueMarker.class})
+    @GreenMarker
     public void someMoreHebrewLetters(OrderedConfiguration<String> configuration)
     {
         configuration.add("Dalet", "Dalet", "after:Gimel");
         configuration.add("He", "He", "after:Dalet");
     }
-    
+
     public void contributeHebrew(OrderedConfiguration<String> configuration)
     {
         configuration.add("Vav", "Vav", "after:He");