ProxyToys
  1. ProxyToys
  2. PTOYS-17

As a user, given the example, I want either outcome or error, not an infinite loop

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      Long story short, my company has wrapped some connection object in a delegate, then in a decorator, then in a delegate again.

      Somewhere somehow later, a Set of these objects is copied. And equals() and hashcode() to delegated is invoked too.

      As a result of that, in DelegatingInvoker detects it's a ReflectionUtils equals, then extracts the delegate (of type decoratingInvoker), it's a proxy class but not instance of DelegatingInvoker.

      So it will keep in the while loop forever.

      (DelegatingInvoker snippet to illustrate my explanation above)

      public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {

      final Object result;

      Object delegate = delegate();

      // equals(...) and hashCode()

      if (method.equals(ReflectionUtils.equals)) {

      // Note: equals will normally compare the classes directly, so we have to dereference

      // all delegates and then swap the call (in case of our argument is also a delegation proxy).

      final Object arg = args[0];

      while (delegate != null && proxyFactory.isProxyClass(delegate.getClass())) {

      Invoker invoker = proxyFactory.getInvoker(delegate);

      if (invoker instanceof DelegatingInvoker<?>)

      { delegate = DelegatingInvoker.class.cast(invoker).delegate(); }

      }

      I can admit and argue that my company is using the library in a correct way or not, but the bad usage result shouldn't be a infinite loop.

      In my humble opinion, decoratingInvoker should inherit from delegatingInvoker, at least the way we use it.

      Working example to demonstrate the bug:

      import com.google.common.collect.ImmutableSet;

      import com.thoughtworks.proxy.factory.CglibProxyFactory;

      import com.thoughtworks.proxy.toys.decorate.Decorating;

      import com.thoughtworks.proxy.toys.decorate.Decorator;

      import com.thoughtworks.proxy.toys.delegate.Delegating;

      import com.thoughtworks.proxy.toys.delegate.DelegationMode;

      import java.util.HashSet;

      import java.util.Set;

      /**

      • Created by anavarro on 9/8/14.

      */

      public class BugTest {

      public static void main(String [] args)

      { Set<iBase> set = new HashSet<>(); //set.add(new Base()); set.add(build()); set.add(build()); set.add(build()); Set<iBase> bset = ImmutableSet.copyOf(set); }

      private static iBase build()

      { Base base = new Base(); iBase delegated = Delegating.proxy(iBase.class) .with(base) .mode(DelegationMode.SIGNATURE) .build(new CglibProxyFactory()); iBase decorated = Decorating.proxy(iBase.class) .with(delegated) .visiting(new Listener<iBase>()) .build(new CglibProxyFactory()); iBase delegated2 = Delegating.proxy(iBase.class) .with(decorated) .mode(DelegationMode.SIGNATURE) .build(new CglibProxyFactory()); return delegated2; }

      public interface iBase {

      }

      public static class Base implements iBase {

      @Override

      public int hashCode()

      { return 1; }

      }

      public static class Listener<T> extends Decorator<T> {

      }

      }

      I hope you can fix it soon

      Best regards

      Alberto Navarro

      Senior Java Developer @ Recorsure Ltd.

        Activity

        There are no entries against this issue.

          People

          • Assignee:
            Unassigned
            Reporter:
            Alberto Navarro
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: