1 Reply Latest reply on Oct 5, 2004 9:58 PM by Shigeru Chiba

    Writing method args into file with Javassist

    vicki Newbie

      Hi,
      I am trying to choose between AspectJ and Javassist as testing tools in my company. Javassist seems to me more straightforward, and I lean towards it, but there are some utility functionality that is harder to implement in Javassist. For instance, I cannot use System.out.println for printing out tested method's arguments or local variables because the instrumented classes are running in appserver container or because of some other reason... I need to user FileWriter to create test logs. I was trying to create logging method with CtNewMethod.make(..), and my instrumentor class compiles fine, but when I run it against class to be instrumented I get
      Exception in thread "main" javassist.CannotCompileException: [source error] no such class: FileWriter
      at javassist.CtNewMethod.make(CtNewMethod.java:78)
      at javassist.CtNewMethod.make(CtNewMethod.java:44)
      at TestWriteClass.main(TestWriteClass.java:34)
      Caused by: compile error: no such class: FileWriter

      Could anyone please point me into the direction of where I can find a code snippet showing how to do it right?

      Thanks a lot!
      Vicki

        • 1. Re: Extending Reflection to intercept Constructors
          Shigeru Chiba Expert

          I now have a working version based on 2) above, by adding a boolean field to the class, which is set during the instantiation of the embedded Metaobject (this is an instance field and is instantiated straight after the super(...) constructor runs and prior to the execution of the remainder of the constructor). The field determines whether the full constructor (after any explicit or implicit call to super(...)) should be intercepted (effectively stopped).

          The constructor is enhanced through the following code in Reflection:

          CtConstructor c;
          ...
          c.insertBeforeBody("if (" + interceptConstructorField + ") {return;}");


          ... where interceptConstructorField contains the name of the new boolean field added to the class. This field is set in the constructor of the Metaobject based on an equivalent new (static) boolean field in Metaobject. So, if:

          Metaobject.setInterceptConstructor(true)


          ... is called, when the next instance of the reflected class is instantiated, only its superclass constructor will run, as the inserted return will be reached. Set it back to false, and the full constructor will run for the next instance.

          The design uses static fields and methods in Metaobject (should these live instead in ClassMetaobject?), as the instance of Metaobject is not instantiated until during the instantiation of the reflected object. This made me realise that the additional field within the reflected class is probably not needed, rather:

          c.insertBeforeBody("if (" + metaobjectGetter + "().isInterceptConstructor()) {return;}");


          ... is just as effective, with the slight disadvantage being that there is no way down the track to tell whether a particular reflective object's constructor was intercepted. So maybe the field should stay.

          I have a full set of jUnit tests. Could someone please advise me on how best to contribute this enhancement?

          Brett Randall