[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [aspectj-users] pointcut clash (?)
|
I'm impleting a lazy loader, that is a component that loads complex data
structures (e.g., lists, hashmaps) only on demand. The idea is that each
instance variable annotated with a custom annotation is not loaded immediatly
(as the object construction happens) but only when such variable is accessed.
This is the pointcut that realizes the above:
pointcut lazyLoaderRequired( LazyLoading loadingProperties, FilteredLoader
mySelf ) :
(
get( @LazyLoading
Collection<StatefullDatabaseObject+>+ StatefullDatabaseObject+.* )
||
get( @LazyLoading
Map<SerializableObject+,
DatabaseObject+>+ SerializableObject+.* )
||
get( @LazyLoading
Map<SerializableObject+,
StatelessDatabaseObject+>+ SerializableObject+.* )
)
&&
@annotation( loadingProperties )
&&
this( mySelf )
&&
(! execution( public void
FilteredLoader.loadFilteredData(Class) ) )
&&
(! cflow(adviceexecution()) )
;
each time I perform a "get" on a complex data structure within a
StatefullDatabaseObject, the pointcut intercepts such calls. The advice is the
following:
before( LazyLoading loadingProperties, FilteredLoader mySelf) :
lazyLoaderRequired( loadingProperties, mySelf) {
// perform standard lazy loading
this.performLazyLoading(loadingProperties, mySelf, false);
}
The idea behing the advice is that each time a "get" happens on a complex data
structure, the aspect checks an internal cache to see if such complex data
structure has been loaded yet or not. In the case it has not been loaded it
loads, otherwise pull it from the cache. The last parameter (false) of the
performLazyLoading(..) does this: if false searches the cache before loading
the objects, if true never checks the cache and loads the object (i.e., this
flag suppresses lazy loading).
All the above works great.
Now there are special cases where I want the lazy loading mechanism to be
forced, that is the aspect should intercepts particular conditions and force a
loading of the required complex structures. Such particular cases are all the
method of the DatabaseDialog+ or all the methods of the QueryElements+. This
conditions extend the above pointcut definition, and therefore the pointcut
should be:
pointcut lazyLoaderForced( LazyLoading loadingProperties, FilteredLoader
mySelf) :
cflow( lazyLoaderRequired( loadingProperties,
mySelf) )
&&
(
execution( public boolean
DatabaseDialog+.perform*() throws
DatabaseException )
||
execution( public JComboBox
QueryElements.*(..) )
||
execution( * DatabaseDialog+.*(..) )
)
;
and the corresponding advice should change the suppress-lazy-loading flag:
before( LazyLoading loadingProperties, FilteredLoader mySelf ):
lazyLoaderForced( loadingProperties, mySelf) {
// perform forced lazy loading
this.performLazyLoading(loadingProperties, mySelf, true);
}
Now what happens is that, checking with debugger, println, and observing
program misbehaviour, the lazyLoadingForced advice does not work for
DatabaseDialog+ and QueryElements+ methods. It is like the lazyLoadingRequired
works before the forced one. This is what lead me think there's a pointcut
clash, but probably I'm doing a wrong pointcut definition.
Luca
On Friday 13 March 2009 19:52:13 Andy Clement wrote:
> Hi Luca,
>
> I'm having a little trouble understanding the configuration - those
> pointcuts are quite complex.
>
> > Now what should happen is that a method of QueryElements is adviced by
> > the lazy loader required pointcut, and eclipse confirms this. However,
> > what
>
> happen
>
> > observing the running code is that the lazyLoaderRequired pointcut is
>
> always
>
> > triggered. I suspect this is due to the fact that two pointcuts are
>
> And this says eclipse confirms a method of QueryElements is advised by the
> lazy loader
> required pointcut and at runtime the lazy loader required pointcut is
> always triggered. Did
> you mean lazyLoaderForced for one of those?
>
> I'm not sure how you are expecting these two pointcuts to interact at a
> join point - and how
> do you think the second one is overriding the first one? They have
> different names. You
> can't influence what the first one is doing by writing the second one -
> unless it was around
> advice and the second one happened to have higher precedence and did not
> proceed to the join
> point to drive the lower precedence one.
>
> If you can give a sample of the advised code (or pseudocode for it) and
> what you want to
> achieve, that might help.
>
> The use of cflow is going to cause quite a few markers in AJDT to show up -
> but they will
> all be annotated with a ? indicating the location is advised in the
> bytecode but a decision will
> be made at runtime whether to invoke the advice.
>
> Andy.
>
> 2009/3/13 Luca Ferrari <fluca1978@xxxxxxxxxxx>
>
> > Hi,
> > I'm getting into troubles with an aspect that should drive a lazy loader
> > for
> > complex data types:
> >
> > pointcut lazyLoaderRequired( LazyLoading loadingProperties,
> > FilteredLoader mySelf ) :
> > (
> > get( @LazyLoading
> > Collection<StatefullDatabaseObject+>+ StatefullDatabaseObject+.* )
> >
> > get( @LazyLoading
> > Map<SerializableObject+,
> > DatabaseObject+>+ SerializableObject+.* )
> >
> > get( @LazyLoading
> > Map<SerializableObject+,
> > StatelessDatabaseObject+>+ SerializableObject+.* )
> > )
> > &&
> > @annotation( loadingProperties )
> > &&
> > this( mySelf )
> > &&
> > (! execution( public void
> > FilteredLoader.loadFilteredData(Class) ) )
> > &&
> > (! cflow(adviceexecution()) )
> > ;
> >
> >
> > the above pointcut intercepts get calls and evaluates if the lazy loading
> > should happen (or not, if it has been already performed):
> >
> > before( LazyLoading loadingProperties, FilteredLoader mySelf) :
> > lazyLoaderRequired( loadingProperties, mySelf) {
> > // perform standard lazy loading
> > this.performLazyLoading(loadingProperties, mySelf, false);
> >
> > }
> >
> >
> > Now I've got situations where I want lazy loading to be disabled, so I
> > wrote
> > another pointcut that partially override the above one:
> >
> > pointcut lazyLoaderForced( LazyLoading loadingProperties, FilteredLoader
> > mySelf) :
> > cflow( lazyLoaderRequired(
> > loadingProperties, mySelf) )
> > &&
> > (
> > execution( public boolean
> > DatabaseDialog+.perform*() throws
> > DatabaseException )
> >
> > withincode( public JComboBox
> > QueryElements.*(..) )
> >
> > execution( * DatabaseDialog+.*(..) )
> >
> >
> > )
> > ;
> >
> > and defined another advice that should be triggered by the above
> > pointcut:
> >
> > before( LazyLoading loadingProperties, FilteredLoader mySelf ):
> > lazyLoaderForced( loadingProperties, mySelf) {
> > // perform forced lazy loading
> > this.performLazyLoading(loadingProperties, mySelf, true);
> > }
> >
> >
> > Now what should happen is that a method of QueryElements is adviced by
> > the lazy loader required pointcut, and eclipse confirms this. However,
> > what happen
> > observing the running code is that the lazyLoaderRequired pointcut is
> > always
> > triggered. I suspect this is due to the fact that two pointcuts are
> > overlapping, but I've tried also to isolate the statements of a lazy
> > loading
> > required but the program always executes the required pointcut/advice.
> >
> > Any idea about the problem?
> >
> > Thanks,
> > Luca
> > _______________________________________________
> > aspectj-users mailing list
> > aspectj-users@xxxxxxxxxxx
> > https://dev.eclipse.org/mailman/listinfo/aspectj-users