I want my AOP!, Part 3
Tutorial Details:
I want my AOP!, Part 3
I want my AOP!, Part 3
By: By Ramnivas Laddad
Use AspectJ to modularize crosscutting concerns in real-world problems
spect-oriented programming (AOP) -- a new programming paradigm -- allows modular implementation of crosscutting concerns. In Part 1 of this three-part series covering AOP, I defined a concern as:
A concern is a particular goal, concept, or area of interest. In technology terms, a typical software system comprises several core and system-level concerns. For example, a credit card processing system's core concern would process payments, while its system-level concerns would handle logging, transaction integrity, authentication, security, performance, and so on. Many such concerns -- known as crosscutting concerns -- tend to affect multiple implementation modules. Using current programming methodologies, crosscutting concerns span over multiple modules, resulting in systems that are harder to design, understand, implement, and evolve.
AOP works in addition to, not as a replacement for, object-oriented programming (OOP). AspectJ, a free AOP implementation for Java, helps create software systems that are easier to implement, understand, and maintain.
Read the whole "I Want My AOP" series:
Part 1. Separate software concerns with aspect-oriented programming
Part 2. Learn AspectJ to better understand aspect-oriented programming
Part 3. Use AspectJ to modularize crosscutting concerns in real-world problems
In Part 1 , I introduced basic AOP concepts, while in Part 2 I presented an AspectJ tutorial. Armed with your new AOP and AspectJ knowledge, in this article you'll learn how to modularize crosscutting-concern implementations with real-world examples.
Although I discuss several AspectJ examples, by no means do I imply that such implementations can only work using AspectJ. In general, AOP (and for that matter, any other programming methodology) is not about what but about how. This article's examples demonstrate that implementing software systems with AOP offers crosscutting-concern modularity advantages, including more focused code and maintenance ease.
I keep the examples intentionally simple to focus on AOP's and AspectJ's usages. For example, in the thread-pooling example, I do not implement the pool management's full functionality. However, I do concentrate on how to apply the AOP techniques. Also note, for logging I deliberately use System.out.println() instead of the logging aspect to keep the focus from the main problem to the logging concern.
This article looks at examples from several categories: resource-pool management, policy enforcement, characteristics-based behavior, and flexible access control. I wrap up the article (and the series) by presenting several other ways to use AspectJ in your work.
Note: You can download this article's source code from Resources .
Example 1: Resource-pool management modularization
One common way to optimize resource usage recycles previously created resources such as threads and database connections.
A typical OOP approach to introducing resource pooling requires you to make a few up-front decisions. To wit, the design must specify when and how to obtain resources from the pool and how to put them back. Since profiling the system necessitates many optimizations, designing up-front resource pooling proves difficult. However, introducing such support afterwards requires you to modify many source files. (See Part 1 's "Architecture's Dilemma" section for more details.) Further, the conventional approach lacks agility; it is not easy to turn on, off, or tune such optimizations.
Let's see how AOP and AspectJ help implement resource-pool management in a modularized fashion.
First, let's implement a simple TCP/IP service for converting requested strings to uppercase. The server creates a new thread each time a new connection request arrives. Once a thread completes serving a connection, it terminates naturally. The implementation below is simple Java without any AspectJ constructs:
// UppercaseServer.java
import java.io.*;
import java.net.*;
public class UppercaseServer {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage: java UppercaseServer ");
System.exit(1);
}
int portNum = Integer.parseInt(args[0]);
ServerSocket serverSocket = new ServerSocket(portNum);
while(true) {
Socket requestSocket = serverSocket.accept();
Thread serverThread
= new Thread(new UppercaseWorker(requestSocket));
serverThread.start();
}
}
}
class UppercaseWorker implements Runnable {
private Socket _requestSocket;
public UppercaseWorker(Socket requestSocket) throws IOException {
System.out.println("Creating new worker");
_requestSocket = requestSocket;
}
public void run() {
BufferedReader requestReader = null;
Writer responseWriter = null;
try {
requestReader
= new BufferedReader(
new InputStreamReader(_requestSocket.getInputStream()));
responseWriter
= new OutputStreamWriter(_requestSocket.getOutputStream());
while(true) {
String requestString = requestReader.readLine();
if (requestString == null) {
break;
}
System.out.println("Got request: " + requestString);
responseWriter.write(requestString.toUpperCase() + "\n");
responseWriter.flush();
}
} catch(IOException ex) {
} finally {
try {
if (responseWriter != null) {
responseWriter.close();
}
if (requestReader != null) {
requestReader.close();
}
_requestSocket.close();
} catch (IOException ex2) {
}
}
System.out.println("Ending the session");
}
}
Next, let's see how AspectJ can add a thread-pooling crosscutting concern. First, write a simple ThreadPool class that acts as a stack for available threads. The get() method extracts a thread from the stack, whereas the put() method pushes one in. The put() method also contains the DelegatingThread class that delegates the run() method to the _delegatee worker object:
// ThreadPool.java
import java.util.*;
public class ThreadPool {
List _waitingThread = new Vector();
public void put(DelegatingThread thread) {
System.out.println("Putting back: " + thread);
_waitingThread.add(thread);
}
public DelegatingThread get() {
if (_waitingThread.size() != 0) {
DelegatingThread availableThread
= (DelegatingThread)_waitingThread.remove(0);
System.out.println("Providing for work: " + availableThread);
return availableThread;
}
return null;
}
static class DelegatingThread extends Thread {
private Runnable _delegatee;
public void setDelegatee(Runnable delegatee) {
_delegatee = delegatee;
}
public void run() {
_delegatee.run();
}
}
}
You now possess the classes needed to add thread pooling. Next, write an aspect that uses the ThreadPool class to add thread pooling to the server:
// ThreadPooling.java
public aspect ThreadPooling {
ThreadPool pool = new ThreadPool();
//=====================================================================
// Thread creation
//=====================================================================
pointcut threadCreation(Runnable runnable)
: call(Thread.new(Runnable)) && args(runnable);
Thread around(Runnable runnable) : threadCreation(runnable) {
ThreadPool.DelegatingThread availableThread = pool.get();
if (availableThread == null) {
availableThread = new ThreadPool.DelegatingThread();
}
availableThread.setDelegatee(runnable);
return availableThread;
}
//=====================================================================
// Session
//=====================================================================
pointcut session(ThreadPool.DelegatingThread thread)
: execution(void ThreadPool.DelegatingThread.run()) && this(thread);
void around(ThreadPool.DelegatingThread thread) : session(thread) {
while(true) {
proceed(thread);
pool.put(thread);
synchronized(thread) {
try {
thread.wait();
} catch(InterruptedException ex) {
}
}
}
}
//=====================================================================
// Thread start
//=====================================================================
pointcut threadStart(ThreadPool.DelegatingThread thread)
: call(void Thread.start()) && target(thread);
void around(Thread thread) : threadStart(thread) {
if (thread.isAlive()) {
// wake it up
synchronized(thread) {
thread.notifyAll();
}
} else {
proceed(thread);
}
}
}
Let's examine the implementation in detail:
Pointcut threadCreation() captures joinpoints, thus creating a new thread object taking a Runnable object as the argument.
Advise the threadCreation() pointcut to first check the thread pool for available threads. If no thread is available, create a new one. In either case, set the delegatee to the Runnable object passed in and return that object instead. Note, you do not call proceed() in this advice, so therefore you never execute the captured operation.
Pointcut session() captures the run() method's execution of any ThreadPool.DelegatingThread objects.
By putting session() inside a while(true) loop, you advise session() to never finish the servicing. That ensures a thread, once created, never dies. Once a request is processed, you put the thread back into thread pool and put the thread into waiting state.
Pointcut threadStart() captures a call to the Thread.start() method. It uses isAlive() to check if the thread previously started. That would happen for a thread obtained from a pool and now in a waiting state. Wake up the thread by notifying it. If the thread had not started yet, as for a freshly created thread, proceed with starting the thread.
Note that you made no changes to UppercaseServer.java . The code for a simple test client is in UppercaseClient.java .
You can use the same technique for pooling database-connection objects. Simply capture joinpoints that create new connections and advise them to use one from a connection pool instead, if an appropriate connection is available. You also need to capture joinpoints that close connection objects and advis
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: I want my AOP!, Part 3
View Tutorial: I want my AOP!, Part 3
Related
Tutorials:
Programming Java threads in the
real world, Part
3 - JavaWorld -
November 1998
Programming Java threads in the
real world, Part
3 - JavaWorld -
November 1998 |
Make room for JavaSpaces, Part 3 - JavaWorld March
2000
Make room for JavaSpaces, Part 3 - JavaWorld March
2000 |
Printing in
Java, Part 3 - JavaWorld January 2001
Printing in
Java, Part 3 - JavaWorld January 2001 |
Printing in
Java, Part 5 - JavaWorld March
2001
Printing in
Java, Part 5 - JavaWorld March
2001 |
Clean up your wire protocol with SOAP, Part 2 - JavaWorld April 2001
Clean up your wire protocol with SOAP, Part 2 - JavaWorld April 2001 |
Clean up your wire protocol with SOAP, Part 3 - JavaWorld June
2001
Clean up your wire protocol with SOAP, Part 3 - JavaWorld June
2001 |
Access the world's biggest database with Web DataBase Connectivity -
JavaWorld March 2001
Access the world's biggest database with Web DataBase Connectivity -
JavaWorld March 2001 |
I want my AOP!, Part 1
I want my AOP!, Part 1 |
I want my AOP!,
Part 2
I want my AOP!,
Part 2 |
I want my AOP!, Part 3
I want my AOP!, Part 3 |
Get the inside
track on J2EE architect certification
Get the inside
track on J2EE architect certification |
Good, but
obsolete
Good, but
obsolete |
Use AOP to maintain legacy Java applications
Use AOP to maintain legacy Java applications
This artical shows you how to use aspect-oriented programming (AOP) to gain an unprecedented view into the inner workings of even the most opaque of legacy applications.
Please note that this article assume |
Object-relation mapping without the container
If you follow the latest developer buzz then you\\\\\'ve likely heard of IOC (Inversion of Control) containers and AOP (aspect-oriented programming). |
Second-generation aspect-oriented
programming
Second-generation aspect-oriented
programming |
Aspect-Oriented Annotations
Aspect-Oriented Annotations
Annotations are one of the new language features in J2SE 5.0, and allow you to attach metadata onto any Java construct. Meanwhile, Aspect-Oriented Programming (AOP) is a fairly new technology that makes it easier for you to en |
jGuard v0.60 released!
jGuard v0.60 released!
i am pleased to announce a new major release(v0.60) of the java security library called jGuard(http://sourceforge.net/projects/jguard/).
this library is build on top of jaas, for J2EE web applications.
his goal is to provide f |
Aspect-Oriented Programming in Java
This article is divided into three parts: The first part explaines the concepts of AOP, the second introduces AspectJ(TM), an implementation of the AOP concepts in Java, and part three compares the AOP approach to metalevel programming.
|
Migrating from Windows to Linux, Part 1: Preparation
Want to switch to Linux, but don't know where to begin? In Part I of Migrating from Windows to Linux, THG will help you prepare for the big move. Step-by-step instructions and printable checklists will ensure your happy and safe journey into Linux. |
USB FAQ
FAQ topics include recommended USB patches for the Solaris OS, the USBA 1.0 Framework, libusb support, and more. |
|
|
|