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 2019/02/24 03:11:14 UTC

[tapestry-5] branch 5.4.x updated (f477935 -> b8f4a67)

This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a change to branch 5.4.x
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git.


    from f477935  TAP5-2075 - Fix tests
     new 08b03f4  Revert "TAP5-2582: Service creation for Hibernate Session results in"
     new b8f4a67  TAP5-2582: Service creation for Hibernate Session results in

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../internal/services/PlasticProxyFactoryImpl.java |  14 +-
 .../ioc/services/PlasticProxyFactory.java          |  15 ++
 .../internal/plastic/PlasticClassImpl.java         | 203 +++++++++------------
 .../tapestry5/plastic/MethodDescription.java       |  15 --
 .../apache/tapestry5/plastic/PlasticManager.java   |  56 +++++-
 tapestry-ioc/build.gradle                          |   6 +-
 .../apache/tapestry5/ioc/internal/ModuleImpl.java  |   6 +-
 .../groovy/ioc/specs/GeneralIntegrationSpec.groovy |  24 +++
 .../tapestry5/ioc/internal/AdviceModule.java       |  17 --
 9 files changed, 197 insertions(+), 159 deletions(-)


[tapestry-5] 01/02: Revert "TAP5-2582: Service creation for Hibernate Session results in"

Posted by th...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch 5.4.x
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 08b03f47676ee10b827ae65f81c50a8a3e244e94
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sat Feb 23 20:13:37 2019 -0300

    Revert "TAP5-2582: Service creation for Hibernate Session results in"
    
    This reverts commit d7cc7c7daed3e8d38472d211ceecfa2218793503.
---
 .../internal/plastic/PlasticClassImpl.java         | 124 ++-------------------
 .../tapestry5/plastic/MethodDescription.java       |  15 ---
 .../org/apache/tapestry5/plastic/PlasticClass.java |  11 --
 tapestry-ioc/build.gradle                          |   6 +-
 .../apache/tapestry5/ioc/internal/ModuleImpl.java  |   9 +-
 .../specs/AspectInterceptorBuilderImplSpec.groovy  |   2 +-
 .../tapestry5/ioc/internal/AdviceModule.java       |  21 ----
 7 files changed, 15 insertions(+), 173 deletions(-)

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 9683e1c..264825a 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
@@ -621,37 +621,11 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
 
         introduceInterface(interfaceType);
 
-        // TAP5-2582: avoiding adding/delegating the same method more than once
-//        for (Method m : interfaceType.getMethods())
-//        {
-//            introduceMethod(m).delegateTo(field);
-//        }
-        
-        Map<MethodSignature, MethodDescription> map = createMethodSignatureMap(interfaceType);
-        for (MethodSignature methodSignature : map.keySet())
+        for (Method m : interfaceType.getMethods())
         {
-            introduceMethod(map.get(methodSignature)).delegateTo(field);
+            introduceMethod(m).delegateTo(field);
         }
-        
-        return this;
-    }
-    
-    @Override
-    public PlasticClass proxyInterface(Class interfaceType, PlasticMethod method)
-    {
-        check();
 
-        assert method != null;
-
-        introduceInterface(interfaceType);
-
-        // TAP5-2582: avoiding adding/delegating the same method more than once
-        Map<MethodSignature, MethodDescription> map = createMethodSignatureMap(interfaceType);
-        for (MethodSignature methodSignature : map.keySet())
-        {
-            introduceMethod(map.get(methodSignature)).delegateTo(method);
-        }
-        
         return this;
     }
 
@@ -1436,7 +1410,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
 
         if (!interfaceType.isInterface())
             throw new IllegalArgumentException(String.format(
-                    "Class %s is not an interface; only interfaces may be introduced.", interfaceType.getName()));
+                    "Class %s is not an interface; ony interfaces may be introduced.", interfaceType.getName()));
 
         String interfaceName = nameCache.toInternalName(interfaceType);
 
@@ -1457,19 +1431,14 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
         addClassAnnotations(interfaceClassNode);
 
         Set<PlasticMethod> introducedMethods = new HashSet<PlasticMethod>();
-        
-        Map<MethodSignature, MethodDescription> map = createMethodSignatureMap(interfaceType);
-        
-        // for (Method m : interfaceType.getMethods())
-	for (MethodSignature methodSignature : map.keySet())
+
+        for (Method m : interfaceType.getMethods())
         {
-            // MethodDescription description = new MethodDescription(m);
-            final MethodDescription description = map.get(methodSignature);
+            MethodDescription description = new MethodDescription(m);
 
-            if (!isMethodImplemented(description) && !isDefaultMethod(methodSignature.method))
+            if (!isMethodImplemented(description) && !isDefaultMethod(m))
             {
-                // introducedMethods.add(introduceMethod(m));
-                introducedMethods.add(introduceMethod(description));
+                introducedMethods.add(introduceMethod(m));
             }
         }
 
@@ -1478,83 +1447,6 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
         return introducedMethods;
     }
 
-    private Map<MethodSignature, MethodDescription> createMethodSignatureMap(Class interfaceType) {
-	// TAP-2582: preprocessing the method list so we don't add duplicated
-        // methods, something that happens when an interface has superinterfaces
-        // and they define the same method signature.
-        // In addition, we collect all the thrown checked exceptions, just in case.
-        Map<MethodSignature, MethodDescription> map = new HashMap<MethodSignature, MethodDescription>();
-        for (Method m : interfaceType.getMethods())
-        {
-            final MethodSignature methodSignature = new MethodSignature(m);
-            final MethodDescription newMethodDescription = new MethodDescription(m);
-            if (!map.containsKey(methodSignature)) 
-            {
-		map.put(methodSignature, newMethodDescription);
-            }
-            else 
-            {
-        	if (newMethodDescription.checkedExceptionTypes != null && newMethodDescription.checkedExceptionTypes.length > 0)
-        	{
-        	    final MethodDescription methodDescription = map.get(methodSignature);
-                    final Set<String> checkedExceptionTypes = new HashSet<String>();
-                    checkedExceptionTypes.addAll(Arrays.asList(methodDescription.checkedExceptionTypes));
-                    checkedExceptionTypes.addAll(Arrays.asList(newMethodDescription.checkedExceptionTypes));
-                    map.put(methodSignature, new MethodDescription(
-                	    methodDescription, 
-                	    checkedExceptionTypes.toArray(new String[checkedExceptionTypes.size()])));
-        	}
-            }
-        }
-	return map;
-    }
-    
-    final private static class MethodSignature implements Comparable<MethodSignature>{
-	
-	final private Method method;
-	final private String name;
-	final private Class<?>[] parameterTypes;
-	
-	public MethodSignature(Method method) {
-	    this.method = method;
-	    this.name = method.getName();
-	    this.parameterTypes = method.getParameterTypes();
-	}
-
-	@Override
-	public int hashCode() {
-	    final int prime = 31;
-	    int result = 1;
-	    result = prime * result + Arrays.hashCode(parameterTypes);
-	    result = prime * result + ((name == null) ? 0 : name.hashCode());
-	    return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-	    if (this == obj)
-		return true;
-	    if (obj == null)
-		return false;
-	    if (getClass() != obj.getClass())
-		return false;
-	    MethodSignature other = (MethodSignature) obj;
-	    if (!Arrays.equals(parameterTypes, other.parameterTypes))
-		return false;
-	    if (name == null) {
-		if (other.name != null)
-		    return false;
-	    } else if (!name.equals(other.name))
-		return false;
-	    return true;
-	}
-
-	@Override
-	public int compareTo(MethodSignature o) {
-	    return method.getName().compareTo(o.method.getName());
-	}
-    }
-
     @Override
     public PlasticClass addToString(final String toStringValue)
     {
diff --git a/plastic/src/main/java/org/apache/tapestry5/plastic/MethodDescription.java b/plastic/src/main/java/org/apache/tapestry5/plastic/MethodDescription.java
index 5f8b88f..e0b7d2a 100644
--- a/plastic/src/main/java/org/apache/tapestry5/plastic/MethodDescription.java
+++ b/plastic/src/main/java/org/apache/tapestry5/plastic/MethodDescription.java
@@ -72,21 +72,6 @@ public class MethodDescription implements Comparable<MethodDescription>
     {
         this(Modifier.PUBLIC, returnType, methodName, argumentTypes, null, null);
     }
-    
-    /**
-     * Convenience constructor for copying a MethodDescription with
-     * different exception types.
-     * @since 5.4.4
-     */
-    public MethodDescription(MethodDescription description, String[] checkedExceptionTypes)
-    {
-	this.argumentTypes = description.argumentTypes;
-	this.checkedExceptionTypes = checkedExceptionTypes;
-	this.genericSignature = description.genericSignature;
-	this.methodName = description.methodName;
-	this.modifiers = description.modifiers;
-	this.returnType = description.returnType;
-    }
 
     /**
      * @param modifiers
diff --git a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
index 2168456..e212fe5 100644
--- a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
+++ b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
@@ -163,17 +163,6 @@ public interface PlasticClass extends AnnotationAccess
      * @return this plastic class, for further configuration
      */
     PlasticClass proxyInterface(Class interfaceType, PlasticField field);
-    
-    /**
-     * Introduces the interface, and then invokes {@link PlasticMethod#delegateTo(PlasticMethod)} on each method
-     * defined by the interface.
-     *
-     * @param interfaceType defines the interface to proxy
-     * @param method        method to delegate to
-     * @return this plastic class, for further configuration
-     * @since 5.4.4
-     */
-    PlasticClass proxyInterface(Class interfaceType, PlasticMethod method);
 
     /**
      * Conditionally adds an implementation of <code>toString()</code> to the class, but only if it is not already
diff --git a/tapestry-ioc/build.gradle b/tapestry-ioc/build.gradle
index b208818..8113a23 100644
--- a/tapestry-ioc/build.gradle
+++ b/tapestry-ioc/build.gradle
@@ -15,10 +15,8 @@ dependencies {
 
     compile "org.slf4j:slf4j-api:${versions.slf4j}"
 
-    testCompile "org.apache.commons:commons-lang3:3.4"
-    testCompile "org.hibernate:hibernate-core:5.2.10.Final"
-    testRuntime "org.hsqldb:hsqldb:2.2.8"
-    
+    testCompile "commons-lang:commons-lang:2.6"
+
     provided "org.testng:testng:${versions.testng}", { transitive = false }
 }
 
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 51f864c..48bf24d 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
@@ -509,11 +509,10 @@ public class ModuleImpl implements Module
                     }
                 });
 
-                plasticClass.proxyInterface(serviceInterface, delegateMethod);
-//                for (Method m : serviceInterface.getMethods())
-//                {
-//                    plasticClass.introduceMethod(m).delegateTo(delegateMethod);
-//                }
+                for (Method m : serviceInterface.getMethods())
+                {
+                    plasticClass.introduceMethod(m).delegateTo(delegateMethod);
+                }
 
                 plasticClass.introduceMethod(WRITE_REPLACE).changeImplementation(new InstructionBuilderCallback()
                 {
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy
index b614c38..e543482 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy
@@ -1,6 +1,6 @@
 package ioc.specs
 
-import org.apache.commons.lang3.StringUtils
+import org.apache.commons.lang.StringUtils
 import org.apache.tapestry5.ioc.internal.services.TextTransformer
 import org.apache.tapestry5.ioc.services.AspectDecorator
 import org.apache.tapestry5.plastic.MethodAdvice
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
index f943152..0e0a186 100644
--- a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
@@ -13,15 +13,9 @@
 // limitations under the License.
 package org.apache.tapestry5.ioc.internal;
 
-
 import org.apache.tapestry5.ioc.MethodAdviceReceiver;
-import org.apache.tapestry5.ioc.ObjectLocator;
-import org.apache.tapestry5.ioc.Registry;
-import org.apache.tapestry5.ioc.RegistryBuilder;
 import org.apache.tapestry5.ioc.ServiceBinder;
 import org.apache.tapestry5.ioc.annotations.Advise;
-import org.hibernate.Session;
-import org.hibernate.cfg.Configuration;
 
 public class AdviceModule
 {
@@ -51,19 +45,4 @@ public class AdviceModule
             final MethodAdviceReceiver methodAdviceReceiver) {
         methodAdviceReceiver.adviseAllMethods(new TestAdvice());
     }
-    
-//    public static void main(String[] args) {
-//	Registry registry = RegistryBuilder.buildAndStartupRegistry(AdviceModule.class);
-//	Session session = registry.getService(Session.class);
-//    }
-    
-    // TAP5-2582
-    public static Session buildHibernateSession(
-	    ObjectLocator objectLocator
-	) {
-	    return new Configuration()
-	        .configure("hibernate.cfg.xml")
-	        .buildSessionFactory()
-	        .openSession();
-	}
 }


[tapestry-5] 02/02: TAP5-2582: Service creation for Hibernate Session results in

Posted by th...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

thiagohp pushed a commit to branch 5.4.x
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit b8f4a672fe5a5a6709bb5ec7cd89c0c7ff0cf0be
Author: Thiago H. de Paula Figueiredo <th...@arsmachina.com.br>
AuthorDate: Sun Feb 24 00:10:42 2019 -0300

    TAP5-2582: Service creation for Hibernate Session results in
    
    ClassFormatError: Duplicate method name&signature
---
 .../internal/services/PlasticProxyFactoryImpl.java | 14 ++-
 .../ioc/services/PlasticProxyFactory.java          | 15 ++++
 .../internal/plastic/PlasticClassImpl.java         | 99 ++++++++++++++++++++--
 .../org/apache/tapestry5/plastic/PlasticClass.java | 11 +++
 .../apache/tapestry5/plastic/PlasticManager.java   | 56 +++++++++++-
 .../apache/tapestry5/ioc/internal/ModuleImpl.java  |  7 +-
 .../specs/AspectInterceptorBuilderImplSpec.groovy  |  2 +-
 .../groovy/ioc/specs/GeneralIntegrationSpec.groovy | 24 ++++++
 .../tapestry5/ioc/internal/AdviceModule.java       |  4 +
 9 files changed, 214 insertions(+), 18 deletions(-)

diff --git a/beanmodel/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java b/beanmodel/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
index dc5397c..f1b3f67 100644
--- a/beanmodel/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
+++ b/beanmodel/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java
@@ -65,16 +65,24 @@ public class PlasticProxyFactoryImpl implements PlasticProxyFactory
     @Override
     public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback)
     {
-        return manager.createProxy(interfaceType, implementationType, callback);
+        return createProxy(interfaceType, implementationType, callback, true);
     }
-    
+
+    @Override
+    public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType,
+            Class<? extends T> implementationType,
+            PlasticClassTransformer callback,
+            boolean introduceInterface) {
+        return manager.createProxy(interfaceType, implementationType, callback, introduceInterface);
+    }
+
+
     @Override
     public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback)
     {
         return manager.createProxy(interfaceType, callback);
     }
     
-    
     @Override
     public <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType,
             Class<? extends T> implementationType)
diff --git a/commons/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java b/commons/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
index 75e93e4..99bcc55 100644
--- a/commons/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
+++ b/commons/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java
@@ -63,6 +63,20 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub
      *         configures the proxy
      * @return instantiator that can be used to create an instance of the proxy class
      */
+    @IncompatibleChange(release = "5.4.5", details = "TAP5-2528")
+    <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback, boolean introduceInterface);
+
+    /**
+     * Same as <code>createProxy(interfacetype, implementationType, callback, true)</code>
+     *
+     * @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);
 
@@ -156,4 +170,5 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub
      * @since 5.3.3
      */
     void clearCache();
+
 }
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 264825a..a7c1fc5 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
@@ -621,7 +621,7 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
 
         introduceInterface(interfaceType);
 
-        for (Method m : interfaceType.getMethods())
+        for (Method m : getUniqueMethods(interfaceType))
         {
             introduceMethod(m).delegateTo(field);
         }
@@ -968,7 +968,6 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
     public PlasticMethod introduceMethod(Method method)
     {
         check();
-
         return introduceMethod(new MethodDescription(method));
     }
 
@@ -1401,9 +1400,13 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
         return new InstructionBuilderImpl(description, mn, nameCache);
     }
 
-    @Override
     public Set<PlasticMethod> introduceInterface(Class interfaceType)
     {
+        return introduceInterface(interfaceType, null);
+    }
+    
+    private Set<PlasticMethod> introduceInterface(Class interfaceType, PlasticMethod method)
+    {
         check();
 
         assert interfaceType != null;
@@ -1431,14 +1434,22 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
         addClassAnnotations(interfaceClassNode);
 
         Set<PlasticMethod> introducedMethods = new HashSet<PlasticMethod>();
+        Set<Method> alreadyIntroducedMethods = new HashSet<>();
 
-        for (Method m : interfaceType.getMethods())
+        Method[] sortedMethods = interfaceType.getMethods();
+        Arrays.sort(sortedMethods, METHOD_COMPARATOR);
+        for (Method m : sortedMethods)
         {
             MethodDescription description = new MethodDescription(m);
 
-            if (!isMethodImplemented(description) && !isDefaultMethod(m))
+            if (!isMethodImplemented(description) && !isDefaultMethod(m) && !contains(alreadyIntroducedMethods, m))
             {
-                introducedMethods.add(introduceMethod(m));
+                PlasticMethod introducedMethod = introduceMethod(m);
+                introducedMethods.add(introducedMethod);
+                if (method != null) {
+                    introducedMethod.delegateTo(method);
+                }
+                alreadyIntroducedMethods.add(m);
             }
         }
 
@@ -1446,6 +1457,30 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
 
         return introducedMethods;
     }
+    
+    @Override
+    public PlasticClass proxyInterface(Class interfaceType, PlasticMethod method)
+    {
+        check();
+        assert method != null;
+
+        introduceInterface(interfaceType, method);
+        
+        return this;
+    }
+
+    private boolean contains(Set<Method> alreadyIntroducedMethods, Method m) {
+        boolean contains = false;
+        for (Method method : alreadyIntroducedMethods) 
+        {
+            if (METHOD_COMPARATOR.compare(method, m) == 0)
+            {
+                contains = true;
+                break;
+            }
+        }
+        return false;
+    }
 
     @Override
     public PlasticClass addToString(final String toStringValue)
@@ -1525,6 +1560,58 @@ public class PlasticClassImpl extends Lockable implements PlasticClass, Internal
             pool.setFieldReadInstrumentation(classNode.name, fieldName, fi);
         }
     }
+    
+    final private MethodComparator METHOD_COMPARATOR = new MethodComparator();
+    
+    final private class MethodComparator implements Comparator<Method> 
+    {
+
+        @Override
+        public int compare(Method o1, Method o2) 
+        {
+            
+            int comparison = o1.getName().compareTo(o2.getName());
+            
+            if (comparison == 0) 
+            {
+                comparison = o1.getParameterTypes().length - o2.getParameterTypes().length;
+            }
+            
+            if (comparison == 0) 
+            {
+                final int count = o1.getParameterTypes().length;
+                for (int i = 0; i < count; i++) 
+                {
+                    Class p1 = o1.getParameterTypes()[i];
+                    Class p2 = o1.getParameterTypes()[i];
+                    if (!p1.equals(p2)) 
+                    {
+                        comparison = p1.getName().compareTo(p2.getName());
+                        break;
+                    }
+                }
+            }
+            return comparison;
+        }
+    }
+    
+    private List<Method> getUniqueMethods(Class interfaceType) 
+    {
+        final List<Method> unique = new ArrayList<>(Arrays.asList(interfaceType.getMethods()));
+        Collections.sort(unique, METHOD_COMPARATOR);
+        Method last = null;
+        Iterator<Method> iterator = unique.iterator();
+        while (iterator.hasNext()) 
+        {
+            Method m = iterator.next();
+            if (last != null && METHOD_COMPARATOR.compare(m, last) == 0)
+            {
+                last = m;
+                iterator.remove();
+            }
+        }
+        return unique;
+    }
 
     @Override
     public String toString()
diff --git a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
index e212fe5..2168456 100644
--- a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
+++ b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticClass.java
@@ -163,6 +163,17 @@ public interface PlasticClass extends AnnotationAccess
      * @return this plastic class, for further configuration
      */
     PlasticClass proxyInterface(Class interfaceType, PlasticField field);
+    
+    /**
+     * Introduces the interface, and then invokes {@link PlasticMethod#delegateTo(PlasticMethod)} on each method
+     * defined by the interface.
+     *
+     * @param interfaceType defines the interface to proxy
+     * @param method        method to delegate to
+     * @return this plastic class, for further configuration
+     * @since 5.4.4
+     */
+    PlasticClass proxyInterface(Class interfaceType, PlasticMethod method);
 
     /**
      * Conditionally adds an implementation of <code>toString()</code> to the class, but only if it is not already
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 5f31755..74acf21 100644
--- a/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
+++ b/plastic/src/main/java/org/apache/tapestry5/plastic/PlasticManager.java
@@ -234,6 +234,21 @@ public class PlasticManager implements PlasticClassListenerHub
      * 
      * @param interfaceType
      *            class to extend from, which must be a class, not an interface
+     * @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)
+     */
+    public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback, boolean introduceInterface)
+    {
+        return createProxy(interfaceType, null, callback, introduceInterface);
+    }
+
+    /**
+     * 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
@@ -244,9 +259,30 @@ public class PlasticManager implements PlasticClassListenerHub
      */
     public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback)
     {
+        return createProxy(interfaceType, implementationType, callback, true);
+    }
+    
+    /**
+     * 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
+     * @param introduceInterface
+     *            whether to introduce the interface to the Plastic class or not.
+     * @return the instantiator, which allows instances of the new class to be created
+     * @see #createProxyTransformation(Class, Class)
+     * @since 5.4.5
+     */
+    public <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, Class<? extends T> implementationType, PlasticClassTransformer callback,
+            boolean introduceInterface)
+    {
         assert callback != null;
 
-        PlasticClassTransformation<T> transformation = createProxyTransformation(interfaceType, implementationType);
+        PlasticClassTransformation<T> transformation = createProxyTransformation(interfaceType, implementationType, introduceInterface);
 
         callback.transform(transformation.getPlasticClass());
 
@@ -254,6 +290,14 @@ public class PlasticManager implements PlasticClassListenerHub
     }
 
     /**
+     * Returns <code>createProxyTransformation(interfaceType, implementationType, true)</code>
+     */
+    public <T> PlasticClassTransformation<T> createProxyTransformation(Class interfaceType, Class implementationType)
+    {
+        return createProxyTransformation(interfaceType, implementationType, true);
+    }
+
+    /**
      * 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).
@@ -262,9 +306,12 @@ public class PlasticManager implements PlasticClassListenerHub
      *            class proxy will extend from
      * @param implementationType
      *            class that implements interfaceType. It can be null.
+     * @param introduceInterface
+     *            whether <code>result.getPlasticClass().introduceInterface(interfaceType);</code> should
+     *            be called or not.
      * @return transformation from which an instantiator may be created
      */
-    public <T> PlasticClassTransformation<T> createProxyTransformation(Class interfaceType, Class implementationType)
+    public <T> PlasticClassTransformation<T> createProxyTransformation(Class interfaceType, Class implementationType, boolean introduceInterface)
     {
         assert interfaceType != null;
 
@@ -279,7 +326,10 @@ public class PlasticManager implements PlasticClassListenerHub
         PlasticClassTransformation<T> result = 
                 pool.createTransformation("java.lang.Object", name, implementationClassName);
 
-        result.getPlasticClass().introduceInterface(interfaceType);
+        if (introduceInterface)
+        {
+            result.getPlasticClass().introduceInterface(interfaceType);
+        }
 
         return result;
     }
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 48bf24d..98a2f8c 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
@@ -509,10 +509,7 @@ public class ModuleImpl implements Module
                     }
                 });
 
-                for (Method m : serviceInterface.getMethods())
-                {
-                    plasticClass.introduceMethod(m).delegateTo(delegateMethod);
-                }
+                plasticClass.proxyInterface(serviceInterface, delegateMethod);
 
                 plasticClass.introduceMethod(WRITE_REPLACE).changeImplementation(new InstructionBuilderCallback()
                 {
@@ -525,7 +522,7 @@ public class ModuleImpl implements Module
 
                 plasticClass.addToString(description);
             }
-        });
+        }, false);
 
         return instantiator.newInstance();
     }
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy
index e543482..b614c38 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/AspectInterceptorBuilderImplSpec.groovy
@@ -1,6 +1,6 @@
 package ioc.specs
 
-import org.apache.commons.lang.StringUtils
+import org.apache.commons.lang3.StringUtils
 import org.apache.tapestry5.ioc.internal.services.TextTransformer
 import org.apache.tapestry5.ioc.services.AspectDecorator
 import org.apache.tapestry5.plastic.MethodAdvice
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/GeneralIntegrationSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/GeneralIntegrationSpec.groovy
index 1e30463..8fda9a4 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/GeneralIntegrationSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/GeneralIntegrationSpec.groovy
@@ -1,7 +1,12 @@
 package ioc.specs
 
+import org.apache.tapestry5.ioc.ObjectLocator
+import org.apache.tapestry5.ioc.Registry
+import org.apache.tapestry5.ioc.RegistryBuilder
 import org.apache.tapestry5.ioc.internal.services.Bean
 import org.apache.tapestry5.ioc.services.PropertyAccess
+import org.hibernate.Session
+import org.hibernate.cfg.Configuration
 
 class GeneralIntegrationSpec extends AbstractSharedRegistrySpecification {
 
@@ -20,6 +25,25 @@ class GeneralIntegrationSpec extends AbstractSharedRegistrySpecification {
     b.value == 99
     pa.get(b, "value") == 99
   }
+  
+  def "Avoiding duplicated method implementation in service proxies"() {
+      when:
+      Registry registry = RegistryBuilder.buildAndStartupRegistry(TestModule.class);
+      then:
+      // Throws exception without fix.
+      Session session = registry.getService(Session.class);
+  }
 
+  public static final class TestModule 
+  {
+      public static Session buildHibernateSession(
+          ObjectLocator objectLocator
+      ) {
+          return new Configuration()
+              .configure("hibernate.cfg.xml")
+              .buildSessionFactory()
+              .openSession();
+      }
+  }
 
 }
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
index 0e0a186..ea2e576 100644
--- a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
@@ -14,8 +14,11 @@
 package org.apache.tapestry5.ioc.internal;
 
 import org.apache.tapestry5.ioc.MethodAdviceReceiver;
+import org.apache.tapestry5.ioc.ObjectLocator;
 import org.apache.tapestry5.ioc.ServiceBinder;
 import org.apache.tapestry5.ioc.annotations.Advise;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
 
 public class AdviceModule
 {
@@ -45,4 +48,5 @@ public class AdviceModule
             final MethodAdviceReceiver methodAdviceReceiver) {
         methodAdviceReceiver.adviseAllMethods(new TestAdvice());
     }
+    
 }