Uploaded image for project: 'Weld'
  1. Weld
  2. WELD-2618

ProxyFactory#getProxyName() produces non-deterministic verbose proxy names

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Minor Minor
    • 3.1.6.Final, 4.0.1.Final
    • 3.1.3.Final
    • Proxies
    • None

      (I created this issue partially at the request of Matej Novotny: https://lists.jboss.org/pipermail/weld-dev/2020-March/003768.html)

      This is a minor bug with no practical impact but I wanted to capture it so it doesn't get lost.

      The getProxyName() method can produce different proxy names for the same inputs. This is due in part to the fact that Proxies.TypeInfo does not sort its Set instances.

      In addition, the getProxyName() method does not actually produce the final proxy name that is used. The getProxyClass() method adds additional computation.

      The net result is that this kind of thing produces slightly bizarre proxy names:

      final Method getProxyName =
      ProxyFactory.class.getDeclaredMethod("getProxyName", String.class,
      Class.class, Set.class, Bean.class);
      getProxyName.setAccessible(true);
      final Set<Type> typeSet = new LinkedHashSet<>();
      
      // Let's add two disparate interfaces in an arbitrary, but predictable,
      order.
      
      typeSet.add(Serializable.class);
      typeSet.add(Cloneable.class);
      final String proxyName = (String)getProxyName.invoke(null, null,
      Object.class, typeSet, null);
      
      // Serializable.class comes first, so is used to calculate the package name.
      // Then the interfaces are sorted by their simple names, not their full package names.
      // So Cloneable comes first.  Finally everything is put together, so you get java.io bolted
      // on to Cloneable.
      assertEquals("java.io.Cloneable$Serializable$$Proxy$", proxyName); // ?!
      

      (The actual proxy name used in this case is further computed by the getProxyClass() method and so will be, in fact, if I'm reading the code right, org.jboss.weld.io.Cloneable$Serializable$$Proxy$_$$_Weld$Proxy$. It's also worth noting that if I were proxying something starting with javax, the package prefix would be org.jboss.weldx.)

      Additionally, I believe that the first occurrence of $$ above is a mistake due to there not being any checking for the last iteration of this loop: https://github.com/weld/core/blob/10a1d11af8c815a2a4a8fc5a4061698215e602b0/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java#L283

      I'm fully aware these are opaque internal constructs that users shouldn't have to care about; the background is only that I'm doing close code reading and trying to understand as fully as I can how proxies work. This name computation confused me.

              manovotn Matěj Novotný
              ljnelson+github@gmail.com Laird Nelson (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: