[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [aspectj-users] newbie AspectJ questions
|
Mark,
Just to add to Adrian's response it
_is_ valid for Xlint:canNotImplementLazyTjp
to be issued by AspectJ 5. In addition to your around advice should you
have another piece of advice, either in the same or typically a different
aspect, that can be optimized for lazy JoinPoint object creation you will
get this warning. This will be largely avoided by reducing the scope of
your around advice as suggested by Adrian. Furthermore it may be possible
to avoid the warnings altogether by using before rather than around advice
if your security interceptor does not modify arguments and only throws
unchecked exceptions. Finally use Xlint="ignore" to remove all
warnings.
Matthew Webster
AOSD Project
Java Technology Centre, MP146
IBM Hursley Park, Winchester, SO21 2JN, England
Telephone: +44 196 2816139 (external) 246139 (internal)
Email: Matthew Webster/UK/IBM @ IBMGB, matthew_webster@xxxxxxxxxx
http://w3.hursley.ibm.com/~websterm/
Please respond to aspectj-users@xxxxxxxxxxx
Sent by:
aspectj-users-bounces@xxxxxxxxxxx
To:
aspectj-users@xxxxxxxxxxx
cc:
Subject:
Re: [aspectj-users]
newbie AspectJ questions
Adrian,
First, I'd like to thank you for the detailed reply. I
mean *huge* thanks. The sad fact is that I'm not able to spend nearly as
much time as I'd like learning the details of AspectJ, and from what I'm
reading, once I have this one mechanism set up, that's all I'm going to
need. I was not looking forward to spending the next week or two tracing
execution and combing through the AspectJ Compiler manual.
To clear up some of the uncertainty in my post, yes I'm
using AspectJ 1.5; it was required because I make heavy use of generics
in my code. I've got a customized version of the maven plugin (still using
Maven 1.0.2, and the latest AspectJ plugin for it uses 1.2.1) and I'll
probably send the patch to the people who make it once I make sure things
are working. I'm wondering if the lazyTjp warnings might be an artifact
of the plugin. It's using an ant task (I've replaced most of the variable
properties with their current settings):
<ant:iajc
fork="false"
incremental="false"
XnoWeave="false"
Xlint="warning"
destDir="${destDir}"
sourceRootCopyFilter="${maven.aspectj.sourceRootCopyFilter}"
debug="false"
emacssym="no"
verbose="false"
source="1.5"
target="1.5"
time="false">
I'm assuming that if I change Xlint to "error",
most of those warnings will go away? I can't test that at the moment, but
I'll give it a try in a few hours.
And yes, AclSecurable is an interface. All of the domain
objects that can be secured with Access Control Lists will be tagged with
that interface and the security aspect will only be valid for those objects;
the interfaces that define each type of domain object extend AclSecurable,
and are then implemented in turn by the domain object classes. Fortunately,
they are all in the same package, and now that I understand a little more
about the pointcut matching, I should be able to whittle it down to just
the classes that need it, and probably down to the methods that need it.
Again, thanks! If I run into any other problems, I'll
reply again, but hopefully that'll cover it.
Mark
On Jan 31, 2006, at 2:46 AM, Adrian Colyer wrote:
To try and explain some of what's going on for you here...
The closure classes are generated by the AspectJ compiler when around advice
cannot be inlined (the default). In this case, the call to "proceed()"
in the around advice is escaping the advice body (by being passed to the
security interceptor inside the callback object) and so AspectJ must generate
a closure class (think of it like a continuation implementation).
The reason you have so many of them.... is that the pointcut you have written
matches a very broad set of join points. In particular, you have used "target(AclSecurable)"
(and I'm presuming AclSecurable is an interface). "target" matches
based on the runtime type of the target at a join point. Since you are
using execution I'll use that for the example.
Give some class A
public class A {
public void foo() { ... }
}
When AspectJ weaves this class, it is possible that the "target"
when foo executes *is* an AclSecurable, even though A isn't. The way this
could happen is if someone defines a subclass B:
public class B extends A implements AclSecurable {
}
Now given b of type B, a call to b.foo() results in an execution of foo()
that should have security interception applied to it. Given the requirements
to support separate and incremental compilation, AspectJ will apply
a runtime test before the execution of A.foo to see if the target object
really does implement AclSecurable, and the around advice will execute
if so. Given the potential for this to happen at almost any method execution
join point, you will have a lot of closure classes!
You can narrow this down using one or both of the following techniques:
* constrain the join point matching to only those types within your domain
model. For example, you might add a pointcut:
pointcut inDomainModel() : within( edu.uscs.whisper.domain..*);
(or whatever package prefix or prefixes you are using for the domain types).
and then refine the domainObjectInstanceExecution pointcut as follows:
pointcut domainObjectInstanceExecution() :
target(AclSecurable) &&
execution(public * *(..)) &&
inDomainModel();
(assuming the aspect itself is not in the same package as the domain model
types, the additional !within will no longer be required).
* The second narrowing technique is to switch from using target to using
static type matching. This will work well if you use the AclSecurable interface
at the root of any domain type hierarchy (eg., in the example above, "A"
implements AclSecurable, and not "B" only). The only drawback
to this solution is that if you have a domain type hierarchy such as A
and B above, and only B implements the AclSecurable interface, then methods
on A that are not overriden by B will NOT go through the SecurityInterceptor.
Use the interface at the root of the domain hierarchy you want to secure.
The pointcut will now look like this:
pointcut domainObjectInstanceExecution() :
execution(public * AclSecurable+.*(..)) &&
inDomainModel();
(the execution _expression_ reads: "the execution of any public method
defined in AclSecurable or any subtype of AclSecurable").
Now to address the other issues:
* lazyTjp is a compiler optimisation that applies when using thisJoinPoint.
Prior to AspectJ 5, this optimisation had to be explicitly turned on, but
from AspectJ 5 onwards, the optimisation is enabled by default. You don't
say what version of AspectJ you are using, but we shouldn't be warning
for this under AspectJ 5 - we will fix that as a bug if so. If you are
using e.g. 1.2.1 and have enabled the -XlazyTjp flag then this is why the
warning is coming out. The warning is a simple advisory that an optimisation
was not applied, and your program will behave perfectly correctly.
* the needsSerialVersionUIDField warnings are coming out because
the AspectJ weaving process has had to generate synthetic fields in your
domain types. These can affect serialization (in particular if you haven't
explicitly specified a serialVersionUID, then the generated alternative
will be different after weaving). This can be an issue if you want to serialize
and deserialize woven and unwoven versions of the type. Defining a serialVersionUID
is recommended best practice in any case, and will ensure you never encounter
any issues of this type. I notice from that message that even the execution
of hashCode and equals methods are being advice by your pointcut. You probably
don't want to apply security to these methods (if you do, fine). You can
exclude methods from Object from having security interception applied by
refining the pointcut _expression_ once more:
pointcut javaLangObjectMethodExecution() :
execution(* Object.*(..));
pointcut domainObjectInstanceExecution() :
execution(public * AclSecurable+.*(..)) &&
!javaLangObjectMethodExecution() &&
inDomainModel();
Sorry for the long reply - your post touched on a number of interesting
issues!
On 31/01/06, Mark Slater < lists@xxxxxxxxxxxxxxxxxx>
wrote:I'm new to AspectJ, and direct use of aspects in general. I've been
using them indirectly with the Spring Framework and the Acegi security
system that complements spring. But now I need to implement my own aspect
to provide security on my domain objects.
Based on the Acegi documentation, I've got the following
aspect:
package edu.ucsc.whisper.security.aspectj;
import org.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor
;
import org.acegisecurity.intercept.method.aspectj.AspectJCallback;
import org.springframework.beans.factory.InitializingBean;
import edu.ucsc.whisper.core.AclSecurable;
public aspect DomainObjectInstanceSecurityAspect
implements InitializingBean
{
private AspectJSecurityInterceptor securityInterceptor;
pointcut domainObjectInstanceExecution():
target( AclSecurable )
&& execution( public
* *(..) ) && !within( DomainObjectInstanceSecurityAspect );
Object around(): domainObjectInstanceExecution()
{
if( this.securityInterceptor
!= null )
{
AspectJCallback
callback = new AspectJCallback()
{
public Object proceedWithObject()
{
return( proceed() );
}
};
return( this.securityInterceptor.invoke(
thisJoinPoint, callback ) );
}
else
{
return( proceed()
);
}
}
public AspectJSecurityInterceptor getSecurityInterceptor()
{
return( securityInterceptor
);
}
public void setSecurityInterceptor( AspectJSecurityInterceptor
newInterceptor )
{
securityInterceptor = newInterceptor;
}
public void afterPropertiesSet()
throws Exception
{
if( securityInterceptor ==
null )
{
throw( new IllegalArgumentException(
"SecurityInterceptor required." ) );
}
}
}
As you can see, I only want this aspect applied to objects
that implement the AclSecurable interface. However, when I look at the
output classes (I'm using maven to build), I've got one or more ...$AjcClosure#.class
files for each class in the project, and my JUnit test cases. I'm not sure
why they would be needed for classes that aren't even indirectly related
to the AclSecurable class/interface hierarchy. And I really don't see why
the JUnit test cases (which are defined in a separate source tree and compiled
to a separate class tree) should be getting this treatment.
But worse (in my mind) is that when I build, I'm getting
the following output for every method in my project:
{package}/{class}.java:55 [warning] can not implement
lazyTjp on this joinpoint method-execution(void {package}.{class}.{method}(
{parameters} )) because around advice is used [Xlint:canNotImplementLazyTjp]
public void setEditUserAccountInfoValidator( EditUserAccountInfoValidator
newValidator )
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
see also: /Users/mark/Documents/school/whisper/ftr116_mslater/src/aspectj/edu/ucsc/whisper/security/aspectj/DomainObjectInstanceSecurityAspect.java:18::0
I've done some searching and I can't even figure out what
it means that it can't implement lazyTjp, so I don't know if this can be
safely ignored, or if it means I've got a bug someplace.
I'm also getting a few messages that look like this:
edu/ucsc/whisper/security/aspectj/DomainObjectInstanceSecurityAspect.java:18
[warning] serialVersionUID of type edu.ucsc.whisper.core.DefaultAuthority
needs to be set because of added non-private method hashCode_aroundBody10
[Xlint:needsSerialVersionUIDField]
And once again, I'm not sure what this is talking about...
is it suggesting that I need to add new fields to objects that (in this
case) I don't even want the aspect applied to?
I'm finding this more confusing than I'd expected it to
be. Any help?
Thanks,
Mark
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users
--
-- Adrian
adrian.colyer@xxxxxxxxx
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users