You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2014/01/02 17:15:24 UTC

[2/3] git commit: TAP5-2029: Copy annotations from service implementation to proxy

TAP5-2029: Copy annotations from service implementation to proxy


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/4a818e35
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/4a818e35
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/4a818e35

Branch: refs/heads/master
Commit: 4a818e35585ac0860aaffa23bc0d1799514480da
Parents: ae473c8
Author: Thiago H. de Paula Figueiredo <th...@apache.org>
Authored: Thu Jan 2 14:13:12 2014 -0200
Committer: Thiago H. de Paula Figueiredo <th...@apache.org>
Committed: Thu Jan 2 14:13:12 2014 -0200

----------------------------------------------------------------------
 .../internal/plastic/InheritanceData.java       |  4 +-
 .../internal/plastic/PlasticClassImpl.java      | 83 +++++++++++++++++++-
 .../internal/plastic/PlasticClassPool.java      | 75 +++++++++++++++---
 .../tapestry5/plastic/PlasticManager.java       | 28 ++++++-
 .../services/ComponentTemplateSourceImpl.java   |  2 +-
 .../internal/services/PageMarkupRenderer.java   |  2 +-
 .../internal/services/PageResponseRenderer.java |  2 +-
 .../ServiceAnnotationObjectProvider.java        |  2 +-
 .../tapestry5/modules/TapestryModule.java       | 18 ++---
 .../services/ApplicationInitializer.java        |  2 +-
 .../services/ClasspathAssetAliasManager.java    |  2 +-
 .../services/RequestExceptionHandler.java       |  2 +-
 .../tapestry5/services/RequestGlobals.java      |  2 +-
 .../tapestry5/services/RequestHandler.java      |  2 +-
 .../services/ServletApplicationInitializer.java |  2 +-
 .../apache/tapestry5/services/URLEncoder.java   |  2 +-
 .../assets/StreamableResourceSource.java        |  2 +-
 .../tapestry5/services/meta/MetaWorker.java     |  2 +-
 .../integration/app1/CoreBehaviorsTests.java    |  4 +-
 .../tapestry5/integration/app1/pages/Index.java |  6 +-
 .../org/apache/tapestry5/ioc/AdvisorDef.java    |  2 +-
 .../org/apache/tapestry5/ioc/ObjectLocator.java |  2 +-
 .../apache/tapestry5/ioc/ServiceResources.java  | 14 ++--
 .../tapestry5/ioc/annotations/EagerLoad.java    |  2 +-
 .../annotations/PreventServiceDecoration.java   |  2 +-
 .../apache/tapestry5/ioc/def/DecoratorDef.java  |  2 +-
 .../apache/tapestry5/ioc/def/ServiceDef.java    |  6 +-
 .../apache/tapestry5/ioc/def/ServiceDef3.java   | 11 +++
 .../ioc/internal/EagerLoadServiceProxy.java     |  2 +-
 .../tapestry5/ioc/internal/ModuleImpl.java      | 16 ++--
 .../tapestry5/ioc/internal/RegistryImpl.java    |  4 +-
 .../internal/ReloadableObjectCreatorSource.java |  2 +-
 ...dableServiceImplementationObjectCreator.java |  2 +-
 .../tapestry5/ioc/internal/ServiceDefImpl.java  |  5 ++
 .../ioc/internal/ServiceResourcesImpl.java      |  5 ++
 .../internal/services/AspectDecoratorImpl.java  |  2 +-
 .../services/AspectInterceptorBuilderImpl.java  |  2 +-
 .../services/PerThreadServiceLifecycle.java     |  2 +-
 .../services/PlasticProxyFactoryImpl.java       | 24 +++++-
 .../ioc/internal/util/InternalUtils.java        |  7 ++
 .../util/WrongConfigurationTypeGuard.java       |  2 +-
 .../ioc/services/LoggingDecorator.java          |  2 +-
 .../ioc/services/PlasticProxyFactory.java       | 52 ++++++++++++
 .../ioc/services/RegistryShutdownListener.java  |  2 +-
 .../groovy/ioc/specs/BridgeBuilderSpec.groovy   |  2 +-
 .../ioc/specs/ContributionDefImplSpec.groovy    |  2 +-
 .../ioc/specs/DefaultModuleDefImplSpec.groovy   |  2 +-
 .../groovy/ioc/specs/PerThreadScopeSpec.groovy  |  2 +-
 ...istryConstructionAndRuntimeErrorsSpec.groovy |  2 +-
 .../src/test/groovy/ioc/specs/ReloadSpec.groovy |  2 +-
 .../groovy/ioc/specs/ServiceLookupSpec.groovy   |  4 +-
 .../ValidatingConfigurationWrapperSpec.groovy   |  2 +-
 ...idatingMappedConfigurationWrapperSpec.groovy |  4 +-
 .../ServiceProxySerializationSpec.groovy        |  2 +-
 54 files changed, 349 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java
index 17d90d2..ab7a17f 100644
--- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java
+++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/InheritanceData.java
@@ -119,7 +119,9 @@ public class InheritanceData
     }
 
     public void addInterface(String name) {
-        interfaceNames.add(name);
+        if (!interfaceNames.contains(name)) {
+            interfaceNames.add(name);
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
index a0e88d4..e12ef71 100644
--- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
+++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassImpl.java
@@ -14,11 +14,13 @@
 
 package org.apache.tapestry5.internal.plastic;
 
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 import org.apache.tapestry5.internal.plastic.asm.Type;
 import org.apache.tapestry5.internal.plastic.asm.tree.*;
 import org.apache.tapestry5.plastic.*;
 
+import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
@@ -166,28 +168,34 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
     // Set of methods that need to contribute to the shim and gain access to it
 
     final Set<PlasticMethodImpl> shimMethods = PlasticInternalUtils.newSet();
+    
+    final ClassNode implementationClassNode;
+    
+    private ClassNode interfaceClassNode;
 
     /**
      * @param classNode
+     * @param implementationClassNode
      * @param pool
      * @param parentInheritanceData
      * @param parentStaticContext
      * @param proxy
      */
-    public PlasticClassImpl(ClassNode classNode, PlasticClassPool pool, InheritanceData parentInheritanceData,
+    public PlasticClassImpl(ClassNode classNode, ClassNode implementationClassNode, PlasticClassPool pool, InheritanceData parentInheritanceData,
                             StaticContext parentStaticContext, boolean proxy)
     {
         this.classNode = classNode;
         this.pool = pool;
         this.proxy = proxy;
-
+        this.implementationClassNode = implementationClassNode;
+        
         staticContext = parentStaticContext.dupe();
 
         className = PlasticInternalUtils.toClassName(classNode.name);
         superClassName = PlasticInternalUtils.toClassName(classNode.superName);
 
         fieldInstrumentations = new FieldInstrumentations(classNode.superName);
-
+        
         annotationAccess = new DelegatingAnnotationAccess(pool.createAnnotationAccess(classNode.visibleAnnotations),
                 pool.createAnnotationAccess(superClassName));
 
@@ -326,6 +334,32 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
 
         return annotationAccess.getAnnotation(annotationType);
     }
+    
+    private static void copyAnnotationsFromServiceImplementation(MethodNode methodNode, ClassNode source)
+    {
+        if (source != null)
+        {
+        
+            for (MethodNode implementationNode : source.methods)
+            {
+                // Find corresponding method in the implementation class MethodNode
+                if (methodNode.name.equals(implementationNode.name) && methodNode.desc.equals(implementationNode.desc))
+                {
+                    implementationNode.accept(methodNode);
+                    
+                    // We want to copy just annotations, not code.
+                    methodNode.instructions.clear();
+                    methodNode.instructions.resetLabels();
+                    
+                    break;
+                    
+                }
+                
+            }
+            
+        }
+        
+    }
 
     public PlasticClass proxyInterface(Class interfaceType, PlasticField field)
     {
@@ -346,6 +380,8 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
     public ClassInstantiator createInstantiator()
     {
         lock();
+        
+        addClassAnnotations(implementationClassNode);
 
         createShimIfNeeded();
 
@@ -360,6 +396,29 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
         return createInstantiatorFromClass(transformedClass);
     }
 
+    private void addClassAnnotations(ClassNode otherClassNode)
+    {
+        // Copy annotations from implementation if available.
+        // Code adapted from ClassNode.accept(), as we just want to copy
+        // the annotations and nothing more.
+        if (otherClassNode != null) 
+        {
+            
+            int i, n;
+            n = otherClassNode.visibleAnnotations == null ? 0 : otherClassNode.visibleAnnotations.size();
+            for (i = 0; i < n; ++i) {
+                AnnotationNode an = otherClassNode.visibleAnnotations.get(i);
+                an.accept(classNode.visitAnnotation(an.desc, true));
+            }
+            n = otherClassNode.invisibleAnnotations == null ? 0 : otherClassNode.invisibleAnnotations.size();
+            for (i = 0; i < n; ++i) {
+                AnnotationNode an = otherClassNode.invisibleAnnotations.get(i);
+                an.accept(classNode.visitAnnotation(an.desc, false));
+            }
+            
+        }
+    }
+
     private ClassInstantiator createInstantiatorFromClass(Class clazz)
     {
         try
@@ -674,6 +733,11 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
         MethodNode methodNode = new MethodNode(description.modifiers, description.methodName, desc,
                 description.genericSignature, exceptions);
         boolean isOverride = inheritanceData.isImplemented(methodNode.name, desc);
+        
+        if (!isOverride) {
+            copyAnnotationsFromServiceImplementation(methodNode, interfaceClassNode);
+            copyAnnotationsFromServiceImplementation(methodNode, implementationClassNode);
+        }
 
         if (isOverride)
             createOverrideOfBaseClassImpl(description, methodNode);
@@ -1065,12 +1129,23 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
                     "Class %s is not an interface; ony interfaces may be introduced.", interfaceType.getName()));
 
         String interfaceName = nameCache.toInternalName(interfaceType);
+        
+        try
+        {
+            interfaceClassNode = PlasticClassPool.readClassNode(interfaceType.getName(), getClass().getClassLoader());
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
 
         if (!inheritanceData.isInterfaceImplemented(interfaceName))
         {
             classNode.interfaces.add(interfaceName);
             inheritanceData.addInterface(interfaceName);
         }
+        
+        addClassAnnotations(interfaceClassNode);
 
         Set<PlasticMethod> introducedMethods = new HashSet<PlasticMethod>();
 
@@ -1083,6 +1158,8 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
                 introducedMethods.add(introduceMethod(m));
             }
         }
+        
+        interfaceClassNode = null;
 
         return introducedMethods;
     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
index 5d38c0c..41ce961 100644
--- a/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
+++ b/plastic/src/main/java/org/apache/tapestry5/internal/plastic/PlasticClassPool.java
@@ -20,6 +20,9 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
 import org.apache.tapestry5.internal.plastic.asm.tree.*;
 import org.apache.tapestry5.plastic.*;
 
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Modifier;
 import java.util.*;
@@ -86,6 +89,9 @@ public class PlasticClassPool implements ClassLoaderDelegate, Opcodes, PlasticCl
 
     private final Map<String, FieldInstrumentations> instrumentations = PlasticInternalUtils.newMap();
 
+    private final Map<String, String> transformedClassNameToImplementationClassName = PlasticInternalUtils.newMap();
+    
+
     private final FieldInstrumentations placeholder = new FieldInstrumentations(null);
 
 
@@ -120,7 +126,6 @@ public class PlasticClassPool implements ClassLoaderDelegate, Opcodes, PlasticCl
         synchronized (loader)
         {
             Class result = realize(PlasticInternalUtils.toClassName(classNode.name), ClassType.PRIMARY, classNode);
-
             baseClassDefs.put(result.getName(), new BaseClassDef(inheritanceData, staticContext));
 
             return result;
@@ -434,17 +439,19 @@ public class PlasticClassPool implements ClassLoaderDelegate, Opcodes, PlasticCl
         String baseClassName = PlasticInternalUtils.toClassName(classNode.superName);
 
         instrumentations.put(classNode.name, new FieldInstrumentations(classNode.superName));
-
-        return createTransformation(baseClassName, classNode, false);
+        
+        // TODO: check whether second parameter should really be null
+        return createTransformation(baseClassName, classNode, null, false); 
     }
 
     /**
      * @param baseClassName class from which the transformed class extends
      * @param classNode     node for the class
+     * @param implementationClassNode     node for the implementation class. May be null.
      * @param proxy         if true, the class is a new empty class; if false an existing class that's being transformed
      * @throws ClassNotFoundException
      */
-    private InternalPlasticClassTransformation createTransformation(String baseClassName, ClassNode classNode, boolean proxy)
+    private InternalPlasticClassTransformation createTransformation(String baseClassName, ClassNode classNode, ClassNode implementationClassNode, boolean proxy)
             throws ClassNotFoundException
     {
         if (shouldInterceptClassLoading(baseClassName))
@@ -455,12 +462,12 @@ public class PlasticClassPool implements ClassLoaderDelegate, Opcodes, PlasticCl
 
             assert def != null;
 
-            return new PlasticClassImpl(classNode, this, def.inheritanceData, def.staticContext, proxy);
+            return new PlasticClassImpl(classNode, implementationClassNode, this, def.inheritanceData, def.staticContext, proxy);
         }
 
         // When the base class is Object, or otherwise not in a transformed package,
         // then start with the empty
-        return new PlasticClassImpl(classNode, this, emptyInheritanceData, emptyStaticContext, proxy);
+        return new PlasticClassImpl(classNode, implementationClassNode, this, emptyInheritanceData, emptyStaticContext, proxy);
     }
 
     /**
@@ -487,21 +494,69 @@ public class PlasticClassPool implements ClassLoaderDelegate, Opcodes, PlasticCl
         return PlasticInternalUtils.readBytecodeForClass(parentClassLoader, className, true);
     }
 
-    public PlasticClassTransformation createTransformation(String baseClassName, String newClassName)
+    public PlasticClassTransformation createTransformation(String baseClassName, String newClassName) {
+        return createTransformation(baseClassName, newClassName, null);
+    }
+    
+    public PlasticClassTransformation createTransformation(String baseClassName, String newClassName, String implementationClassName)
     {
         try
         {
             ClassNode newClassNode = new ClassNode();
 
-            newClassNode.visit(V1_5, ACC_PUBLIC, PlasticInternalUtils.toInternalName(newClassName), null,
-                    PlasticInternalUtils.toInternalName(baseClassName), null);
+            final String internalNewClassNameinternalName = PlasticInternalUtils.toInternalName(newClassName);
+            final String internalBaseClassName = PlasticInternalUtils.toInternalName(baseClassName);
+            newClassNode.visit(V1_5, ACC_PUBLIC, internalNewClassNameinternalName, null, internalBaseClassName, null);
+            
+            ClassNode implementationClassNode = null;
+            
+            if (implementationClassName != null)
+            {
+                // When decorating or advising a service, implementationClassName is the name
+                // of a proxy class already, such as "$ServiceName_[random string]",
+                // which doesn't exist as a file in the classpath, just in memory.
+                // So we need to keep what's the original implementation class name
+                // for each proxy, even a proxy around a proxy.
+                if (transformedClassNameToImplementationClassName.containsKey(implementationClassName))
+                {
+                    implementationClassName = 
+                            transformedClassNameToImplementationClassName.get(implementationClassName);
+                }
+                implementationClassNode = readClassNode(implementationClassName);
+                transformedClassNameToImplementationClassName.put(newClassName, implementationClassName);
+            }
 
-            return createTransformation(baseClassName, newClassNode, true);
+            return createTransformation(baseClassName, newClassNode, implementationClassNode, true);
         } catch (ClassNotFoundException ex)
         {
             throw new RuntimeException(String.format("Unable to create class %s as sub-class of %s: %s", newClassName,
                     baseClassName, PlasticInternalUtils.toMessage(ex)), ex);
         }
+        catch (IOException e)
+        {
+            throw new RuntimeException(String.format("Unable to load class %s as the implementation of service %s", 
+                    implementationClassName, baseClassName), e);
+        }
+    }
+
+    private ClassNode readClassNode(String className) throws IOException
+    {
+        return readClassNode(className, getClassLoader());
+    }
+    
+    static ClassNode readClassNode(String className, ClassLoader classLoader) throws IOException
+    {
+        ClassNode classNode = new ClassNode();
+        ClassReader classReader = new ClassReader(className);
+        final String location = PlasticInternalUtils.toInternalName(className) + ".class";
+        InputStream inputStream = classLoader.getResourceAsStream(location);
+        BufferedInputStream bis = new BufferedInputStream(inputStream);
+        classReader = new ClassReader(inputStream);
+        bis.close();
+        inputStream.close();
+        classReader.accept(classNode, 0);
+        return classNode;
+        
     }
 
     public ClassInstantiator getClassInstantiator(String className)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
----------------------------------------------------------------------
diff --git a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
index 26546de..4da7cc8 100644
--- a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
+++ b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
@@ -228,9 +228,27 @@ public class PlasticManager implements PlasticClassListenerHub
      */
     public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback)
     {
+    	return createProxy(interfaceType, null, callback);
+    }
+
+    /**
+     * Creates an entirely new class. The class extends from Object and implements the provided interface.
+     * 
+     * @param interfaceType
+     *            class to extend from, which must be a class, not an interface
+     * @param implementationType
+     *            class that implements interfaceType. It can be null. 
+     * @param callback
+     *            used to configure the new class
+     * @return the instantiator, which allows instances of the new class to be created
+     * @see #createProxyTransformation(Class, Class)
+     * @since 5.4
+     */
+    public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback)
+    {
         assert callback != null;
 
-        PlasticClassTransformation<T> transformation = createProxyTransformation(interfaceType);
+        PlasticClassTransformation<T> transformation = createProxyTransformation(interfaceType, implementationType);
 
         callback.transform(transformation.getPlasticClass());
 
@@ -244,9 +262,11 @@ public class PlasticManager implements PlasticClassListenerHub
      * 
      * @param interfaceType
      *            class proxy will extend from
+     * @param implementationType
+     *            class that implements interfaceType. It can be null.
      * @return transformation from which an instantiator may be created
      */
-    public <T> PlasticClassTransformation<T> createProxyTransformation(Class interfaceType)
+    public <T> PlasticClassTransformation<T> createProxyTransformation(Class interfaceType, Class implementationType)
     {
         assert interfaceType != null;
 
@@ -257,7 +277,9 @@ public class PlasticManager implements PlasticClassListenerHub
 
         String name = String.format("$%s_%s", interfaceType.getSimpleName(), PlasticUtils.nextUID());
 
-        PlasticClassTransformation<T> result = pool.createTransformation("java.lang.Object", name);
+        final String implementationClassName = implementationType != null ? implementationType.getName() : null;
+        PlasticClassTransformation<T> result = 
+                pool.createTransformation("java.lang.Object", name, implementationClassName);
 
         result.getPlasticClass().introduceInterface(interfaceType);
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
index d651625..87b9b23 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentTemplateSourceImpl.java
@@ -42,7 +42,7 @@ import java.util.Locale;
 import java.util.Map;
 
 /**
- * Service implementation that manages a cache of parsed component templates.
+ * NonAnnotatedServiceInterface implementation that manages a cache of parsed component templates.
  */
 public final class ComponentTemplateSourceImpl extends InvalidationEventHubImpl implements ComponentTemplateSource,
         UpdateListener

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageMarkupRenderer.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageMarkupRenderer.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageMarkupRenderer.java
index 2ddee2a..ad6750f 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageMarkupRenderer.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageMarkupRenderer.java
@@ -18,7 +18,7 @@ import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.internal.structure.Page;
 
 /**
- * Service used to render page markup using a MarkupWriter.  This is  used when rendering a complete page as part of a
+ * NonAnnotatedServiceInterface used to render page markup using a MarkupWriter.  This is  used when rendering a complete page as part of a
  * {@linkplain org.apache.tapestry5.internal.services.PageRenderRequestHandlerImpl page render request},
  */
 public interface PageMarkupRenderer

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRenderer.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRenderer.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRenderer.java
index 62b5282..97c30b7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRenderer.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageResponseRenderer.java
@@ -19,7 +19,7 @@ import org.apache.tapestry5.internal.structure.Page;
 import java.io.IOException;
 
 /**
- * Service responsible for writing a full page markup response.
+ * NonAnnotatedServiceInterface responsible for writing a full page markup response.
  */
 public interface PageResponseRenderer
 {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServiceAnnotationObjectProvider.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServiceAnnotationObjectProvider.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServiceAnnotationObjectProvider.java
index da0b26f..de68a77 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServiceAnnotationObjectProvider.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ServiceAnnotationObjectProvider.java
@@ -20,7 +20,7 @@ import org.apache.tapestry5.ioc.ObjectLocator;
 import org.apache.tapestry5.ioc.ObjectProvider;
 
 /**
- * Adds support for the {@link Service} annotation (which can be applied to fields or parameters), which is used to
+ * Adds support for the {@link NonAnnotatedServiceInterface} annotation (which can be applied to fields or parameters), which is used to
  * disambiguate injection when multiple services implement the same service interface.
  */
 public class ServiceAnnotationObjectProvider implements ObjectProvider

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index aa79a57..e7c7f87 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -375,13 +375,13 @@ public final class TapestryModule
 
     // ========================================================================
     //
-    // Service Builder Methods (static)
+    // NonAnnotatedServiceInterface Builder Methods (static)
     //
     // ========================================================================
 
     // ========================================================================
     //
-    // Service Contribution Methods (static)
+    // NonAnnotatedServiceInterface Contribution Methods (static)
     //
     // ========================================================================
 
@@ -709,7 +709,7 @@ public final class TapestryModule
      * <dd>Access to properties of resources (log, messages, etc.)</dd>
      * <dt>Asset</dt>
      * <dd>injection of assets (triggered via {@link Path} annotation), with the path relative to the component class</dd>
-     * <dt>Service</dt>
+     * <dt>NonAnnotatedServiceInterface</dt>
      * <dd>Ordered last, for use when Inject is present and nothing else works, matches field type against Tapestry IoC
      * services</dd>
      * </dl>
@@ -729,7 +729,7 @@ public final class TapestryModule
 
         // This needs to be the last one, since it matches against services
         // and might blow up if there is no match.
-        configuration.addInstance("Service", ServiceInjectionProvider.class, "after:*");
+        configuration.addInstance("NonAnnotatedServiceInterface", ServiceInjectionProvider.class, "after:*");
     }
 
     /**
@@ -738,8 +738,8 @@ public final class TapestryModule
      * <dt>Asset
      * <dt>
      * <dd>Checks for the {@link Path} annotation, and injects an {@link Asset}</dd>
-     * <dt>Service</dt>
-     * <dd>Injects based on the {@link Service} annotation, if present</dd>
+     * <dt>NonAnnotatedServiceInterface</dt>
+     * <dd>Injects based on the {@link NonAnnotatedServiceInterface} annotation, if present</dd>
      * <dt>ApplicationMessages</dt>
      * <dd>Injects the global application messages</dd>
      * </dl>
@@ -753,7 +753,7 @@ public final class TapestryModule
     {
         configuration.add("Asset", assetObjectProvider, "before:AnnotationBasedContributions");
 
-        configuration.add("Service", new ServiceAnnotationObjectProvider(), "before:AnnotationBasedContributions");
+        configuration.add("NonAnnotatedServiceInterface", new ServiceAnnotationObjectProvider(), "before:AnnotationBasedContributions");
 
         configuration.add("ApplicationMessages", new ApplicationMessageCatalogObjectProvider(locator),
                 "before:AnnotationBasedContributions");
@@ -1129,7 +1129,7 @@ public final class TapestryModule
 
     // ========================================================================
     //
-    // Service Builder Methods (instance)
+    // NonAnnotatedServiceInterface Builder Methods (instance)
     //
     // ========================================================================
 
@@ -1504,7 +1504,7 @@ public final class TapestryModule
 
     // ========================================================================
     //
-    // Service Contribution Methods (instance)
+    // NonAnnotatedServiceInterface Contribution Methods (instance)
     //
     // ========================================================================
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/ApplicationInitializer.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/ApplicationInitializer.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/ApplicationInitializer.java
index 4674192..1ce486a 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/ApplicationInitializer.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/ApplicationInitializer.java
@@ -17,7 +17,7 @@ package org.apache.tapestry5.services;
 import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
 
 /**
- * Service interface for initializing Tapestry for the application.  The service is a {@linkplain
+ * NonAnnotatedServiceInterface interface for initializing Tapestry for the application.  The service is a {@linkplain
  * org.apache.tapestry5.ioc.services.PipelineBuilder pipeline}, into which {@linkplain
  * org.apache.tapestry5.services.ApplicationInitializerFilter filters} may be contributed.
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
index b540780..5548586 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
@@ -27,7 +27,7 @@ import java.util.Map;
  * classpath, is converted into a shorter virtual path. The term "alias" here is generally referred to as
  * "virtual folder" elsewhere.
  * <p/>
- * Service configuration is a map from folder aliases (short names) to complete paths. Names should not start or end end
+ * NonAnnotatedServiceInterface configuration is a map from folder aliases (short names) to complete paths. Names should not start or end end
  * with a slash. Generally, an alias should be a single name (not contain a slash). Paths should also not start or end
  * with a slash. An example mapping would be <code>mylib</code> to <code>com/example/mylib</code>.
  * <p/>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestExceptionHandler.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestExceptionHandler.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestExceptionHandler.java
index 3d63bf8..676deec 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestExceptionHandler.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestExceptionHandler.java
@@ -17,7 +17,7 @@ package org.apache.tapestry5.services;
 import java.io.IOException;
 
 /**
- * Service invoked when an uncaught exception occurs. The error handler is responsible for providing a response to the
+ * NonAnnotatedServiceInterface invoked when an uncaught exception occurs. The error handler is responsible for providing a response to the
  * user to describe the error.
  */
 public interface RequestExceptionHandler

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestGlobals.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestGlobals.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestGlobals.java
index 65f53b1..7004b10 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestGlobals.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestGlobals.java
@@ -21,7 +21,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 /**
- * Service used to store the current request objects, both the Servlet API versions, and the
+ * NonAnnotatedServiceInterface used to store the current request objects, both the Servlet API versions, and the
  * Tapestry generic versions.
  * The service has a per-thread scope.
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestHandler.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestHandler.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestHandler.java
index 9a012c0..8aa33db 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestHandler.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/RequestHandler.java
@@ -19,7 +19,7 @@ import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
 import java.io.IOException;
 
 /**
- * Service interface for the RequestHandler {@linkplain org.apache.tapestry5.ioc.services.PipelineBuilder pipeline}
+ * NonAnnotatedServiceInterface interface for the RequestHandler {@linkplain org.apache.tapestry5.ioc.services.PipelineBuilder pipeline}
  * service. At the end of the pipeline, the service hands off to the {@linkplain org.apache.tapestry5.services.Dispatcher
  * master dispatcher service}.
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/ServletApplicationInitializer.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/ServletApplicationInitializer.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/ServletApplicationInitializer.java
index af3b65d..48eb50d 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/ServletApplicationInitializer.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/ServletApplicationInitializer.java
@@ -19,7 +19,7 @@ import org.apache.tapestry5.ioc.annotations.UsesOrderedConfiguration;
 import javax.servlet.ServletContext;
 
 /**
- * Service interface for initializing a servlet application, as a {@linkplain org.apache.tapestry5.ioc.services.PipelineBuilder
+ * NonAnnotatedServiceInterface interface for initializing a servlet application, as a {@linkplain org.apache.tapestry5.ioc.services.PipelineBuilder
  * pipeline}. The terminator hands off to the {@link org.apache.tapestry5.services.ApplicationInitializer} service.
  */
 @UsesOrderedConfiguration(ServletApplicationInitializerFilter.class)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/URLEncoder.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/URLEncoder.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/URLEncoder.java
index 2bc0e63..10e7ab6 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/URLEncoder.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/URLEncoder.java
@@ -15,7 +15,7 @@
 package org.apache.tapestry5.services;
 
 /**
- * Service used to encode or decode strings that are placed into URLs.  This is used as an alternative to UUEncoding.
+ * NonAnnotatedServiceInterface used to encode or decode strings that are placed into URLs.  This is used as an alternative to UUEncoding.
  * Alphabetics, numbers and some punctuation ("-", "_", ".", ":") are passed through as is, the "$" character is an
  * escape, followed by either another "$", or by a four digit hex unicode number.  A null input (not a blank input, but
  * actual null) has a special encoding, "$N". Likewise, the blank string has the special encoding "$B".

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java
index 4a35499..ac885c6 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java
@@ -24,7 +24,7 @@ import java.util.Set;
  * Converts {@link Resource}s into {@link StreamableResource}s, and may be responsible for
  * {@linkplain ResourceTransformer transforming} resources based on file extension. Contributions map a file extension
  * (such as "coffee") to a transformer for that file extension.
- * Service decorators added to this service may provide additional processing (compression, minimization, and caching).
+ * NonAnnotatedServiceInterface decorators added to this service may provide additional processing (compression, minimization, and caching).
  *
  * @since 5.3
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/main/java/org/apache/tapestry5/services/meta/MetaWorker.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/meta/MetaWorker.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/meta/MetaWorker.java
index 5edf83c..0e80540 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/meta/MetaWorker.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/meta/MetaWorker.java
@@ -18,7 +18,7 @@ import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
 import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2;
 
 /**
- * Service that makes it easy to identify a class annotation and use its presence, or the value of an attribute,
+ * NonAnnotatedServiceInterface that makes it easy to identify a class annotation and use its presence, or the value of an attribute,
  * to set a meta-data key. The configuration map class annotation types to corresponding extractors who will be invoked
  * when the annotation is present. Most commonly, a {@link FixedExtractor} is used to set a fixed value to a fixed key,
  * triggered by the presence of the corresponding annotation.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
index 7f4f287..9f14319 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/CoreBehaviorsTests.java
@@ -1541,7 +1541,7 @@ public class CoreBehaviorsTests extends App1TestCase
     @Test
     public void module_loading()
     {
-        openLinks("Test Only Service Demo");
+        openLinks("Test Only NonAnnotatedServiceInterface Demo");
 
         assertText("message", "TestOnly service message");
     }
@@ -1593,7 +1593,7 @@ public class CoreBehaviorsTests extends App1TestCase
     @Test
     public void injection_of_application_message_catalog_into_service()
     {
-        openLinks("Inject Global Messages into Service Demo");
+        openLinks("Inject Global Messages into NonAnnotatedServiceInterface Demo");
 
         assertText("status", "Application Catalog Working");
     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 8b2e3fe..a3f2337 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -128,10 +128,10 @@ public class Index
 
                     new Item("RenderNotificationDemo", "RenderNotification Demo", "Use of RenderNotification mixin"),
 
-                    new Item("InjectMessagesDemo", "Inject Global Messages into Service Demo",
+                    new Item("InjectMessagesDemo", "Inject Global Messages into NonAnnotatedServiceInterface Demo",
                             "Ensure that it is possible to inject the application global message catalog into a service"),
 
-                    new Item("ReloadDemo", "Reloadable Service Implementation Demo",
+                    new Item("ReloadDemo", "Reloadable NonAnnotatedServiceInterface Implementation Demo",
                             "Used when manually testing service reloads"),
 
                     new Item("RequestParameterDemo", "RequestParameter Annotation Demo",
@@ -144,7 +144,7 @@ public class Index
                     new Item("PageResetDemo", "PageReset Annotation Demo",
                             "Use of PageReset annotation to re-initialize page state"),
 
-                    new Item("TestOnlyServiceDemo", "Test Only Service Demo",
+                    new Item("TestOnlyServiceDemo", "Test Only NonAnnotatedServiceInterface Demo",
                             "IoC module available via web.xml configuration"),
 
                     new Item("RenderObjectExceptionDemo", "RenderObject Exception Demo",

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/AdvisorDef.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/AdvisorDef.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/AdvisorDef.java
index ef71125..30687e3 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/AdvisorDef.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/AdvisorDef.java
@@ -17,7 +17,7 @@ package org.apache.tapestry5.ioc;
 import org.apache.tapestry5.ioc.def.ServiceDef;
 
 /**
- * Definition of a service advisor, which (by default) is derived from a service advisor method. Service advisor methods
+ * Definition of a service advisor, which (by default) is derived from a service advisor method. NonAnnotatedServiceInterface advisor methods
  * are static or instance methods on module classes prefixed with "advise". When a service is realized, a list of
  * matching AdvisorDefs is generated, then ordered, and from each a {@link org.apache.tapestry5.ioc.ServiceAdvisor} is
  * obtained and invoked.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java
index 81d1f77..64ea9b5 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ObjectLocator.java
@@ -36,7 +36,7 @@ public interface ObjectLocator
      * transparent to the application).
      *
      * @param <T>
-     * @param serviceId        unique Service id used to locate the service object (may contain <em>symbols</em>,
+     * @param serviceId        unique NonAnnotatedServiceInterface id used to locate the service object (may contain <em>symbols</em>,
      *                         which
      *                         will be expanded), case is ignored
      * @param serviceInterface the interface implemented by the service (or an interface extended by the service

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java
index b3c190e..2ef70f0 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceResources.java
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry5.ioc;
 
+import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
 import org.slf4j.Logger;
 
 /**
@@ -34,6 +35,12 @@ public interface ServiceResources extends ObjectLocator, AnnotationAccess
     Class getServiceInterface();
 
     /**
+     * Returns the service implementation.
+     */
+    @IncompatibleChange(release = "5.4", details = "Added method for TAP5-2029")
+    Class getServiceImplementation();
+
+    /**
      * Returns a Logger appropriate for logging messages. This includes debug level messages about the creation and
      * configuration of the underlying service, as well as debug, warning, or error level messages from the service
      * itself. Often service interceptors will make use of the service's logger.
@@ -46,11 +53,4 @@ public interface ServiceResources extends ObjectLocator, AnnotationAccess
      */
     OperationTracker getTracker();
 
-    /**
-     * Returns null (as of 5.3).
-     * 
-     * @since 5.2.0
-     * @deprecated Deprecated in 5.3 with no replacement. May be removed in 5.4.
-     */
-    Class getImplementationClass();
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/EagerLoad.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/EagerLoad.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/EagerLoad.java
index f67c67d..7bf7b1b 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/EagerLoad.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/EagerLoad.java
@@ -24,7 +24,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * Marker annotation placed on a service builder method to indicate that the service should be eagerly loaded: realized
- * as if a service method had been invoked. Service realization invokes the service builder method and applys any
+ * as if a service method had been invoked. NonAnnotatedServiceInterface realization invokes the service builder method and applys any
  * decorators to the service.
  * <p/>
  * This annotation may also be placed directly on a service implementation class, when using autobuilding via the {@link

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/PreventServiceDecoration.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/PreventServiceDecoration.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/PreventServiceDecoration.java
index 6c78cb7..a97436f 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/PreventServiceDecoration.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/annotations/PreventServiceDecoration.java
@@ -26,7 +26,7 @@ import java.lang.annotation.*;
  * The annotation may also be placed on a module class, to indicate that all services defined for the module should not
  * allow decoration.
  * <p/>
- * Service decoration includes the decoration mechanism (from Tapestry 5.0) and the newer service advice mechanism (from
+ * NonAnnotatedServiceInterface decoration includes the decoration mechanism (from Tapestry 5.0) and the newer service advice mechanism (from
  * Tapestry 5.1).
  * <p/>
  * Generally, services that are used to advise or decorate other services (such as {@link org.apache.tapestry5.ioc.services.LoggingAdvisor}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/DecoratorDef.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/DecoratorDef.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/DecoratorDef.java
index 7c3c663..61595a8 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/DecoratorDef.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/DecoratorDef.java
@@ -36,7 +36,7 @@ import org.apache.tapestry5.ioc.ServiceResources;
  * the Security interceptor, which would delegate to the Transaction interceptor, which would finally delegate to the
  * core service implementation.
  * <p/>
- * Service decorators are part of the initial version of Tapestry IoC.  Starting in release 5.1, their use has been
+ * NonAnnotatedServiceInterface decorators are part of the initial version of Tapestry IoC.  Starting in release 5.1, their use has been
  * deprecated, in favor of {@link org.apache.tapestry5.ioc.AdvisorDef}, which is based on {@link
  * org.apache.tapestry5.ioc.services.AspectInterceptorBuilder}.
  * <p/>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef.java
index 7b31f8a..b04d4ff 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef.java
@@ -22,7 +22,7 @@ import org.apache.tapestry5.ioc.services.ServiceLifecycleSource;
 import java.util.Set;
 
 /**
- * Service definition derived, by default, from a service builder method. This has been extended in Tapestry 5.1 with
+ * NonAnnotatedServiceInterface definition derived, by default, from a service builder method. This has been extended in Tapestry 5.1 with
  * {@link org.apache.tapestry5.ioc.def.ServiceDef2}, which adds additional methods. Tapestry 5.3 added {@link ServiceDef3}.
  */
 @SuppressWarnings("rawtypes")
@@ -37,8 +37,8 @@ public interface ServiceDef
     ObjectCreator createServiceCreator(ServiceBuilderResources resources);
 
     /**
-     * Returns the service id, derived from the method name or the unqualified service interface name. Service ids must
-     * be unique among <em>all</em> services in all modules. Service ids are used in a heavy handed way to support
+     * Returns the service id, derived from the method name or the unqualified service interface name. NonAnnotatedServiceInterface ids must
+     * be unique among <em>all</em> services in all modules. NonAnnotatedServiceInterface ids are used in a heavy handed way to support
      * ultimate disambiguation, but their primary purpose is to support service contribution methods.
      */
     String getServiceId();

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef3.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef3.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef3.java
index 8f23cbb..bd7535c 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef3.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/def/ServiceDef3.java
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.ioc.def;
 
 import org.apache.tapestry5.ioc.AnnotationAccess;
+import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
 
 /**
  * Introduced for Tapestry 5.3, contains new methods to provide access to annotations on the class,
@@ -26,4 +27,14 @@ import org.apache.tapestry5.ioc.AnnotationAccess;
  */
 public interface ServiceDef3 extends ServiceDef2, AnnotationAccess
 {
+	
+    /**
+     * Returns the service implementation associated with this service. When creating the proxies
+     * for the service interface, the implementation of the service interface methods will
+     * receive the annotations of the corresponding method in the service interface.
+     * @since 5.4
+     */
+	@IncompatibleChange(release = "5.4", details = "Added method")
+    Class getServiceImplementation();
+
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/EagerLoadServiceProxy.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/EagerLoadServiceProxy.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/EagerLoadServiceProxy.java
index 5ad53cd..8b6c398 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/EagerLoadServiceProxy.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/EagerLoadServiceProxy.java
@@ -15,7 +15,7 @@
 package org.apache.tapestry5.ioc.internal;
 
 /**
- * Interface implemented by all service proxies. Service proxies are always {@link
+ * Interface implemented by all service proxies. NonAnnotatedServiceInterface proxies are always {@link
  * org.apache.tapestry5.ioc.services.RegistryShutdownListener}s, they also can be eager-load
  */
 public interface EagerLoadServiceProxy

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
index 85334f4..3c291e3 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ModuleImpl.java
@@ -22,6 +22,7 @@ import org.apache.tapestry5.ioc.internal.util.*;
 import org.apache.tapestry5.ioc.services.AspectDecorator;
 import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
 import org.apache.tapestry5.ioc.services.Status;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
 import org.apache.tapestry5.plastic.*;
 import org.slf4j.Logger;
 
@@ -279,7 +280,7 @@ public class ModuleImpl implements Module
                         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.",
+                                            "NonAnnotatedServiceInterface 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();
@@ -309,7 +310,7 @@ public class ModuleImpl implements Module
 
                     JustInTimeObjectCreator delegate = new JustInTimeObjectCreator(tracker, creator, serviceId);
 
-                    Object proxy = createProxy(resources, delegate);
+                    Object proxy = createProxy(resources, delegate, def.isPreventDecoration());
 
                     registry.addRegistryShutdownListener(delegate);
 
@@ -325,6 +326,7 @@ public class ModuleImpl implements Module
                     return proxy;
                 } catch (Exception ex)
                 {
+                    ex.printStackTrace();
                     throw new RuntimeException(IOCMessages.errorBuildingService(serviceId, def, ex), ex);
                 }
             }
@@ -448,7 +450,7 @@ public class ModuleImpl implements Module
         throw new RuntimeException(IOCMessages.instantiateBuilderError(moduleClass, fail), fail);
     }
 
-    private Object createProxy(ServiceResources resources, ObjectCreator creator)
+    private Object createProxy(ServiceResources resources, ObjectCreator creator, boolean preventDecoration)
     {
         String serviceId = resources.getServiceId();
         Class serviceInterface = resources.getServiceInterface();
@@ -457,13 +459,14 @@ public class ModuleImpl implements Module
 
         ServiceProxyToken token = SerializationSupport.createToken(serviceId);
 
-        return createProxyInstance(creator, token, serviceInterface, toString);
+        final Class serviceImplementation = preventDecoration || serviceInterface == TypeCoercer.class ? null : resources.getServiceImplementation();
+        return createProxyInstance(creator, token, serviceInterface, serviceImplementation, toString);
     }
 
     private Object createProxyInstance(final ObjectCreator creator, final ServiceProxyToken token,
-                                       final Class serviceInterface, final String description)
+                                       final Class serviceInterface, final Class serviceImplementation, final String description)
     {
-        ClassInstantiator instantiator = proxyFactory.createProxy(serviceInterface, new PlasticClassTransformer()
+        ClassInstantiator instantiator = proxyFactory.createProxy(serviceInterface, serviceImplementation, new PlasticClassTransformer()
         {
             public void transform(final PlasticClass plasticClass)
             {
@@ -588,4 +591,5 @@ public class ModuleImpl implements Module
     {
         return String.format("ModuleImpl[%s]", moduleDef.getLoggerName());
     }
+    
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
index 1170fe6..aecbab9 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java
@@ -445,7 +445,7 @@ public class RegistryImpl implements Registry, InternalRegistry, ServiceProxyPro
         Module module = serviceIdToModule.get(serviceId);
 
         if (module == null)
-            throw new UnknownValueException(String.format("Service id '%s' is not defined by any module.", serviceId),
+            throw new UnknownValueException(String.format("NonAnnotatedServiceInterface id '%s' is not defined by any module.", serviceId),
                     new AvailableValues("Defined service ids", serviceIdToModule));
 
         return module;
@@ -1093,7 +1093,7 @@ public class RegistryImpl implements Registry, InternalRegistry, ServiceProxyPro
 
         getService(UpdateListenerHub.class).addUpdateListener(creator);
 
-        return proxyFactory.createProxy(interfaceClass, (ObjectCreator<T>) creator,
+        return proxyFactory.createProxy(interfaceClass, implementationClass, (ObjectCreator<T>) creator,
                 String.format("<Autoreload proxy %s(%s)>", implementationClass.getName(), interfaceClass.getName()));
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java
index 2bf35f7..2473a29 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java
@@ -83,6 +83,6 @@ public class ReloadableObjectCreatorSource implements ObjectCreatorSource
             reloadableCreator.createObject();
         }
 
-        return proxyFactory.createProxy(serviceInterfaceClass, reloadableCreator, getDescription());
+        return proxyFactory.createProxy(serviceInterfaceClass, resources.getServiceImplementation(), reloadableCreator, getDescription());
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java
index 93baf33..b1d0232 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java
@@ -45,7 +45,7 @@ public class ReloadableServiceImplementationObjectCreator extends AbstractReload
 
         if (constructor == null)
             throw new RuntimeException(String.format(
-                    "Service implementation class %s does not have a suitable public constructor.", clazz.getName()));
+                    "NonAnnotatedServiceInterface implementation class %s does not have a suitable public constructor.", clazz.getName()));
 
         ObjectCreator constructorServiceCreator = new ConstructorServiceCreator(resources, constructor.toString(),
                 constructor);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java
index 3baa05c..9575f32 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceDefImpl.java
@@ -99,6 +99,11 @@ public class ServiceDefImpl implements ServiceDef3
         return serviceInterface;
     }
 
+    public Class getServiceImplementation()
+    {
+        return serviceImplementation;
+    }
+
     public String getServiceScope()
     {
         return scope;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java
index 3b64db3..8f5aebe 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceResourcesImpl.java
@@ -72,6 +72,11 @@ public class ServiceResourcesImpl extends ObjectLocatorImpl implements ServiceBu
         return serviceDef.getServiceInterface();
     }
 
+    public Class getServiceImplementation()
+    {
+        return serviceDef.getServiceImplementation();
+    }
+
     public Logger getLogger()
     {
         return logger;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java
index 79b99b9..66b3685 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectDecoratorImpl.java
@@ -38,7 +38,7 @@ public class AspectDecoratorImpl implements AspectDecorator
 
     public <T> AspectInterceptorBuilder<T> createBuilder(Class<T> serviceInterface, final T delegate, String description)
     {
-        return createBuilder(serviceInterface, delegate, new AnnotationAccessImpl(serviceInterface), description);
+        return createBuilder(serviceInterface, delegate, new AnnotationAccessImpl(delegate.getClass()), description);
     }
 
     public <T> AspectInterceptorBuilder<T> createBuilder(final Class<T> serviceInterface, final T delegate,

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java
index 9850b9b..b2807d0 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/AspectInterceptorBuilderImpl.java
@@ -43,7 +43,7 @@ public class AspectInterceptorBuilderImpl<T> extends AbtractAspectInterceptorBui
 
         this.serviceInterface = serviceInterface;
 
-        transformation = plasticProxyFactory.createProxyTransformation(serviceInterface);
+        transformation = plasticProxyFactory.createProxyTransformation(serviceInterface, (Class<? extends T>) delegate.getClass());
         plasticClass = transformation.getPlasticClass();
 
         plasticClass.addToString(description);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PerThreadServiceLifecycle.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PerThreadServiceLifecycle.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PerThreadServiceLifecycle.java
index 5b17ce0..ae606d2 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PerThreadServiceLifecycle.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PerThreadServiceLifecycle.java
@@ -25,7 +25,7 @@ import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
  * Allows a service to exist "per thread" (in each thread). Creates a proxy that delegates to a per-thread instance.
  * <p/>
  * This scheme ensures that, although the service builder method will be invoked many times over the life of the
- * application, the service decoration process occurs only once. The final calling chain is: Service Proxy --&gt;
+ * application, the service decoration process occurs only once. The final calling chain is: NonAnnotatedServiceInterface Proxy --&gt;
  * Interceptor(s) (from Decorators) --&gt; Advise Proxy (from Advisiors) --&gt; PerThread Proxy --&gt; (per thread)
  * instance.
  */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
index a5f5a13..a7bb67a 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
@@ -19,6 +19,7 @@ import org.apache.tapestry5.internal.plastic.asm.Type;
 import org.apache.tapestry5.internal.plastic.asm.tree.*;
 import org.apache.tapestry5.ioc.Location;
 import org.apache.tapestry5.ioc.ObjectCreator;
+import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
@@ -59,22 +60,39 @@ public class PlasticProxyFactoryImpl implements PlasticProxyFactory
         return manager.getClassLoader();
     }
 
+    public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback)
+    {
+        return manager.createProxy(interfaceType, implementationType, callback);
+    }
+    
     public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback)
     {
         return manager.createProxy(interfaceType, callback);
     }
+    
+    
+    public <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType,
+            Class<? extends T> implementationType)
+    {
+        return manager.createProxyTransformation(interfaceType, implementationType);
+    }
 
-    public PlasticClassTransformation createProxyTransformation(Class interfaceType)
+    public <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType)
     {
-        return manager.createProxyTransformation(interfaceType);
+        return createProxyTransformation(interfaceType, null);
     }
 
     public <T> T createProxy(final Class<T> interfaceType, final ObjectCreator<T> creator, final String description)
+    {   return createProxy(interfaceType, null, creator, description);
+    }
+    
+    public <T> T createProxy(final Class<T> interfaceType, final Class<? extends T> implementationType,
+            final ObjectCreator<T> creator, final String description)
     {
         assert creator != null;
         assert InternalUtils.isNonBlank(description);
 
-        ClassInstantiator<T> instantiator = createProxy(interfaceType, new PlasticClassTransformer()
+        ClassInstantiator<T> instantiator = createProxy(interfaceType, implementationType, new PlasticClassTransformer()
         {
             public void transform(PlasticClass plasticClass)
             {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
index 11c22c9..1122293 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
@@ -30,6 +30,7 @@ import org.slf4j.Logger;
 
 import javax.annotation.PostConstruct;
 import javax.inject.Named;
+
 import java.io.Closeable;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
@@ -897,6 +898,11 @@ public class InternalUtils
             {
                 return toAnnotationProvider(findMethod(getServiceInterface(), methodName, argumentTypes));
             }
+            
+			public Class getServiceImplementation() 
+			{
+				return null;
+			}
 
             // ServiceDef2 methods:
 
@@ -934,6 +940,7 @@ public class InternalUtils
             {
                 return sd2.isEagerLoad();
             }
+
         };
     }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/WrongConfigurationTypeGuard.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/WrongConfigurationTypeGuard.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/WrongConfigurationTypeGuard.java
index b18cb0a..db2de0e 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/WrongConfigurationTypeGuard.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/WrongConfigurationTypeGuard.java
@@ -37,7 +37,7 @@ public class WrongConfigurationTypeGuard implements InjectionResources
     public <T> T findResource(Class<T> type, Type genericType)
     {
         if (type == guardType)
-            throw new IllegalArgumentException(String.format("Service '%s' is configured using %s, not %s.",
+            throw new IllegalArgumentException(String.format("NonAnnotatedServiceInterface '%s' is configured using %s, not %s.",
                                                              serviceId,
                                                              expectedType.getName(), guardType.getName()));
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java
index be0c43e..2b79b0a 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/LoggingDecorator.java
@@ -17,7 +17,7 @@ package org.apache.tapestry5.ioc.services;
 import org.slf4j.Logger;
 
 /**
- * Service that can create a logging interceptor that wraps around a service implementation (or interceptor). The
+ * NonAnnotatedServiceInterface that can create a logging interceptor that wraps around a service implementation (or interceptor). The
  * interceptor works with the service's log to log, at debug level, method entry (with arguments), method exit (with
  * return value, if any) as well as any thrown exceptions.
  * <p/>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
index 81e1eac..7addde0 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
@@ -16,6 +16,7 @@ package org.apache.tapestry5.ioc.services;
 
 import org.apache.tapestry5.ioc.Location;
 import org.apache.tapestry5.ioc.ObjectCreator;
+import org.apache.tapestry5.ioc.annotations.IncompatibleChange;
 import org.apache.tapestry5.plastic.ClassInstantiator;
 import org.apache.tapestry5.plastic.PlasticClassListenerHub;
 import org.apache.tapestry5.plastic.PlasticClassTransformation;
@@ -51,6 +52,21 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub
     <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback);
 
     /**
+     * Creates a proxy object that implements the indicated interface and indicated service implementation type,
+     * then invokes the callback to further configure the proxy.
+     *
+     * @param interfaceType
+     *         interface implemented by proxy
+     * @param implementationType
+     *         a class that implements the interfaceType. It can be null.
+     * @param callback
+     *         configures the proxy
+     * @return instantiator that can be used to create an instance of the proxy class
+     */
+    @IncompatibleChange(release = "5.4", details = "TAP5-2029")
+    <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback);
+
+    /**
      * Creates the underlying {@link PlasticClassTransformation} for an interface proxy. This should only be
      * used in the cases where encapsulating the PlasticClass construction into a {@linkplain PlasticClassTransformer
      * callback} is not feasible (which is the case for some of the older APIs inside Tapestry IoC).
@@ -62,6 +78,21 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub
     <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType);
 
     /**
+     * Creates the underlying {@link PlasticClassTransformation} for an interface proxy with a given
+     * implementation class. This should only be
+     * used in the cases where encapsulating the PlasticClass construction into a {@linkplain PlasticClassTransformer
+     * callback} is not feasible (which is the case for some of the older APIs inside Tapestry IoC).
+     *
+     * @param interfaceType
+     *         class proxy will extend from
+     * @param implementationType
+     *         a class that implements the interfaceType. It can be null.
+     * @return transformation from which an instantiator may be created
+     */
+    @IncompatibleChange(release = "5.4", details = "TAP5-2029")
+    <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType, Class<? extends T> implementationType);
+
+    /**
      * Creates a proxy instance that delegates all methods through a corresponding
      * ObjectCreator. Each method invocation on the proxy will route through {@link ObjectCreator#createObject()} (the
      * creator implementation may decide to
@@ -78,6 +109,27 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub
      * @return proxy instance
      */
     <T> T createProxy(Class<T> interfaceType, ObjectCreator<T> creator, String description);
+    
+    /**
+     * Creates a proxy instance that delegates all methods through a corresponding
+     * ObjectCreator. Each method invocation on the proxy will route through {@link ObjectCreator#createObject()} (the
+     * creator implementation may decide to
+     * cache the return value as appropriate).
+     *
+     * @param <T>
+     *         type of proxy
+     * @param interfaceType
+     *         interface class for proxy
+     * @param implementationType
+     *         class that implements the interface type. It may be null
+     * @param creator
+     *         object responsible for creating the real object
+     * @param description
+     *         the <code>toString()</code> of the proxy
+     * @return proxy instance
+     */
+    @IncompatibleChange(release = "5.4", details = "TAP5-2029")
+    <T> T createProxy(Class<T> interfaceType, Class<? extends T> implementationType, ObjectCreator<T> creator, String description);
 
     /**
      * Converts a method to a {@link Location}, which includes information about the source file name and line number.

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/RegistryShutdownListener.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/RegistryShutdownListener.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/RegistryShutdownListener.java
index edf3b0b..e7633c4 100644
--- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/RegistryShutdownListener.java
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/RegistryShutdownListener.java
@@ -25,7 +25,7 @@ import java.util.EventListener;
 public interface RegistryShutdownListener extends EventListener
 {
     /**
-     * Invoked when the registry shuts down, giving services a chance to perform any final operations. Service
+     * Invoked when the registry shuts down, giving services a chance to perform any final operations. NonAnnotatedServiceInterface
      * implementations should not attempt to invoke methods on other services (via proxies) as the service proxies may
      * themselves be shutdown.
      */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/test/groovy/ioc/specs/BridgeBuilderSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/BridgeBuilderSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/BridgeBuilderSpec.groovy
index 402d3a9..204a584 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/BridgeBuilderSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/BridgeBuilderSpec.groovy
@@ -60,7 +60,7 @@ class BridgeBuilderSpec extends AbstractSharedRegistrySpecification {
 
     ToStringService service = new ToStringService() {
 
-      String toString() { "Service" }
+      String toString() { "NonAnnotatedServiceInterface" }
     }
 
     ToStringFilter filter = new ToStringFilter() {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/test/groovy/ioc/specs/ContributionDefImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/ContributionDefImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/ContributionDefImplSpec.groovy
index e85c516..fe498c7 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/ContributionDefImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/ContributionDefImplSpec.groovy
@@ -159,7 +159,7 @@ class ContributionDefImplSpec extends Specification {
 
     RuntimeException e = thrown()
 
-    e.message.contains "Service 'Foo' is configured using org.apache.tapestry5.ioc.Configuration, not org.apache.tapestry5.ioc.MappedConfiguration."
+    e.message.contains "NonAnnotatedServiceInterface 'Foo' is configured using org.apache.tapestry5.ioc.Configuration, not org.apache.tapestry5.ioc.MappedConfiguration."
   }
 
   def "ordered configuration injects and contributes a service via @InjectService"() {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/test/groovy/ioc/specs/DefaultModuleDefImplSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/DefaultModuleDefImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/DefaultModuleDefImplSpec.groovy
index d017dfc..9682a4b 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/DefaultModuleDefImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/DefaultModuleDefImplSpec.groovy
@@ -144,7 +144,7 @@ class DefaultModuleDefImplSpec extends Specification {
 
     RuntimeException ex = thrown()
 
-    ex.message.contains "Service Fred (defined by ${ServiceIdConflictMethodModule.name}.buildFred()"
+    ex.message.contains "NonAnnotatedServiceInterface Fred (defined by ${ServiceIdConflictMethodModule.name}.buildFred()"
     ex.message.contains "conflicts with previously defined service defined by ${ServiceIdConflictMethodModule.name}.buildFred(Object)"
   }
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/test/groovy/ioc/specs/PerThreadScopeSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/PerThreadScopeSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/PerThreadScopeSpec.groovy
index d79c6ce..b771e4b 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/PerThreadScopeSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/PerThreadScopeSpec.groovy
@@ -57,7 +57,7 @@ class PerThreadScopeSpec extends AbstractRegistrySpecification {
     Exception e = thrown()
 
     e.message.contains "Error building service proxy for service 'ScopeRequiresAProxyAndNoInterfaceIsProvided'"
-    e.message.contains "Service scope 'perthread' requires a proxy"
+    e.message.contains "NonAnnotatedServiceInterface scope 'perthread' requires a proxy"
   }
 
   def "ensure that perthread services are discarded by cleanupThread()"() {

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/4a818e35/tapestry-ioc/src/test/groovy/ioc/specs/RegistryConstructionAndRuntimeErrorsSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/RegistryConstructionAndRuntimeErrorsSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/RegistryConstructionAndRuntimeErrorsSpec.groovy
index a746d07..fc8ca85 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/RegistryConstructionAndRuntimeErrorsSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/RegistryConstructionAndRuntimeErrorsSpec.groovy
@@ -20,7 +20,7 @@ class RegistryConstructionAndRuntimeErrorsSpec extends AbstractRegistrySpecifica
 
     RuntimeException ex = thrown()
 
-    ex.message.startsWith "Service id 'Fred' has already been defined by"
+    ex.message.startsWith "NonAnnotatedServiceInterface id 'Fred' has already been defined by"
 
     // Can't check entire message, can't guarantee what order modules will be processed in
   }