Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Weaving code that comes from an Annotation's value

Michael Herrmann wrote:
Hi Dean, 

thank you very much for your detailed explanation. We've already talked on
the SF.net forum of Contract4J where I suggested Contract4J V3, do you
remember? I'm asking this very question because I'm thinking about writing
my own implementation of Design by Contract. 
  
I forgot about that ;) 
For this, I wouldn't want to use an _expression_ evaluator, because I'd like
to avoid the 'hassles' you mentioned. I'd rather write a preprocessor that
generates .aj files in order to get around it. 
  
My design goals have been to make it as simple as possible for the masses of Java developers with no AJ experience to adopt C4J. That's meant a heck of a lot of work for me! However, if you have more specific needs and don't mind asking users to write some AJ, then you've got more options and you can do things more simply.

For example, you could combine the annotation approach with my experimental "javabeans"-like approach (my so-called "V2", a version naming scheme that I've come to regret...). Specifically, you could have users write test methods as part of the class, e.g., "Foo.preFoo()" to run before "Foo.foo()" (and "Foo.postFoo()" to run after "foo" and "Foo.invarFoo()" to run before and after "foo" for invariants). Then use the annotation to connect the two:

Here's a hack (I didn't even try compiling this, so caveat emptor!):
public interface Foo {
        @ExecuteBefore("preFoo");
        public void foo(String s, int i); // added args.
	public boolean preFoo(String s, int); // new test method
}

...

aspect BeforeExecutor {
  pointcut execBefore (Object o, ExecuteBefore eb):
    execution(@ExecuteBefore * *.*(..)) && this(o) && @annotation(eb);

  before (Object o, ExecuteBefore eb): execBefore (o, eb) {
    CodeSignature cs = (CodeSignature) thisJoinPoint.getSignature();
    Method m = cs.getMethod();
    Boolean b = m.invoke (o, thisJoinPoint.getArgs());
    if (b.getValue() == false) { 
      failHorribly();
    }
  }
}

Actually, this example doesn't ask the users to write any AJ, either. However, it's a simpler and more constrained version of my "beans" approach. Looking at it, you don't even need the annotation value; you could construct the test method name from "foo" and "pre"! This might be all you need. (There are some reflection nuances that my "V2" handles, but that's because it's designed to be a general-purpose tool for the masses...)

Or, instead of using annotations, you could just write aspects that advise the desired methods directly and run the test expressions explicitly. That results in a lot of repetitive boilerplate code, however.

Does anybody else maybe know of a possibility of how to achieve this without
using a preprocessor?

  
The three approaches I've used are (i) preprocessor, (ii) the "javabeans"-like test methods and aspects that invoke them before and/or after the corresponding methods they test, and (iii) an embedded _expression_ evaluator. The _expression_ evaluator is the latest version and the one I think offers the capability and ease of adoption.
Thanks all
Michael Herrmann

  
This is pretty much what I do in Contract4J
(http://www.contract4j.org), where the @Pre annotations triggers
before advice. In this case, the value of the annotation is a java
_expression_ and it is evaluated with Jakarta Jexl's _expression_
evaluator.

I'm actually talking about the newest version that I am finishing, not
the two previous releases on the website. (ETA for the new release is
~1 week).

Writing the aspect is not difficult. Evaluating the _expression_ is
harder, depending on how "sophisticated" it needs to be.

Concerning the _expression_ in the annotation value, does it vary with
each usage of the aspect or is it fixed? Your example suggests you
want to do tracing, but maybe that's just the example. If you have a
fixed java _expression_ or one that varies in "simple" ways, it would be
far easier to omit it from the annotation and put it in the aspect
itself.  Consider the tracing aspect and ignoring the
thisJoinPointStaticPart.toString() method ;), you could write tracing
advice that does something like this:
   before(Object o, <other args>): mypointcut(o,<...>) {
     System.out.format ("class name = %s, stuff = %s",
o.getClass().getName(), ...);
   }
Even if the _expression_ changes a lot, maybe it would be simpler to
write a base aspect and override it for each class/method, where the
advice for class "Foo.foo" contains the _expression_. I'm just trying to
save you the hassles of integrating an _expression_ evaluator, having
gone through that pain myself, if you don't really need it.

Actually, it wouldn't be that bad if your expressions don't require
access to local context data, like Foo fields or methods. The pain
comes in setting up Jexl's context correctly.

So, with that digression, the aspect would be something like

aspect BeforeExecutor {
  pointcut execBefore (Object o, ExecuteBefore eb):
    execution(@ExecuteBefore * *.*(..)) && this(o) && @annotation(eb);

  before (Object o, ExecuteBefore eb): execBefore (o, eb) {
    evalExpression(eb.value());
  }

  void evalExpression(String expr) { ... }
}

Of course, "evalExpression" is the hard bit.

I can send you a preview of the newest C4J if you'd like to see what I
did with Jexl. In my case, I need to do some fancy footwork to setup
Jexl's "context" for evaluating the _expression_. It can be done!

Good luck,
dean

--
Dean Wampler
http://www.aspectprogramming.com
http://www.newaspects.com
http://www.contract4j.org


On 2/4/06, Michael Herrmann <Michael_Herrmann@xxxxxx> wrote:
    
Hi,

I'd like to be able to annotate my methods with code that should then
      
always
    
be called before the method itself is called. Is it, through AspectJ,
possible to treat the value of a (String) element of an annotation as
      
code?
    
For example:
public interface Foo {
        @ExecuteBefore("System.out.println('hi');");
        public void foo();
}

I now want System.out.println('hi') to always be called before the
implementation of foo() is called. You might recommend using abstract
classes in this case, but this is just an extremely oversimplified
      
example
    
to show you what I mean and using abstract classes or anything similar
      
won't
    
help me, unfortunately.

Thank you very much for your time
Michael Herrmann
      
  


-- 
Dean Wampler, Ph.D.
dean at aspectprogramming.com  
http://www.aspectprogramming.com  
http://www.contract4j.org
I want my tombstone to say: 
   Unknown Application Error in Dean Wampler.exe. 
   Application Terminated.
   [Okay]    [Cancel]

Back to the top