Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] How to provide external pcd definition?

Well I love it. I remember Ron Bodkin suggesting something similar when we got together last. At the cost of runtime efficiency, you could easily write all sorts of useful debugging and profiling aspects and configure them without redeploying your app. Actual production use would be limited by the efficiency considerations, but for a small set of join points:

  // this pointcut is used to narrow down as far as possible at compile
time the set of places
  // at which a dynamic pointcut could match (for efficiency)
  pointcut scope() : within(org.xyz.foo);

it could even be used in production.

Hope to see this released somewhere so that we can play with it. I guess it's probably too much to hope that it would show up in 1.2...

Cheers,
nick

On May 11, 2004, at 1:50 PM, Adrian Colyer wrote:

This question has been vexing me for the last few days. Any configuration
of a pointcut would have to go through the AspectJ compiler, so what
you're currently doing is about as good as it can get right now.

You could imagine an XML syntax that gets turned into an aspect by some
build step, e.g.

<aspect name="DatabaseTestAspect" extends=" AbstractDatabaseTestAspect">
  <pointcut name="applicationCode">within(patterntesting..*)</pointcut>
  <pointcut name="allowedCode">within(patterntesting.db..*)</pointcut>
</aspect>

(just for illustration, not a real syntax)

but is that really so much easier to understand than:

aspect DatabaseTestAspect extends AbstractDatabaseTestAspect {
  pointcut applicationCode() : within(patterntesting..*);
  pointcut allowedCode() : within(patterntesting.db..*);
}

? Especially when you've still got to pass the result through the compiler
anyway.

I've been talking a lot with the Spring folks at the TSS Symposium, and I can see a case for wanting true runtime configuration of pointcut values for some infrastructure (auxiliary) aspects - the kind of things that the J2EE community is very used to specifying in config files rather than in code. One of the exciting things that came out of those discussions is a
way to use Spring's IoC capabilities to configure aspects (more on that
soon), but this capability doesn't extend to configuring pointcuts (just things like the DataSource for a persistence aspect to use etc.). I wanted to enable pointcut configuration in the same way, so I've built a private prototype today that shows one way it could be done. Here's how it looks,
and I'd be interested in feedback as to whether others would find this
useful:

Firstly, a new utility class: JoinPointMatcher.  JoinPointMatcher is
constructed with a string (in the expected usage this is obtained from a
config file, but it could be generated in the program itself at runtime
for extreme use cases) which contains an AspectJ pointcut expression,
e.g.:

JoinPointMatcher jpm = new JoinPointMatcher("within(patterntesting..*)");

At any join point, you can ask JoinPointMatcher whether or not it matches:
 if( jpm.matches(thisJoinPoint)) ...

Here's an aspect that allows runtime configuration using this mechanism:

aspect DynamicPointcutConstructionExample {

  private static JoinPointMatcher jpm;

  public void setPointcutExpression(String pointcutExpr) {
    jpm = new JoinPointMatcher(pointcutExpr);
  }

  // this pointcut is used to narrow down as far as possible at compile
time the set of places
  // at which a dynamic pointcut could match (for efficiency)
  pointcut scope() : within(org.xyz.foo);

 before() : scope() && if(jpm.matches(thisJoinPoint)) {
    System.out.println("I matched!!");
 }

}

The consequence you pay for using dynamic pointcuts (I'm using the word
dynamic in analogy to the use of "dynamic" in DII, it may not be the best
term) is that the pointcut matching is (very much) less efficient since
the jpm.match code is driven for every join point in the scope (whereas
the same pointcut specified at compile time would cause the advice to
execute exactly where it needs to with no additional overhead or
redundancy). If a dynamic pointcut proved to be too slow, you could always
switch back to a traditional statically specified pc.

If you're using Spring with the above example, you can configure the
aspect with e.g.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd";>
<beans>
<!-- what follows is an example syntax for specifying a factoryMethod,

I hope we end up with something very close to this in Spring -->
    <bean id="dynamicPointcutConstructionExample"
          class="DynamicPointcutConstructionExample"
          factoryMethod="aspectOf">
        <property name="pointcutExpression">
           execution(* *(..)) && this(Foo)
        </property>
    </bean>
</beans>

Spring will set the value of the pointcutExpression attribute when the
aspect is constructed. Many thanks are due to Rod Johnson for the
inspiration to look into this.

[For the AspectJ developers, here's how the prototype currently works:

JoinPointMatcher uses the PatternParser class to build a Pointcut
(simple).

I then added a new match method in the Pointcut hierarchy that takes a
JoinPoint instead of a shadow, and implemented match(JoinPoint) down the
hierarchy to do the right thing. I had to add match(Class) methods to
TypePatterns too. All the changes were self-contained, and the logic
mirrors the matching logic for shadows.

Restrictions in the implementation are that you can't use cflow or
cflowbelow in a dynamic pointcut (matching is done solely on the current join point), you can't use if() (don't want to go off into code), and you can't provide context information (bind "this(foo)" to a parameter "foo")
or refer to other pointcuts.

Essentially I've written a convenience class for writing a powerful form
of if() pcds.
]

Love it? Hate it? Let me know...

Cheers, Adrian.

I know, I know, I digressed for a day - Back to 1.2rc2 and AJDT
tomorrow....

-- Adrian
Adrian_Colyer@xxxxxxxxxx

aspectj-users-admin@xxxxxxxxxxx wrote on 07/05/2004 09:17:35:

Hi,

On the Pattern Testing project (http://patterntesting.sf.net), we have
aspects that enforce some design rules. For example:

public abstract aspect AbstractDatabaseTestAspect
{
    /**
     * Specify what is application code that should be subject to the
     * pattern test.
     *
     * Ex: <code>pointcut applicationCode():
within(patterntesting.*)</code>
     */
    public abstract pointcut applicationCode();

    /**
     * Specify which classes are allowed to call JDBC.
     */
    public abstract pointcut allowedCode();

    /**
     * Specify which JDBC calls are forbidden.
     */
    pointcut forbiddenCalls() :
        call(public * java.sql..*(..)) ||
        call(public * javax.sql..*(..));

    /**
     * Raise error if violations found.
     */
    declare error: (applicationCode() && forbiddenCalls()) &&
!allowedCode() :
        "It is not allowed to use the JDBC API from here";
}

Now, the question is: How can we make the applicationCode and
allowedCode pointcuts configurable by the end users?

Of course one solution is to have create classes that extend the
abstract aspect. However that sounds complex when compared to simple
configuration data (the end users would need to create a project where
to put the code, etc).

Any idea?

Note: The solution we're using so far (but which I don't like because
it's tied to the build system) is to use Ant filters:

public aspect DatabaseTestAspect extends AbstractDatabaseTestAspect
{
    public pointcut applicationCode() :
        @maven.patterntesting.suite.java.database.applicationCode@;
    public pointcut allowedCode() :
        @maven.patterntesting.suite.java.database.allowedCode@;
}

Thanks
-Vincent

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

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




Back to the top