|
technology
[
jonas
]
21:18, Monday, 8 August 2005
The second part of our article series about JRockit JVM support for AOP is now published. This article describes in more detail on how the API is used, showing some code samples and ends with a discussion in which we try to explain how we address the questions and issues (around the shortcomings of bytecode manipulation) raised in part one in the series. The prototype will be downloadable soon, stay tuned.
[
jonas
]
10:18, Wednesday, 27 July 2005
Writing multi-threaded applications in Java can as you know be quite tricky, and if not done correctly, one can easily end up with deadlock situations. For example, take a look at this little code snippet. This piece of Java code implements a Node, which has three methods (that is of our interest):
Here's the implementation:
This class might look okay, but it actually suffers from potential deadlock. For example what happens if, one thread T1 invokes
Thread T1 acquires the lock for node n1, and thread T2 acquires the lock for node n2. Thread T1 now invokes This program is however easily fixed by using the technique of totally ordering all objects in the system.
In this program, all locks will be acquired in increasing order, guaranteed to be the same for all threads, and thereby avoiding deadlock situations.
[
jonas
]
12:07, Monday, 18 July 2005
As I mentioned in my previous blog entry, the synchronized
block is currently not a supported join point in AspectJ 5 (or in any other AOP framework):
Currently you can for example pick out a call to a method that is declared as being synchronized and you can pick out calls to Thread:: notify()/notifyAll()/wait(). Meaning that being able to pick out synchronized blocks are the only missing piece left in order to completely control thread management and locking in Java. The actual bytecode modifications needed to make this work would be fairly simple, but capturing the correct semantics in a good language design would probably be a lot trickier. Well, I'm not a language designer, but I think the problem is interesting so I will spend some time discussing it anyway. In bytecode, a synchronized block is represented as a MONITOR ENTRY and a MONITOR EXIT bytecode instruction pair (however these are not required to be paired). The first natural approach would to let these two bytecode instructions be join points and treat them similar to field access and modification (PUTFIELD and GETFIELD bytecode instructions), meaning simply pick out (and intercept) this single bytecode instruction. Just to clarify what I mean, here is an example of how the syntax for the above given semantics could look in the AspectJ pointcut expression language: lock(Type t) && withincode(* Foo.bar(..)) && args(t) unlock(Type t) && withincode(* Foo.bar(..)) && args(t) Let us take a look at a synchronized block and how it would be affected:
synchronized(obj) {
// body
}
In bytecode to this is equivalent to (pseudo code):
MONITOR ENTRY // lock on obj
// body
MONITOR EXIT
If we now add around advices to these join points then we could for example get (pseude code):
try {
// a call to the around advice, which calls the lock manager
aroundAdvice1(obj) --> myLockManager.acquire(obj);
// body
} finally {
aroundAdvice2(obj) --> myLockManager.release(obj);
}
This approach would give you the possibility to completely control how locking is done in Java (including the possibility of enhancing or completely screw up the Java Memory Model (JMM)). On the other hand it does not allow you to pick out the actual code block that is synchronized (is this something that we want?) . Therefore this approach is perhaps not intuitive, since in Java source code, what we see is not lock acquisition and release but a code block that is guaranteed to be synchronized. So now let's try to approach this problem from the perspective of source code. Since AspectJ (and AspectWerkz) already has limited support for the synchronized keyword by allowing calls to methods declared as being synchronized to be matched, let us take a look at the semantics for this join point. Here's a simple method that is defined as being synchronized:
public synchronized void doStuff() {
// body
}
What this actually means is:
public void doStuff() {
synchronized(this) {
// body
}
}
The options we have of picking up this synchronized code block (wrapped up in the doStuff() method) is by using a execution(synchronized void *.doStuff())or call(synchronized void *.doStuff())pointcut. Using the execution pointcut, the above method body would be transformed to (pseudo code):
synchronized(this) {
// the advice has option of invoking the original body
myAroundAdvice(this)
}
I.e. only synchronized body is matched and intercepted. If we are using the call pointcut, the same code snippet would be transformed to (pseudo code): ... // the advice has the option of invoking the original synchronized block myAroundAdvice(this) ... I.e. the whole synchronized block, including the locking is matched (and intercepted). (This is conceptionally true, in regards to the locking, which is easy to see if you think of the doStuff() method as being inlined.)
I will not go into much detail about how these semantic differences should be expressed in the pointcut language here (this post is too long already). But for example, the last discussion would require the possibility of making a distinction between picking out a code block // pick out synchronized block including the locking block-inclusive(synchronized(Type t)) && withincode(* Foo.bar(..)) && args(t) // pick out only the synchronized block's body, not the locking block-exclusive(synchronized(Type t)) && withincode(* Foo.bar(..)) && args(t) (These "block" pointcut descriptors can of course be used in any kind of block, loops, conditional statements etc., if/whenever they are supported in AspectJ.) To sum up, the questions are: Do we want the power of intercepting the whole locking mechanism (but not the synchronized body), or is it better to follow the semantics we have for a synchronized method? Which approach addresses the use cases we want? Is the most intuitive? Is more orthogonal? Thoughts? Comments? Ideas?
[
jonas
]
15:34, Tuesday, 7 June 2005
Terracotta just recently launched a product (DSO) for clustering POJOs in a completely transparent way. What I find interesting in this product is not mainly in the clustering and caching, but how they make use of AOP and loadtime weaving to make it completely transparent. This sounds a lot like techniques that we have been working on in AspectWerkz last years, and I was not too surprised, although very happy, to learn that they are actually using AspectWerkz. It is really great to see some of the ideas that Alex and I have been working on being used in new and interesting ways and in real-world applications. They seem to use techniques that are fairly similar to the Unit of Work aspect library that I wrote for the AWare aspect library. Meaning: record field changes to object graphs within a transaction which can be committed/rolled back./etc. add specific methods that are defined declaratively. However they have extended to this idea by adding semantics currently not available in AOP. For example being able to pick out synchronized blocks. This is a great idea, and when you think of it, it is in a way a hole in the current AOP implementations. Currently you can for example pick out a call to a method that is declared as being synchronized and you can pick out calls to Thread:: notify()/notifyAll()/wait(). Meaning that being able to pick out synchronized blocks are the only missing piece left in order to completely control thread management and locking in Java. The actual bytecode modifications needed to make this work would be fairly simple, but capturing the correct semantics in a good language design would probably be a lot trickier. All and all a very interesting product that shows the beauty of AOP and loadtime weaving in action, go and check it out. /Jonas
[
jonas
]
20:02, Sunday, 29 May 2005
If you're interested in knowing more about what the future holds for AOP, then you should come to the technical session TS-7659 (titled "Runtime Aspects With JVM Support") on Tuesday, June 28 at JavaOne 2005. This will be the first time ever to show an enterprise JVM - BEA JRockit - with native AOP support. Alex Vasseur and myself have been pushing for this idea since the early days of AspectWerkz when we joined the JRockit group, and it's finally taking shape, with now support for AspectJ 5, the de-facto standard for AOP in Java. Credit should also go to Joakim Dahlstedt, the CTO of JRockit, who has been playing a leading role in the design and implementation. We will talk about the current problems with bytecode based weaving (multiple agents, double bookkeeping, performance etc.) and then discuss how these problems can be solved through native JVM support. We will show a prototype of our implementation, go through the programming model and run a live demo. Here is the abstract: "Aspect Oriented Programming (AOP) is growing in popularity. Adding aspects at runtime, dynamic weaving, can be a very powerful technique for diagnostics, profiling, or debugging of a running system. The concept of adding aspects at runtime (dynamic weaving) is looked upon with skepticism by some. It's also easy for multiple instrumenting agents to cause havoc for each other. We have implemented prototype changes to our Java™ Virtual Machine (JVM™ software), BEA Weblogic JRockit, to support dynamic weaving in the JVM software in a controlled fashion. We also have modified AspectJ 5 to try out this functionality. We believe our changes to the JVM software to support dynamic weaving lessens the skepticism about runtime aspects and allows for multiple instrumenting agents to coexist. Don't miss it, see you there.
[
jonas
]
10:17, Friday, 20 May 2005
I just got back from the Nordic Software Developer Summit (Nordev) 2005. Strange enough, this is the first good developer conference that we have had in Sweden. Altogether it was a really good event with two major tracks, one Java and one .Net. The Java track had interesting talks on topics like: AOP :-), agile development, hibernate, spring, manageability of the JRockit JVM etc. (e.g. the usual suspects). I was glad to see that AOP got a lot of focus with talks from myself and Rickard Oberg and a hands-on workshop (on AspectJ). Both sessions were packed, and people seemed enthusiastic about it. Of all things you can be nervous about, I was nervous about speaking in Swedish (my native language). I had never spoken about AOP in Swedish so it was interesting and a good exercise :-). Everything went pretty well except that eclipse died on me when I was starting up the demo (3.1 M6). (The demo was about how to write a unit of work to achieve transparent persistence/replication/transaction management, perhaps something for an upcoming blog post...). I enjoyed Rickard's talk. He based the talk on examples from the CMS application and he has built, and it was interesting to see both simple and advanced usage of AOP in the real world application. He's using a pretty extreme approach to AOP in which every single object is built up a using intertype declarations (introductions/mixins). I do not think that this model fits every project, and it for sure has drawbacks, but in their CMS application it has given them extremely high reuse and development speed. He showed examples of client aspects, how objects can render themselves differently based on which intertype declarations it has. For example, if an object in their GUI (a page, a site, a portlet etc.) has the intertype declaration ACL applied to it then it will give you the possibility to open up a window to manage security for this object. This object can also be given the Tree intertype declaration, which will allow you to browse the object in a tree structure etc. He also showed examples on how they do client synchronization and cluster wide replication, using the same aspect (which simply records the events triggered and then plays it back). Another interesting aspect that they have is what he calls partial object versioning, in which intertype declarations can be versioned and different versions can be used (in the same object), depending on how system is configured. Rickard gave an example of a customer that came in with a new functional requirements very late in the release cycle, requirements that required redesign of some parts of the system, but that he managed to solve in a simple and generic way by applying an aspect. Then he talked about the need for tools and that most problems that people are complaining about when it comes to AOP are actually not related to AOP, but to the lack of good tools. He showed one interesting tool that they are using on a daily basis, a tool for doing a diff of the system. This diff showed you which advice and or intertype declarations had been removed or added since the last time the system's state was recorded. For example, after a regular refactoring, the diff should be zero. This is something that we should add to AJDT. All and all a good conference, you should try to get there next year.
[
jonas
]
16:21, Monday, 21 March 2005
The upcoming release of JRockit will contain a new, completely killing, tool for memory leak detection. It allows you to (among many other things) to profile an application running in production with (almost) zero overhead (without shutting it down or any preparation whatsoever). Bill Burke and Dion Almaer has already blogged about it. If you are interested to find out more, we have set up a webinar demo that anyone can join. Drop me an email at [jboner AT gmail DOT com] and I will send you the 'dial in info'. ------ ---------------------------- Web Meeting --------------------------------- When: Wednesday, March 23, 2005 10:00 AM-11:00 AM (GMT-07:00) Arizona. Where: Dial In/Web Meeting Web Meeting Address: https://www.webmeeting.att.com Toll Free Dial In Number: (866)214-3176 Int'l Access/Caller Paid Dial In Number: (404)827-9098 ACCESS CODE: 5519740 --------------------------------------------------------------------------------
[
jonas
]
21:28, Tuesday, 15 March 2005
AOSD 2005 has just started. I am excited, and have high expectations since last years conference was a real hit, and this year we have a separate industry track with many interesting talks coming up, f.e. Grady Booch is doing a keynote. I will be giving a talk on AspectWerkz 2 and the road to AspectJ 5 at the AOSD 2005 conference hosted at the Intercontinental hotel in Chicago. If you are in the area, please drop in and say hi. If you are interested you can read the abstract etc. here For those who can't make it, I will make the slides available online after the conference. Hope to see you there...
[
jonas
]
17:10, Thursday, 6 January 2005
One of the new features in the AspectWerkz 2 architecture is that it comes with a full-blown interception framework that allows per instance programmatic deployment with most of the AOP semantics preserved. You can make use of this using both the regular load-time weaving or the AW Proxy (that I blogged about here)
In short you will get:
POJO pojo = new POJO();
// adds tracing to all methods in the 'pojo' instance
((Advisable) pojo).aw$addAdvice(
"* *.*(..)",
new BeforeAdvice() {
public Object invoke(JoinPoint jp) {
System.out.println("Entering: " + jp.getSignature().toString());
}
}
);
The Advisable interface
From a users perspective pretty much all you need to know about is in the
The
aw$
is just to minimize method clashes since these methods are added to your classes on-the-fly.
The different Advice interfacesThe intercept framework supports all main types of advice defined in AOP today:
JoinPoint
instance as a parameter. This class contains f.e. contextual information bout the join point (member) we are executing before/after/around. Such as caller and callee instances and types, argument values and types etc. You can also see that some of the advice takes an optional parameter which provides direct access to the return value or the exception instance.
Preparing your application
To make this work you finally need to tell AspectWerkz which classes you want to make "advisable" and to which extent. This is done in the
Example:
<aspectwerkz>
<system id="intercept-sample">
<advisable expression="within(my.application.domain.*)" pointcut-type="call|set|get"/>
</system>
</aspectwerkz>
Bringing it all together
So now we have talked about the
In this example we are taking a regular POJO and we are adding an advice that will be applied to all methods that are annotated with the annotation
...
POJO pojo = new POJO();
((Advisable) pojo).aw$addAdvice(
"@OneWay * *.*(..)",
new AroundAdvice() {
private Executor m_threadPool = Executors.newCachedThreadPool();
public Object invoke(JoinPoint jp) throws Throwable {
m_threadPool.execute(
new Runnable() {
public void run() {
try {
// proceed with the invocation in a new thread
jp.proceed();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
);
return null;
}
}
);
...
The META-INF/aop.xml
file looks like this:
<aspectwerkz>
<system id="intercept-sample">
<advisable expression="within(sample.intercept.POJO)" pointcut-type="call"/>
</system>
</aspectwerkz>
Resources
I have not written any specific sample application for this article but if you want you can look at and run the tests in the AspectWerkz distribution. You can download the distribution here. The tests are in
[
jonas
]
04:12, Wednesday, 15 December 2004
One of the new features in the AspectWerkz 2 architecture is the ability to deploy and undeploy aspects at runtime, e.g. to do "hot" deployment and undeployment. The implementation is based on HotSwap class redefinition and handles 'change sets' which ensures that the changes to each single join point is atomic. What this means in practice is that if you for example are deploying an aspect which has one before and one after advice, both advising the same join point (method/field etc.) then either both of them will be added or none.
The API exposed to the user is very simple and straight forward to use. Everything is handled by the
DeploymentHandle deploy(Class aspect)
DeploymentHandle deploy(Class aspect, ClassLoader deployLoader)
DeploymentHandle deploy(Class aspect, DeploymentScope scope)
DeploymentHandle deploy(Class aspect, DeploymentScope scope, ClassLoader deployLoader)
DeploymentHandle deploy(Class aspect, String xmlDef)
DeploymentHandle deploy(Class aspect, String xmlDef, ClassLoader deployLoader)
DeploymentHandle deploy(Class aspect, String xmlDef, DeploymentScope scope)
DeploymentHandle deploy(Class aspect, String xmlDef, DeploymentScope scope, ClassLoader deployLoader)
void undeploy(Class aspect)
void undeploy(Class aspect, ClassLoader loader)
void undeploy(DeploymentHandle deploymentHandle)
As you can see you can for example choose to deploy an annotation defined aspect, e.g. a regular Java5 class with AspectWerkz defined annotations (or a regular Java 1.3/1.4 class with AspectWerkz defined JavaDoc annotations, compiled with AspectWerkz's JavaDoc annotation compiler):
DeploymentHandle
(that is returned from each of these methods) here.
You also deploy a class without any annotation definition and pass in the definition in XML format. Here you pass in a string containing the Use-case: Implementing a JMX monitoring aspectNow let's take a look at a concrete example on how to hot deploy an aspect that can do some monitoring for us, report that to an JMX MBean and then undeploy it when the monitoring is done. Writing the aspectSo first, here is the (main parts of the) JMX monitoring aspect:
@Aspect
public class ResponseTimeAspect {
... // methods for registering the MBean lazily, member fields etc.
// the "invocationsToMonitor" pointcut will be defined at deployment time
// in the aop.xml file
@Around("invocationsToMonitor")
public Object monitor(StaticJoinPoint jp) throws Throwable {
Signature signature = jp.getSignature();
long tsStart = System.currentTimeMillis();
Object result = null;
try {
result = jp.proceed();
} finally {
// note: this code is using a JMX helper method and
// we will have one MBean per jointpoint signature (i.e. method, field, etc.)
long tsElapsed = System.currentTimeMillis() - tsStart;
ObjectInstance mbeanI = registerMBean(signature);
if (mbeanI != null) {
m_mbeanServer.invoke(
mbeanI.getObjectName(),
"update",
new Object[]{new Long(tsElapsed)},
new String[]{long.class.getName()}
);
}
}
return result;
}
public static void enableMonitoring(String pointcut) { ... }
public static void disableMonitoring() { ... }
}
As you can see, this aspect is defined using Java5 annotations, but if you are using Java 1.3/1.4 you can define the annnotations using JavaDoc (just put the annotation exactly as it is in the JavaDoc for the method/class) and run AnnotationC
on the class. Then the rest in this article should stay the same. You can read more about the AnnotationC
compiler here.
Hot deploy and undeploy the aspectAs you can see we have added two static methods to the aspect, these will be used to enable and disable the response time aspect. E.g. deploy it and undeploy it.
First we have the
public static void enableMonitoring(String pointcut) {
String xmlDef = "<aspect><pointcut name='invocationsToMonitor' expression='" + pointcut + "'/></aspect>";
Deployer.deploy(ResponseTimeAspect.class, xmlDef);
}
Second we have the
public static void disableMonitoring() {
Deployer.undeploy(ResponseTimeAspect.class);
}
Use the aspect to monitor JDBC SQL statementsThis means that in the user code, all we need to do to enable and disabling this aspect is to invoke these two methods. Here we will monitor the executions of all JDBC statements:
public static void trackResponseTimeOfSqlQueries() {
ResponseTimeAspect.enableMonitoring("call(* java.sql.Statement+.execute*(..))");
... // wait a while to do a recording
ResponseTimeAspect.disableMonitoring();
}
What this pointcut expression (
Note: we could in this specific use-case benefit from retrieving and storing the parameter value to the So now after doing some monitoring you should be able to easily see the data in any JMX console. For example hook in JConsole which you can read more about in this article. Define a deployment scopeFinally, to get this to work in the general case we need to define a deployment scope which defines the set potential join points that we might want to monitor at runtime. This construct gives you (as a application developer or vendor) control over which join points are exposed to the hot deployment API i.e. helps to prevent usage of the hot deployment facilities in specific areas of the application.
This can be done either in the
<aspectwerkz>
<system id="monitoring">
<deployment-scope name="response_time" expression="call(* sample.deployment..*.*(..))"/>
</system>
</aspectwerkz>
Here we have defined a deployment scope that picks out all method calls in our sample application, which means that we can safely deploy our In the code above we have an implicit contract that says that we can not define the aspect to be deployed outside a deployment scope. If we do not define a pointcut that is wider than this it is all fine. But we can now use this deployment scope to ensure that we only deploy the aspect at valid points. To do that we need to retrieve a handle to the scope like this (can be done at any point):
DeploymentScope scope = SystemDefinition.getDefinitionFor(loader, systemId).getDeploymentScope("response_time");
Now we can use the
Deployer.deploy(ResponseTimeAspect.class, xmlDef, scope);
Notes on the impact of the deployment scope preparation
The preparation made by the deployment scope construct means in practice that we are simply adding a level of indirection by adding a call to a When we do undeploy of an aspect, if this aspect is the last one that affects the join point, then the class' bytecode will be reverted to the same state it had before any aspect was deployed. ResourcesMore info about the JMX ResponseTimeAspect
The code for the monitoring aspect is based on the implementation of the You can also check out the complete AWare project which has some tests for the JMX module. Info about how to check out the sources can be found here. More info about the Deployer Module
I have not written any specific sample application for this article but if you want you can look at and run the tests for the deployer module in the AspectWerkz distribution. You can download the distribution here. The tests are in
The
[
jonas
]
19:50, Monday, 13 December 2004
The ideaAfter implementing the AW Proxy extension to AspectWerkz I figured, why not hook into the most widely used proxy implementation out there: cglib and let AspectWerkz weave in the aspects that are around just before the proxy is returned to the user. The solutionSo, this is all that this cglib extension does: asks AspectWerkz if it has anything to say about the class that has just been proxied. If so, then let the AspectWerkz weaver do its job, e.g. weave in the aspects that are currently deployed (on the classpath), and when returns the proxy to the user. If no AspectWerkz aspects are found that has pointcuts that matches the class being proxied then nothing happens. All that was needed to make this work was to add 30 lines of code to one single cglib class. How do I use it?
This means that all you need to do to make any cglib based applications, and there are many: Geronimo, dynaop, Spring AOP, Hibernate etc., become "aspectwerkz-aware" is to replace one single class in the Or.
If you can't or don't want to patch the What is the impact on my existing code?If no AspectWerkz aspects are found that has pointcuts that matches the class being proxied then nothing happens. And if AspectWerkz is not available then the whole process is skipped. So basically, there is nothing to loose, it is pay as you go (or should I rather say: gain as you go ;-) ). How do I get it?The single file you need can be found in the AspectWerkz RC2 distribution, which you can find here.
The cglib extension is in the
In the Enjoy.
[
jonas
]
05:31, Wednesday, 8 December 2004
SummaryProxies are an important piece in the J2EE puzzle. Since it offers a non-intrusive an more transparent way of weaving in advice/interceptors. However, non of the current proxy implementations utilizes all the rich semantics of AOP (as defined by AspectJ), the expressiveness of a real pointcut pattern language and has the speed of statically compiled code. AW Proxy is here to try to narrow this gap. It makes use of the rich semantics for AOP in AspectWerkz and is very high-performant due to the use of static compilation (utilizing the AspectWerkz weaver). All wrapped up a very simple and intuitive API. The need for proxiesThe two arguments against load-time weaving that we hear the most are:
Adding the possibility of using AspectWerkz together with proxies is something that Alex and I have been talking about for a long time but never implemented due to lack of time. Well, this weekend I took the time and it was actually more simple than I thought. After a couple of hours coding (taking the cglib route with its "class proxy", e.g creating a new class on-the-fly that extends the target class and which methods and constructors delegates to the base class' methods, but with the difference that they don't wrap the arguments but pass them on as they are, which gives a lot better performance), I had a working solution. Introducing AW ProxyThe benefit with using the AspectWerkz Proxies compared to the regular load time weaving is that there are no VM options. You simply create your proxy and before it is returned to you it is weaved with the aspects that happens to be available on the classpath at that time. The API is pretty straight forward. All you need is in the
org.codehaus.aspectwerkz.proxy.Proxy
class which has the following API:
// Returns a new proxy for the class specified
public static Object newInstance(Class clazz);
// Returns a new proxy for the class specified, instantiates it by invoking the constructor
// with the argument list specified
public static Object newInstance(Class clazz, Class[] argumentTypes, Object[] argumentValues);
// Same as above, but with optional parameters for caching and making the proxy advisable
public static Object newInstance(Class clazz, boolean useCache, boolean makeAdvisable);
// Same as above, but with optional parameters for caching and making the proxy advisable
public static Object newInstance(Class clazz, Class[] argumentTypes, Object[] argumentValues,
boolean useCache, boolean makeAdvisable);
How to use the API?
Here is a little example on how to use the
// creates and instantiates a new proxy for the class Target
Target target = (Target) Proxy.newInstance(Target.class, false);
That's it!
This Utilizing programmatic runtime deploymentAs I said before, when you create your proxy it will get automatically weaved with all the matching aspects that are found (on the classpath). This is most of the time what you want and need, but there might be cases when you want to add a specific feature, at runtime, to a specfific instance only. In these cases you need programmatic runtime per instance deployment. One of the new features in the AspectWerkz 2 architecture is that it comes with a full-blown interception framework that allows per instance programmatic deployment with most of the AOP semantics preserved.
In short you will get:
POJO pojo = new POJO();
// adds tracing to all methods in the 'pojo' instance
((Advisable) pojo).aw$addAdvice(
"* *.*(..)",
new BeforeAdvice() {
public Object invoke(JoinPoint jp) {
System.out.println("Entering: " + jp.getSignature().toString());
}
}
);
The advice "interceptors" that are supported are:
Now we can combine use this feature together with the AW Proxies. All proxies that are created implements the Example
In this example we create and instantiate a new proxy for the class
Advisable target = (Advisable) Proxy.newInstance(Target.class, true, true);
target.aw$addAdvice(
"String *.*(..)",
new AfterReturningAdvice() {
public void invoke(JoinPoint jp, Object returnValue) {
// do some stuff
}
}
);
BenefitsPlain proxies with rich AOP semantics
The benefits are, besides a less intrusive and more transparent approach, that you can utilize the rich semantics for AOP (well, not all, see below for limitations) that are supported AspectWerkz. Such as, a rich pointcut expression language, before/after/around advice, deployment modules defined by the Very high-performantYou will also get the full performance of the AspectWerkz 2 architecture. If you are interested details of the benchmark we made (and/or run it yourself) then you can read this paper. But in short AW Proxy is roughly:
Limitations
Since it is a proxy approach it only supports Resources
This new feature will be available in AspectWerkz 2.0 RC2 that will be available soon. Until then you can check out the sources from the CVS and build it yourself (by invoking
There are some samples in the Enjoy.
[
jonas
]
13:36, Monday, 6 December 2004
The AspectWerkz 2 architecture has been designed to be an Extensible Aspect Container, which can deploy and run arbitrary aspects. You can read more about the details in this article. In this article I will show you how you can make use of this container to run Spring AOP aspects more performant plus utilize the annotation-driven AOP in AspectWerkz along with its more expressive pointcut pattern language. In this article I am using Spring as an example but everything covered here applies to all frameworks that implements the AOP Alliance interfaces (e.g. dynaop, JoyAop, JAC etc.). Write a regular Spring adviceFirst we write a regular spring advice that implements authentication:
public class AuthenticationAdvice implements MethodBeforeAdvice {
public void before(Method m, Object[] args, Object target) throws Throwable {
// try to authenticate the user
// if not authenticated throw a SecurityException
}
}
Define the advice using Java 5 annotations
In this example we will not define this advice using the slightly verbose Spring config file. But make use of Java 5 annotations. In AspectWerkz you have a set of predefined annotations that we can use, f.e. one for each advice type. The advice we have implemented here is a before advice so we will use the
public class AuthenticationAdvice implements MethodBeforeAdvice {
@Before("authenticationPoints")
public void before(Method m, Object[] args, Object target) {
// try to authenticate the user
// if not authenticated throw a SecurityException
}
}
Here we bind the advice to the pointcut named "authenticationPoints"
, this pointcut will pick out all the points where we want authentication to take place. However we do not define this pointcut yet. Since we want to make this aspect reusable, then it is better to just compile it, put it in a jar and then at deployment time resolve this definition by defining the pointcut in the external META-INF/aop.xml
file.
We can of course choose to not define the pointcut in an external XML file but directly in the
@Before("call(@RestrictedOperation * *.*(..))")
public void before(Method m, Object[] args, Object target) {
...
}
if we think that that is beneficial. (Then the META-INF/aop.xml
only have to define the aspect class name, see below for details).
Define the pointcut in the external aop.xml file
Now all we need to do put this advice to work is to write the little
<aspectwerkz>
<system id="spring-extension-sample">
<aspect class="my.application.aspects.AuthenticationAdvice">
<pointcut name="authenticationPoints" expression="call(@RestrictedOperation * *.*(..))" />
</aspect>
</system>
</aspectwerkz>
Here we defined the pointcut to pick out all method calls to a method that is marked with the annotation @RestrictedOperation
.
Note that we are using a call pointcut here, which means that this advice will execute on the client side and not the server (something that is not possible with regular spring aop which only supports execution pointcuts). This can be beneficial in many situations, it can f.e. can save us a remove call from the client to the server, or take some load off the server if the client is executing in a separate VM, etc. Start up the applicationThe last thing we need to do is to add two VM options:
aspectwerkz-core-RC2.jar
, aspectwerkz-RC2.jar
, aw-ext-spring-0.1.jar
and aw-ext-aopalliance-0.1.jar
plus the regular AspectWerkz dependency jars on the classpath. (You find the aspectwerkz jars in the aspectwerkz distribution and the aw-ext-*.jar jars you need to build yourself (see Resources for details).
The you can start up the application as usual using
We have been thinking of providing a way of defining the spring aspect model on the application level (per What about my Spring bean config file, dependency injection etc?Good news is that you can still use your regular Spring bean config file and let Spring do its job, with dependency injection, bean configurations etc. AspectWerkz has a pluggable factory mechanism for the aspect instantiation and life-cycle management. We have written a factory for the Spring framework that allows you to use Spring to configure your aspects/advice just as usual. Read more about that here. Much better performanceApart from allowing defining your aspects using Java5 annotations and using the semantics of the AspectWerkz pointcut language and weaver, you will also get much better performance (ranging between 1300 to 50 percent). I won't go into detail on that here but you can read more about it in this article. DrawbacksEverything has tradoffs and there are of course some drawbacks in using the AspectWerkz Extensible Aspect Container as the runtime environment for your Spring aspects/advice:
Resources
I have not written any specific sample application for this article but if you want you can look at and run the tests in the AspectWerkz distribution. You can download the distribution here. The tests are in
The
[
jonas
]
08:28, Tuesday, 2 November 2004
I gave an interview for the spanish Java community site javaHispano.org.
Here is the
english version.
[
jonas
]
20:01, Tuesday, 31 August 2004
The Spring Framework is a very powerful library for J2EE development. It comes with an AOP implementation (based on proxies) that is in many cases sufficient in terms of what you need to do. However, there are many situations where you need a more full-blown AOP framework (such as AspectWerkz) to do the job.
On the other hand AspectWerkz (even though it has a decent API for configuration and management) could sometimes benefit from more finegrained and expressive configuration and life-cycle management, which is one thing that Spring does very well.
In short, it is sometimes beneficial to use these two frameworks together and I will now show you a first step on how you can make that happen.
AspectWerkz has a very open architecture in regards to
instantiation, configuration and management of the aspects. Here I will show you how you can make use of this to
take control over your aspects using Spring. (The concepts are the same for PicoContainer
, HiveMind or a home-grown IoC implementation.)
In AspectWerkz instantiation, management and configuration of aspects is handled by an "aspect
container" and to make it easier for users to provide their own custom implementation
it provides the abstract
org.codehaus.aspectwerkz.aspect.AbstractAspectContainer
class which handles all the nitty-gritty details.
All we have to do is to extend the
org.codehaus.aspectwerkz.aspect.AbstractAspectContainer
class and implement the abstract Object createAspect()
method.
So let us do that. Here is the implementation of our SpringAspectContainer
:
public class SpringAspectContainer extends AbstractAspectContainer {
public static final String SPRING_ASPECT_CONTAINER_CONFIG = "spring-bean-config.xml";
/**
* The Spring bean factory.
*/
private XmlBeanFactory m_factory = null;
/**
* Creates a new aspect container strategy that uses the Spring framework to manage aspect instantiation and
* configuaration.
*
* @param crossCuttingInfo the cross-cutting info
*/
public SpringAspectContainer(final CrossCuttingInfo crossCuttingInfo) {
super(crossCuttingInfo);
}
/**
* Creates a new aspect instance.
*
* @return the new aspect instance
*/
protected Object createAspect() {
if (m_factory == null) {
InputStream is = null;
try {
is = ClassLoader.getSystemResourceAsStream(SPRING_ASPECT_CONTAINER_CONFIG);
m_factory = new XmlBeanFactory(is);
} finally {
try {
is.close();
} catch (Throwable e) {
throw new WrappedRuntimeException(e);
}
}
}
// here we are letting Spring instantiate the aspect based on its name
// (the m_infoPrototype field is the CrossCuttingInfo instance passed to the base class)
return m_factory.getBean(m_infoPrototype.getAspectDefinition().getName());
}
}
This is all that is needed implementation wise. Now we only have to define which
aspects should be managed by our new container and configure the aspect in the
Spring bean config file.
To tell the AspectWerkz system that we want to deploy a specific aspect in our
custom aspect container we have to specify that in the regular
aop.xml
file like this:
<aspect class="some.package.MyAspect" container="some.other.package.SpringAspectContainer">
...
</aspect>
For details on the aop.xml
file (what it is, how it is used etc.) see the online documentation.
To configure the aspect we just configure it like any other Spring bean class:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="some.package.MyAspect"
class="some.package.MyAspect"
singleton="false"
init-method="intialize">
<property name="someProperty">
...
</property>
...
</bean>
...
</beans>
For details on how to define your bean classes see the Spring documentation. But
here are some explainations:
<bean id="org.codehaus.aware.security.RoleBasedAccessProtocol"
class="org.codehaus.aware.security.RoleBasedAccessProtocol"
singleton="false"
init-method="intialize">
<property name="type">
<value>JAAS</value>
</property>
<property name="roles">
<list>
<value>admin</value>
<value>jboner</value>
</list>
</property>
<property name="permissions">
<list>
<bean class="org.codehaus.aware.security.Permission">
<property name="role">
<value>jboner</value>
</property>
<property name="className">
<value>org.codehaus.aware.security.SecurityHandlingTest</value>
</property>
<property name="methodName">
<value>authorizeMe1</value>
</property>
</bean>
<bean class="org.codehaus.aware.security.Permission">
<property name="role">
<value>jboner</value>
</property>
<property name="className">
<value>org.codehaus.aware.security.SecurityHandlingTest</value>
</property>
<property name="methodName">
<value>authorizeMe2</value>
</property>
</bean>
</list>
</property>
</bean>
You can find the code for the SpringAspectContainer
along with many other reusable aspects in the AWare library.
Which is a community-driven OSS library for reusable aspects for AspectWerkz.
[
jonas
]
10:40, Friday, 11 June 2004
Yesterday evening I put together a series of two introductory tutorials on AspectWerkz (a third is on its way).
Tutorial one: Hello World.
Tutorial two: Hijacking Hello World
I hope that these will help you to get started with AspectWerkz.
Enjoy.
[
jonas
]
13:40, Monday, 5 April 2004
Just got back from the AOSD 2004 conference. Great experience. Had fun, attended many great talks, met a lot of interesting people etc.
Here are the links to the talks that I/we gave:
[
jonas
]
07:17, Friday, 19 March 2004
Today we released the 0.10 Release Candidate 1 of AspectWerkz.
Which forms the foundation for the next generation of AspectWerkz.
AspectWerkz has gone through a lot of changes, the whole core engine has
for example been thrown out and replaced by a much more flexible and
performant one. The join point model is much more expressive and
orthogonal we have also implemented a JIT compiler that is making
AspectWerkz much more performant. On top of that we have a new
implementation of true runtime weaving, which allows you to redefine
your aspect model including adding new pointcuts at runtime.
Read more about it here.
[
jonas
]
06:58, Friday, 19 March 2004
The AspectWerkz project is since a a month ago sponsored by BEA Systems.
Both Alexandre and I, the founders and primary contributors to
AspectWerkz, are full time BEA employees. I work with the JRockit
engineering team in Stockholm, and our primary objective is to make
AspectWerkz the leading AOP framework for dynamic AOP, and to ensure
that the JRockit JVM is far and away the best Java platform for AOP.
We are, of course, working on a number of interesting future directions
tight to the in tight coordination with the rest of the BEA products
line, but the near term goals are to build deep and unprecedented
support for AOP, including real-time run-time weaving into JRockit Java
Virtual Machine, and to make AspectWerkz on top of JRockit the number
one choice for dynamic AOP in enterprise application environments.
AspectWerkz still is and will remain open source software, licensed
under LGPL and will continue being platform and vendor independent.
[
jonas
]
11:16, Wednesday, 3 March 2004
I was lucky and our submission to JavaOne was accepted.
This means that Alex and I will do a presentation on "Dynamic Aspect-Oriented Programming in J2EE environments".
See you there.
[
jonas
]
09:32, Wednesday, 18 February 2004
Alex and I will do a half-day tutorial on AspectWerkz at AOSD 2004.
The tutorial will be an introduction to AOP/AOSD and AspectWerkz and to how it can be used in real-world enterprise applications.
It will include hands-on exercises and we will show you how to implement services like:
[
jonas
]
09:31, Wednesday, 17 December 2003
Since the last example of the new 'self-defined aspects' model in AspectWerkz
seemed to have caused a lot of confusion and made people miss the point, I will
in this post try to give a more detailed explaination of the previous 'Role-Based
Security' example.
First I just want to stress that this new model of defining the aspects will NOT in any sense make the old pure XML based and the doclet based approaches obsolete. We are here simply providing a new option. A ticket out of deployment descriptor hell.
I also would like to mention that this new model is completely user-demand
driven. It solely exists due to the fact that there is a high need for it.
It basically solves three problems that the users have been complaining about:
/** * @Aspect perThread */ public abstract class AbstractRoleBasedAccessController extends Aspect { protected Subject m_subject = null; protected final SecurityManager m_securityManager = ... /** To be defined by the concrete aspect. */ Pointcut authenticationPoints; /** To be defined by the concrete aspect. * Pointcut authorizationPoints; /** * @Around authenticationPoints */ public Object authenticateUser(JoinPoint joinPoint) throws Throwable { if (m_subject == null) { // no subject => authentication required Context ctx = ... // get the principals and credentials m_subject = m_securityManager.authenticate(ctx); // throws an exception if not authenticated } Object result = Subject.doAsPrivileged( m_subject, new PrivilegedExceptionAction() { public Object run() throws Exception { return joinPoint.proceed(); }; }, null ); return result; } /** * @Around authorizationPoints */ public Object authorizeUser(JoinPoint joinPoint) throws Throwable { MethodJoinPoint jp = (MethodJoinPoint)joinPoint; if (m_securityManager.checkPermission( m_subject, jp.getTargetClass(), jp.getMethod())) { // user is authorized => proceed return joinPoint.proceed(); } else { throw new SecurityException(...); } } } /** * @Aspect perThread */ public class RoleBasedAccessController extends AbstractRoleBasedAccessController { /** * @Execution * *..facade.*.*(..) */ Pointcut authenticationPoints; /** * @Execution * *..service.*.*(..) */ Pointcut authorizationPoints; }
<aspectwerkz>
<system id="security-test">
<package name="example">
<use-aspect class="RoleBasedAccessController">
<param name="type" value="JAAS">
</use-aspect>
</package>
</system>
</aspectwerkz>
Here we can see that I have the possibility of parameterizing the aspect. This
can be very useful in some situations since it allows you to use the same aspect
with different configurations in different contexts
If you think that inheritance adds too much coupling then you have the
option of skipping the concrete subclass completely and define
the pointcuts in the XML definition instead:
<aspectwerkz>
<system id="security-test">
<package name="example">
<use-aspect class="AbstractRoleBasedAccessController">
<pointcut-def name="authenticationPoints" type="execution" pattern="* *..facade.*.*(..)"/>
<pointcut-def name="authorizationPoints" type="execution" pattern="* *..service.*.*(..)"/>
</use-aspect>
</package>
</system>
</aspectwerkz>
If you want to play with this new release (which is a release candidate) you can download it here.
[
jonas
]
14:17, Monday, 1 December 2003
On Wednesday (December 3d) I will give a presentation on dynamic Aspect-Oriented Programming in J2EE environments using AspectWerkz at JavaPolis/BeJUG 2003
The presentation will aim at give an understanding on how AOP and AspectWerkz can be used in real-world enterprise applications and will include a couple of hands-on examples.
If you are in Antwerpen, stop by and say hi.
[
jonas
]
09:31, Monday, 27 October 2003
The upcoming release of AspectWerkz (0.9)
will have support for a new definition model in which the aspects are self-defined.
This means that implementation and definition is written in the same self-contained component.
In this new definition model the aspects are regular Java classes and the advices and introductions
are regular methods and inner classes in these classes. The aspects can be abstract and inheritance
is used and treated like regular Java class inheritance. The meta-data (aspect definition) is defined using
runtime attributes and is currently compiled in into the class on bytecode level (not needed in Java
1.5.x and above).
This new approach makes it easy to create reusable self-contained aspect components and libraries.
It simplifies both the implementation, maintainance and refactorings since everything is
written in one single Java class.
This is an example of a testing aspect defining a virtual mock object mixin that will be
introduced (along with its interfaces) on all the classes matching the pattern foo.baz.*.
/** * @Aspect perInstance */ public class MockObjectAspect extends Aspect { /** * @Introduce foo.baz.* */ class MockObject extends MyBase implements Traceable, Metered { // implementation of the mock object } } /** * @Aspect perThread */ public class RoleBasedAccess extends Aspect { private Subject m_subject; /** * @Call * *..facade.*.*(..) */ Pointcut facadeMethods; /** * @Execution * *..service.*.*(..) */ Pointcut needsAuthorization; /** * @Before facadeMethods */ public void authenticateUser(JoinPoint joinPoint) throws Throwable { Context context = ... // get principals and credentials boolean granted = SecurityManager.authenticateUser(context) // authenticate the user (f.e. using JAAS) if (granted) { m_subject = ... // set the subject } else { throw new SecurityException("user not authenticated: " + context); } } /** * @Around needsAuthorization */ public Object authorizeUser(JoinPoint joinPoint) throws Throwable { MethodJoinPoint jp = (MethodJoinPoint)joinPoint; boolean granted = SecurityManager.checkPermission(m_subject, jp.getTargetClass(), jp.getMethod()); if (granted) { // proceed with normal method invocation return joinPoint.proceed(); } else { throw new SecurityException("access denied at " + jp.getTargetClass() + "." + jp.getMethodName()); } } } |