Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] newbie AspectJ questions

Acegi has built-in integration with AspectJ but it requires an around
closure:
http://acegisecurity.org/docbook/acegi.html#security-interception-aspectj
 
Basically, the framework expects a continuation object to prevent 
, so if you 
 
  _____  

From: aspectj-users-bounces@xxxxxxxxxxx
[mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Matthew Webster
Sent: Tuesday, January 31, 2006 6:44 AM
To: aspectj-users@xxxxxxxxxxx
Subject: 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/whi
sper/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



Back to the top