10 Replies Latest reply: Nov 21, 2010 4:59 AM by dr_nik RSS

    Problem with dynamic proxy

    dr_nik
      Hi everyone!

      I'm starting with dynamic object proxy and after some reading I wrote this sample code for Invocation Handler :

      class Proxer implements InvocationHandler {
      Object own;
      public Proxer(Comparable own) {
      this.own = own;
      }
      @Override
      public Object invoke(Object proxy, Method method, Object[] args)
      throws Throwable {
      if (method.getName()=="compareTo")
      System.out.println("Comparing " + own + " with " + args[0]);
      return method.invoke(own, args);
      }
      }

      This proxy works well if I try this sample:

      Comparable cml=(Comparable) Proxy.newProxyInstance(
      Comparable.class.getClassLoader(),
      new Class[] { Comparable.class },
      new Proxer(new String("String1")));
      System.out.println(cml.compareTo("Another String"));

      Output:

      Comparing String1 with Another String
      18

      But if I try this:

      Comparable cml=(Comparable) Proxy.newProxyInstance(
      Comparable.class.getClassLoader(),
      new Class[] { Comparable.class },
      new Proxer(new String("String1")));
      System.out.println(((Comparable)("Another String")).compareTo(cml));

      I got this error stack:

      Exception in thread "main" java.lang.ClassCastException: $Proxy0 cannot be cast to java.lang.String
      at java.lang.String.compareTo(String.java:92)
      at MainClass.main(MainClass.java:147)

      Is it possible to use proxy on the right side of compareTo and somehow make this typecast ?*

      Thanks in advance.
        • 1. Re: Problem with dynamic proxy
          EJP
          What happens if you remove the cast to (Comparable)?
          • 2. Re: Problem with dynamic proxy
            dr_nik
            It's not the case of ascending typecast, that's why I must show exact type to compiler: Object (from newProxyInstance) to Comparable.

            If I remove this typecast it give me type mismatch error...
            • 3. Re: Problem with dynamic proxy
              EJP
              But you're not doing that. You are casting String to Comparable.
              • 4. Re: Problem with dynamic proxy
                dr_nik
                EJP wrote:
                But you're not doing that. You are casting String to Comparable.
                Why do you think so?

                System.out.print("Proxy is instance of Comparable? ");
                System.out.println(Proxy.newProxyInstance(Comparable.class.getClassLoader(), new Class[] { Comparable.class },new Proxer(new String("String1"))) instanceof Comparable);

                System.out.print("Proxy is instance of String? ");
                System.out.println(Proxy.newProxyInstance(Comparable.class.getClassLoader(), new Class[] { Comparable.class },new Proxer(new String("String1"))) instanceof String);
                          
                System.out.print("Proxy is instance of Object? ");
                System.out.println(Proxy.newProxyInstance(Comparable.class.getClassLoader(), new Class[] { Comparable.class },new Proxer(new String("String1"))) instanceof Object);

                Output:

                Proxy is instance of Comparable? true
                Proxy is instance of String? false
                Proxy is instance of Object? true
                • 5. Re: Problem with dynamic proxy
                  jtahlborn
                  the problem comes because in your code which fails, you are calling the String.compareTo() method, which requires its argument to be a String. there is no way you will be able to generate any class or proxy (other than a String instance, of course) which you will be able to (successfully) pass into the String.compareTo() method.

                  note, calling "((Comparable)myString).compareTo()" is not going to change anything. you will still be invoking the String.compareTo() method.

                  Edited by: jtahlborn on Nov 20, 2010 4:48 PM
                  • 6. Re: Problem with dynamic proxy
                    dr_nik
                    Thank for your help, jtahlborn

                    Cause of this exception is clear, it's just incomprehensible for me that I can invoke some specific methods that proxy implements and I can't use proxy like other "instantiated interfaces"...
                    • 7. Re: Problem with dynamic proxy
                      EJP
                      You are casting String to Comparable.
                      Why do you think so?
                      (Comparable)"AnotherString"
                      is why I think so. That's your code and that is where you are casting String to Comparable. The thing inside the quotes is a String, and the thing inside the parentheses is a typecast.

                      The String.compareTo(String) method is as a result trying to cast the proxy to String, but that isn't you, that's the JRE.
                      Proxy is instance of Comparable? true
                      Proxy is instance of String? false
                      Proxy is instance of Object? true
                      These results are entirely as expected. They have nothing to do with what I wrote.

                      The problem here, getting back to the point, is that compareTo(String) requires a String. Not a Comparable<String>.

                      Edited by: EJP on 21/11/2010 13:52
                      • 8. Re: Problem with dynamic proxy
                        jtahlborn
                        user12119858 wrote:
                        Thank for your help, jtahlborn

                        Cause of this exception is clear, it's just incomprehensible for me that I can invoke some specific methods that proxy implements and I can't use proxy like other "instantiated interfaces"...
                        you can use a proxy like other "instantiated interfaces". it's just that in this situation the method you are trying to invoke requires a String not a Comparable. if you invoked a method which only required a Comparable, then the proxy would work just fine.
                        • 9. Re: Problem with dynamic proxy
                          EJP
                          This is leading to a new train of thought. What if Comparable had been genericized like this:
                          public interface Comparable<T>
                          {
                            int compareTo(Comparable<T>);
                          }
                          Not sure that would have been binary-compatible ... Anyway the point is that it wasn't, and that's why this code is failing.

                          It's also curious why anybody would want to build a dynamic proxy for String. Not something that ever occurred to me in the ten years roughly that we've had the facility.
                          • 10. Re: Problem with dynamic proxy
                            dr_nik
                            Thanks both of you, I think that all clear now.

                            EJP, String class has been involved in this question just for simplification of real deal.

                            Edited by: user12119858 on 21.11.2010 2:41