Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Advising all methods that modify transientfields

> Is there a way to generalize the pointcut above or would I need an
> aspect for each storage class I was dealing with?

It depends on the assumptions you can make and what you mean:
- this(), target(), and args() take a type
- within(), call(), and execution() take a typepattern

One way is to use a tag interface:

    public interface IStore {}

    pointcut withinStoreClass() : within(IStore+);

    pointcut mutatingMethodExecutions() :
        execution(void set*(..))
        || execution(* add*(..))
        || execution(* remove*(..));

    pointcut stateChanges() : withinStoreClass()
        && mutatingMethodExecutions();

Then whenever you have a storage class, you can declare
that it implements IStore (in the class or in an aspect
(the same aspect or a separate one), depending on where
you wanted the dependencies to run). For example, if the
declaring aspect were called "StateChanges", you'd say

  class MutableInt implements StateChanges.IStore { ... }
  - or -
  declare parents: MutableInt implements StateChanges.IStore;
  - or-
  // all top-level types in the org.codehaus.model package
  // are IStore
  declare parents: org.codehaus.model.*
                   implements implements StateChanges.IStore;

Two nice things about the pointcut above:

1) It uses && within(...), which can speed up weaving

2) It is staticly-determinable, so you can use it in
   declare warning|error statements:

    declare warning : mutatingMethodExecutions()
     && !withinStoreClass()
        : "mutating method in non-storage?";

You can also use the same signatures to check for field sets
outside the mutating methods (or constructors):

    declare warning : set(* *.*) &&
        && !(withincode(void set*(..))
             || withincode(* add*(..))
             || withincode(* remove*(..))
             || withincode(new(..)))
    : "state-change not in mututing method/constructor?";

Hope this helps.  If you come up with some interesting
aspects, we'd welcome your posting the code on the list.

Wes

Jason van Zyl wrote:
On Wed, 2003-12-03 at 04:49, Wes Isberg wrote:

I would actually like to capture all methods in which
non-transient
fields are modified for a given storage class.

There isn't a way in AspectJ to pick out a join point
based on whether other join points might occur within
the scope of its execution, even if that's determinable.
You can get the signature of the enclosing join point,
but you don't want to replace a field-set with a reflective call to the method containing it. Even if
you avoid advice advising itself, there might be code
before or after the set in the method.

If you really want to do this, one solution is to convert "state changes" to setter methods in one of two ways. (Neither way gives you the benefit of
grouping a set of state changes for persistence at
one point -- do you miss the C++ const specifier yet?
-- for AspectJ used to try to close over a whole series of messages, see the CricketCage project.)


Having the policy of using methods is completely acceptable to me.
Changing the extended aspect to this:

http://cvs.codehaus.org/viewcvs.cgi/outhaus/jvanzyl/aspects/src/main/org/codehaus/top/prevayler/Persistence.aj?rev=1.2&root=codehaus&view=auto

Works fine with my small test and I will incorporate your enforcement
code as well.

Is there a way to generalize the pointcut above or would I need an
aspect for each storage class I was dealing with?

That's not really a big deal as I could generate the aspect from some
user input if not possible because in my scenerio the storage class must
be specified. I usually prototype with Prevayler as I can change the
application model, blow away prevayler transactions and try again. But I
would like to be able to take the storage class, swizzle it and
automatically generate the necessary OJB artifacts for database
persistence.

jvz.

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users




Back to the top