[jboss-cvs] JBossAS SVN: r62012 - in projects/aop/trunk/aop/docs/examples: beforeafter and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Apr 3 00:21:05 EDT 2007
Author: flavia.rainone
Date: 2007-04-03 00:21:05 -0400 (Tue, 03 Apr 2007)
New Revision: 62012
Added:
projects/aop/trunk/aop/docs/examples/beforeafter/
projects/aop/trunk/aop/docs/examples/beforeafter/Account.java
projects/aop/trunk/aop/docs/examples/beforeafter/Bank.java
projects/aop/trunk/aop/docs/examples/beforeafter/Driver.java
projects/aop/trunk/aop/docs/examples/beforeafter/MutexAspect.java
projects/aop/trunk/aop/docs/examples/beforeafter/Parser.java
projects/aop/trunk/aop/docs/examples/beforeafter/SynchronizedAspect.java
projects/aop/trunk/aop/docs/examples/beforeafter/Transaction.java
projects/aop/trunk/aop/docs/examples/beforeafter/beforeafter.html
projects/aop/trunk/aop/docs/examples/beforeafter/build.xml
projects/aop/trunk/aop/docs/examples/beforeafter/input.txt
projects/aop/trunk/aop/docs/examples/beforeafter/jboss-aop.xml
Log:
[JBAOP-44] First part of the tutorial: introduces an example and talks about before/after advices
Added: projects/aop/trunk/aop/docs/examples/beforeafter/Account.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/Account.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/Account.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+public class Account
+{
+ public String name;
+ public double value;
+
+ public Account(String name, double value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String toString()
+ {
+ return name + ": " + Bank.CURRENCY.format(value);
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/Bank.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/Bank.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/Bank.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Bank
+{
+ public static final NumberFormat CURRENCY = NumberFormat.getCurrencyInstance();
+
+ private Map<String,Account> accounts = new HashMap<String,Account>();
+
+ public void createAccount(String name, double amount)
+ {
+ System.out.println("Creating account \'" + name + "\' with initial balance of $" + amount);
+ accounts.put(name, new Account(name, amount));
+ }
+
+ public void printAccounts()
+ {
+ for (Account account: accounts.values())
+ {
+ System.out.println(account);
+ }
+ }
+
+ public Transaction getDepositTransaction(String accountName)
+ {
+ return new Deposit(getAccount(accountName));
+ }
+
+ public Transaction getWithdrawalTransaction(String accountName)
+ {
+ return new Withdrawal(getAccount(accountName));
+ }
+
+ public Transaction getWireTransferTransaction(String fromAccountName,
+ String toAccountName)
+ {
+ return new WireTransfer(getAccount(fromAccountName), getAccount(toAccountName));
+ }
+
+ private Account getAccount(String name)
+ {
+ if (!accounts.containsKey(name))
+ {
+ System.err.println("Account named '" + name + "' does not exist.");
+ System.exit(1);
+ }
+ return accounts.get(name);
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/Driver.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/Driver.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/Driver.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class Driver
+{
+ public static void main(String[] args) throws Exception
+ {
+ // open file
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new FileInputStream("input.txt")));
+ // create bank
+ Bank bank = new Bank();
+
+ // parse file
+ System.out.println();
+ System.out.println("SETUP");
+ System.out.println("=====");
+ Parser parser = new Parser();
+ parser.parseAccountSetup(bank, reader);
+ Collection<Transaction> transactions = parser.parseTransactions(bank, reader);
+
+
+ // create transaction threads
+ Collection<Thread> threads = new ArrayList<Thread>();
+ for (Transaction transaction: transactions)
+ {
+ threads.add(new Thread(transaction, transaction.toString()));
+ }
+
+ // execute transaction threads
+ System.out.println();
+ System.out.println("TRANSACTIONS");
+ System.out.println("============");
+ for (Thread thread: threads)
+ {
+ thread.start();
+ }
+
+ // join transaction threads
+ for (Thread thread: threads)
+ {
+ thread.join();
+ }
+
+ // print final balance
+ System.out.println();
+ System.out.println("FINAL BALANCE");
+ System.out.println("===== =======");
+ bank.printAccounts();
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/MutexAspect.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/MutexAspect.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/MutexAspect.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package mypackage;
+
+import org.jboss.aop.advice.annotation.JoinPoint;
+
+import org.jboss.aop.MethodInfo;
+
+public class MutexAspect
+{
+ private Object lock = new Object();
+ private boolean locked = false;
+
+ public MutexAspect()
+ {
+ System.out.println("CONSTRUCTOR!!!!!");
+ }
+
+ public void beforeAdvice(@JoinPoint MethodInfo joinPoint)
+ {
+ synchronized(lock)
+ {
+ while (locked)
+ {
+ try
+ {
+ lock.wait();
+ }
+ catch(InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+ locked = true;
+ System.out.println(">>> Retrieved concurrency lock");
+ }
+ }
+
+ public void afterAdvice(@JoinPoint MethodInfo joinPoint)
+ {
+ synchronized(lock)
+ {
+ locked = false;
+ lock.notifyAll();
+ System.out.println("<<< Releasing concurrency lock");
+ }
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/Parser.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/Parser.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/Parser.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class Parser
+{
+ private int lineNumber = 0;
+ private int index = 0;
+
+ public void parseAccountSetup(Bank bank, BufferedReader reader) throws IOException
+ {
+ String line = reader.readLine().trim();
+
+ while (line.length() > 0)
+ {
+ // read name and initial balance
+ String accountName = readAccountName(line, "an amount");
+ double balanceValue = readAmount(line);
+
+ // create account
+ bank.createAccount(accountName, balanceValue);
+
+ lineNumber ++;
+ line = reader.readLine().trim();
+ }
+ }
+
+ public Collection<Transaction> parseTransactions(Bank bank, BufferedReader reader)
+ throws IOException
+ {
+ Collection<Transaction> transactions = new ArrayList<Transaction>();
+
+ lineNumber ++;
+ String line = reader.readLine().trim();
+
+ while (line.length() > 0)
+ {
+ // read first string
+ String accountName = readAccountName(line, "an operation");
+ Transaction transaction = null;
+
+ // if first string contains a transfer (A->B, for example)
+ int transferIndex = accountName.indexOf("->");
+ if (transferIndex != -1)
+ {
+ // create wire transfer
+ String fromAccountName = accountName.substring(0, transferIndex);
+ String toAccountName = accountName.substring(transferIndex + 2);
+ transaction = bank.getWireTransferTransaction(fromAccountName, toAccountName);
+ }
+ else
+ {
+ // create deposit or withdrawal
+ switch(line.charAt(++index))
+ {
+ case '+':
+ transaction = bank.getDepositTransaction(accountName);
+ break;
+ case '-':
+ transaction = bank.getWithdrawalTransaction(accountName);
+ break;
+ default:
+ System.err.println("Unexpected character at line " + lineNumber +
+ ". Should be \'+\' or \'-\', to indicate deposit and withdrawal transactions, respectively.");
+ System.exit(1);
+
+ }
+ }
+
+ // read and set transaction amount
+ double amount = readAmount(line);
+ transaction.setAmount(amount);
+
+ // add transaction to collection
+ transactions.add(transaction);
+
+ lineNumber ++;
+ line = reader.readLine().trim();
+ }
+ // return collection of created transactions
+ return transactions;
+ }
+
+ private String readAccountName(String line, String afterAccount)
+ {
+ index = line.indexOf(' ');
+ if (index == -1)
+ {
+ System.err.println("Line " + lineNumber +
+ " should either contain an account name, followed by " + afterAccount +
+ ", or be empty.");
+ System.exit(1);
+ }
+ return line.substring(0, index);
+ }
+
+ private double readAmount(String line)
+ {
+ if (line.charAt(++ index) != '$')
+ {
+ System.err.println("Line " + lineNumber
+ + " is missing \'$\' before amount value");
+ System.exit(1);
+ }
+
+ try
+ {
+ return Double.parseDouble(line.substring(index + 1));
+ }
+ catch (NumberFormatException e)
+ {
+ System.err.println("Cannot read amount value in line " + lineNumber +
+ ": " + e);
+ System.exit(1);
+ }
+ return 0.0;
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/SynchronizedAspect.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/SynchronizedAspect.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/SynchronizedAspect.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+import org.jboss.aop.joinpoint.Invocation;
+
+public class SynchronizedAspect
+{
+ public Object aroundAdvice(Invocation invocation) throws Throwable
+ {
+ Object result;
+
+ // part 1: retrive lock before joinpoint execution
+ synchronized(this)
+ {
+ System.out.println(">>> Retrieved concurrency lock");
+
+ // part 2: proceed to joinpoint execution
+ result = invocation.invokeNext();
+
+ // part 3: release lock after joinpoint execution
+ System.out.println("<<< Releasing concurrency lock");
+ }
+
+ // part 4: return result
+ return result;
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/Transaction.java
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/Transaction.java (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/Transaction.java 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+public abstract class Transaction implements Runnable
+{
+ protected double amount;
+
+ public void setAmount(double amount)
+ {
+ this.amount = amount;
+ }
+}
+
+class Deposit extends Transaction
+{
+ private Account account;
+
+ public Deposit(Account account)
+ {
+ this.account = account;
+ }
+
+ public void run()
+ {
+ System.out.println("Depositing " + Bank.CURRENCY.format(amount) +
+ " to account " + account.getName());
+ account.value += amount;
+ }
+
+ public String toString()
+ {
+ return "DEPOSIT: " + account.getName() + " " + Bank.CURRENCY.format(amount);
+ }
+}
+
+class Withdrawal extends Transaction
+{
+ private Account account;
+
+ public Withdrawal(Account account)
+ {
+ this.account = account;
+ }
+
+ public void run()
+ {
+ System.out.println("Withdrawing " + Bank.CURRENCY.format(amount) +
+ " from account " + account.getName());
+ account.value -= amount;
+ }
+
+ public String toString()
+ {
+ return "WITHDRAWAL: " + account.getName() + " " + Bank.CURRENCY.format(amount);
+ }
+}
+
+class WireTransfer extends Transaction
+{
+ private Account fromAccount;
+ private Account toAccount;
+
+ public WireTransfer(Account fromAccount, Account toAccount)
+ {
+ this.fromAccount = fromAccount;
+ this.toAccount = toAccount;
+ }
+
+ public void run()
+ {
+ System.out.println("Transfering " + Bank.CURRENCY.format(amount) +
+ " from account " + fromAccount.getName() +
+ " to account " + toAccount.getName());
+ fromAccount.value -= amount;
+ toAccount.value += amount;
+ }
+
+ public String toString()
+ {
+ return "TRANSFER: " + fromAccount.getName() + "->" + toAccount.getName() +
+ " " + Bank.CURRENCY.format(amount);
+ }
+}
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/beforeafter.html
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/beforeafter.html (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/beforeafter.html 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,359 @@
+<html>
+<body>
+<p>
+<h2>Before and After Advices</h2>
+</p><p>
+<h4>Overview</h4>
+JBoss AOP provides several types of advices. The advices seen on the previous
+section, as well as JBoss AOP interceptors, provide around join point interception.
+In this example we introduce before and after advices, and compare their roles to
+around advices' role.
+</p><p>
+<h4>Writing Before/After Advices</h4>
+</p><p>
+Before and after advices are lightweight advices when compared to around advices.
+JBoss AOP invokes these advices before or after the joinpoint execution.
+</p><p>
+As we will see in the next <a href="../annotatedparam-return/annotatedparam-return.html">
+example</a>, these advices can have several different signatures. However, in our
+first example, we will use signatures that are closest to what has been shown on
+previous examples.
+
+So, we introduce a before and after advices as being of the form:
+</p><p>
+<pre>
+public void <any-method-name>(@JoinPoint <any Joinpoint type>)
+</pre>
+</p><p>
+Differently from around advices and interceptors, throwing a <tt>Throwable</tt> is
+not necessary, because these advices do not wrap a joinpoint.
+</p><p>
+Instead of <tt>Invocation</tt> instances, before/after advices receive instances
+of <a href="../../misc/joinpoint.html"><tt>org.jboss.aop.IJoinpointInfo</tt> and
+subinterfaces</a> as parameters.
+</p><p>
+Besides this difference, one can notice the presence of parameter annotation <tt>
+@org.jboss.aop.advice.annotation.JoinPoint</tt>. This is necessary because
+before/after advices can receive values with several semantic roles as parameters.
+As we will see <a href="../annotatedparam-return/annotatedparam-return.html">next</a>,
+this annotation is used to distinguish this parameter type from the other ones, so we
+can achieve flexibility on the type, order and presence of advice parameters.
+</p><p>
+<h4>Binding Before/After Advices</h4>
+</p><p>
+To bind a before/after advice to a pointcut, you only need to declare an xml binding as
+follows (please, open up <tt>jboss-aop.xml</tt> to see this example):
+</p><p>
+<pre>
+<bind pointcut="execution(public void $instanceof{Transaction}->run())">
+ <before name="beforeAdvice" aspect="mypackage.MutexAspect"/>
+ <after name="afterAdvice" aspect="mypackage.MutexAspect"/>
+</bind>
+</pre>
+</p><p>
+As you can see, you just need to declare a usual bind tag, and add to it
+<tt><before></tt> and <tt><after></tt> tags for before and after advices
+respectively. Notice that we can mix interceptor declarations and around, before, and
+after advices declarations in a single binding.
+</p><p>
+
+<h4>Around, Before and After Advices</h4>
+</p><p>
+
+As seen on previous sections, around advices wrap the joinpoint execution. An around
+advice replaces the joinpoint execution in the base system, and is responsible for
+forwarding execution to the joinpoint itself, as well as for returning a value to the
+base system.
+</p><p>
+Around advices can be composed by four parts at most: a before joinpoint execution
+block, a proceed to joinpoint step, an after joinpoint execution block, and, finally,
+a return value step. To see an example, consider this <tt>PER_VM</tt> scoped aspect:
+</p><p>
+<pre>
+public class SynchronizationAspect
+{
+ public Object aroundAdvice(Invocation invocation) throws Throwable
+ {
+ Object result;
+
+ // part 1: retrive lock before joinpoint execution
+ synchronized(this)
+ {
+ System.out.println(">>> Retrieved concurrency lock");
+
+ // part 2: proceed to joinpoint execution
+ result = invocation.invokeNext();
+
+ // part 3: release lock after joinpoint execution
+ System.out.println("<<< Releasing concurrency lock");
+ }
+
+ // part 4: return result
+ return result;
+ }
+}
+</pre>
+</p><p>
+<tt>SynchronizationAspect</tt> synchronizes all intercepted joinpoints (in a
+concurrent programming application), avoiding that two or more intercepted joinpoints
+run at the same time.
+</p><p>
+As we can see, <tt>SynchronizationAspect.aroundAdvice()</tt> is composed of four
+steps:
+
+<list>
+ <li>retrieving a lock before the joinpoint execution, achieved by entering the
+ <tt>synchronized</tt> block;</li>
+ <li>proceeding to joinpoint execution;</li>
+ <li>releasing the lock after the joinpoint execution, achieved by exiting the
+ <tt>synchronized</tt> block;</li>
+ <li>and returning joinpoint result.</li>
+</list>
+
+</p><p>
+Notice that this advice does not alter joinpoint execution (the advice does not
+skip it) nor its return result (the advice could overwrite this value, but returns
+the joinpoint return value itself instead). Hence, we can say that the relevant part
+of it is only what is performed before and after the joinpoint (parts 1 and 3). To
+ilustrate the before/after concept, we wish to replace this single around advice
+by a couple of before/after advices. However, we cannot do that by using the
+previous example. A synchronized block cannot be splitten into two parts and still
+achieve the same effect. So, lets first replace this around advice by one that uses a
+mutex intead of a synchronized block:
+</p><p>
+<pre>
+public class MutexAspect
+{
+ private Object lock = new Object();
+ private boolean locked = false;
+
+ public Object aroundAdvice(Invocation invocation) throws Throwable
+ {
+ Object result;
+
+ // part 1: retrive lock before joinpoint execution
+ synchronized(lock)
+ {
+ while (locked)
+ {
+ try
+ {
+ lock.wait();
+ }
+ catch(InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+ locked = true;
+ System.out.println(">>> Retrieved concurrency lock");
+ }
+
+ // part 2: proceed to joinpoint execution
+ result = invocation.invokeNext();
+
+ // part 3: release lock after joinpoint execution
+ synchronized(lock)
+ {
+ locked = false;
+ lock.notify();
+ System.out.println("<<< Releasing concurrency lock");
+ }
+
+ // part 4: return result
+ return result;
+ }
+}
+</pre>
+</p><p>
+
+As much as <tt>SynchronizedAspect</tt>, <tt>MutexAspect</tt> avoids simultaneous
+access to the intercepted joinpoint, and is also composed of the four steps
+(getting a lock, proceeding to joinpoint execution and releasing the lock).
+</p><p>
+However, we can easily split this around advice into two advices: one that retrieves
+the lock, and another one that releases it. We wish to run the first one before a
+joinpoint, and the other one, after it.
+</p><p>
+The example that follows is a copy of the previous one, except that, now, <tt>
+MutexAspect.aroundAdvice()</tt> has been splitten into <tt>MutexAspect.beforeAdvice()
+</tt> and <tt>MutexAspect.afterAdvice()</tt>:
+</p><p>
+<pre>
+public class MutexAspect
+{
+ private Object lock = new Object();
+ private boolean locked = false;
+
+ public void beforeAdvice(@JoinPoint Joinpoint joinPoint)
+ {
+ synchronized(lock)
+ {
+ while (locked)
+ {
+ try
+ {
+ lock.wait();
+ }
+ catch(InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+ locked = true;
+ System.out.println(">>> Retrieved concurrency lock");
+ }
+ }
+
+ public void afterAdvice(@JoinPoint Joinpoint joinPoint)
+ {
+ synchronized(lock)
+ {
+ locked = false;
+ lock.notify();
+ System.out.println("<<< Releasing concurrency lock");
+ }
+ }
+}
+</pre>
+</p><p>
+Notice that, in this version, parts 2 and 4 are gone (proceeding to joinpoint
+execution and returning its result). This is due to the fact that before and after
+advices don't wrap a joinpoint, they are just executed before or after it.
+
+</p><p>
+<h4>Around vs Before/After</h4>
+</p><p>
+As is shown in this example, around advices can generally be broken into two related
+before and after advices. The reverse is also true.
+However, there are some subtleties that can help you to choose one form or the
+other.
+</p><p>
+First of all, these are advantages of using around advices:
+</p><p>
+<list>
+<li>capability of replacing the entire joinpoint execution, by skipping the call to
+ <tt>Invocation.invokeNext() method</tt>;</li>
+<li>capability of skipping the invocation of subsequent around advices and
+ interceptors, by calling <tt>Invocation.invokeTarget()</tt> instead of
+ <tt>Invocation.invokeNext()</tt>;</li>
+<li>addition of meta-data, available on Invocation objects only.</li>
+</list>
+</p><p>
+Besides this list, there are aspects that cannot be implemented as a pair of before
+and after advices. An example would be the <tt>SynchronizedAspect</tt> shown before.
+A synchronized block cannot be broken into two blocks and achieve the
+same result as one single synchronized block. In the example, we wrote a similar,
+more complex aspect to ilustrate the before/after advice concept. In real
+applications, however, this aspect would not be replaced by a more complex one,
+unless this could bring advantages to the application.
+</p><p>
+When one needs one or more of the cited capabilities, or has an aspect that needs
+to be written as an around advice, we advise the use of around advices.
+</p><p>
+On the other hand, before and after advices also provide some advantages. A pair of
+related before/after advices:
+</p><p>
+<list>
+<li>is lightweight, when compared to around advices</li>
+<li>can be bound to different joinpoints. The before advice can be invoked before
+joinpoint A and after advice, after joinPoint B</li>
+</list>
+</p><p>
+Regarding the second item in the list, notice that this can be extremely useful in
+the case of MutexAspect. Instead of controling the multi-threaded access to a single
+joinpoint, we could obtain the lock before a joinpoint, and release it later,
+after a different joinpoint execution. This allows the synchronization of a sequence
+of joinpoints as if they were a single unit.
+</p><p>
+Notice that replacing the joinpoint return value is not inherent to around advices
+and interceptors. An after advice can also return a value (for more on this, refer to
+<a href="../returnvalue/returnvalue.html">Return Value</a>).
+</p><p>
+<h4>Unrelated Before and After Advices</h4>
+</p><p>
+Despite the application of before and after advices shown in this example, these
+advices can also be used in an unrelated, independent manner.
+</p><p>
+An aspect whose code needs to run only before the joinpoint execution should contain
+only before advices. The same applies to an aspect that needs to execute after
+a joinpoint execution, regarding after advices. Furthermore, an aspect that provides
+functionalities that need to be run before a joinpoint execution, and functionalities
+that need to be run after, should contain a mix of unrelated before and after advices.
+</p><p>
+Examples of unrelated before and after advices will be shown in the next topics of
+this tutorial.
+</p><p>
+<h4>Applying MutexAspect</h4>
+</p><p>
+In our example, we apply <tt>MutexAspect</tt> to a classic example of sinchronization
+and concurrent programming application.
+</p><p>
+Suppose you have bank accounts and operations on accounts can be performed
+concurrently. If we don't synchronize those operations we can end up with an invalid
+account balance.
+</p><p>
+An example would be two operations on account <tt>A</tt>. Suppose one of them
+is a deposit of $30.00, while the other one is a withdrawal of $10.00. If these
+operations are run in an unsynchronized manner, like follows:
+</p><p>
+<list>
+<li>deposit: read balance: $50.00</li>
+<li>withdrawal: read balance: $50.00</li>
+<li>deposit: add $30.00</li>
+<li>withdrawal: subtract $10.00</li>
+<li>deposit: write final balance of $80.00</li>
+<li>withdrawal: write final balance of $40.00</li>
+</list>
+The final balance of the account would be $40.00, and the deposit of $50.00 would
+have been completely ignored, since its final balance has been overwritten by
+the withdrawal operation.
+</p><p>
+<h4>Running</h4>
+</p><p>
+To compile and run:
+<pre>
+ $ ant
+</pre>
+It will javac the files and then run the AOPC precompiler to manipulate the bytecode, then finally run the example. The output should be similar to this:
+<pre>
+run:
+ [java] TRANSACTIONS
+ [java] ============
+ [java] Using context classloader sun.misc.Launcher$AppClassLoader at 133056f to load aspect mypackage.MutexAspect
+ [java] Using context classloader sun.misc.Launcher$AppClassLoader at 133056f to load aspect mypackage.MutexAspect
+ [java] >>> Retrieved concurrency lock
+ [java] Depositing US$ 50.00 to account A
+ [java] <<< Releasing concurrency lock
+ [java] >>> Retrieved concurrency lock
+ [java] Transfering US$ 100.00 from account B to account C
+ [java] <<< Releasing concurrency lock
+ [java] >>> Retrieved concurrency lock
+ [java] Withdrawing US$ 10.00 from account A
+ [java] <<< Releasing concurrency lock
+ [java] >>> Retrieved concurrency lock
+ [java] Transfering US$ 89.11 from account C to account A
+ [java] <<< Releasing concurrency lock
+ [java] >>> Retrieved concurrency lock
+ [java] Depositing US$ 51.00 to account B
+ [java] <<< Releasing concurrency lock
+ [java] >>> Retrieved concurrency lock
+ [java] Withdrawing US$ 0.11 from account C
+ [java] <<< Releasing concurrency lock
+ [java] >>> Retrieved concurrency lock
+ [java] Withdrawing US$ 5.00 from account B
+ [java] <<< Releasing concurrency lock
+
+ [java] FINAL BALANCE
+ [java] ===== =======
+ [java] A: US$ 159.11
+ [java] C: US$ 10.78
+ [java] B: -US$ 4.00
+
+</pre>
+</p><p>
+</p>
+</body>
+</html>
\ No newline at end of file
Added: projects/aop/trunk/aop/docs/examples/beforeafter/build.xml
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/build.xml (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/build.xml 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project default="run" name="JBoss/AOP">
+ <target name="prepare">
+ <property name="jboss.aop.root" value="../../../.."/>
+ <property name="jboss.aop.lib" value="${jboss.aop.root}/lib"/>
+ <property name="jboss.aop.lib50" value="${jboss.aop.root}/lib-50"/>
+
+ <path id="jboss.aop.classpath">
+ <fileset dir="${jboss.aop.lib}">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <path id="jboss.aop.classpath50">
+ <fileset dir="${jboss.aop.lib50}">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <path id="classpath">
+ <path refid="jboss.aop.classpath"/>
+ <pathelement path="."/>
+ </path>
+
+ <property name="aop50jar" value="${jboss.aop.lib50}/jboss-aop-jdk50.jar"/>
+
+ <path id="classpath50">
+ <path refid="jboss.aop.classpath50"/>
+ <pathelement path="."/>
+ </path>
+
+ <taskdef name="aopc" classname="org.jboss.aop.ant.AopC" classpathref="jboss.aop.classpath"/>
+ </target>
+
+
+ <target name="compile" depends="prepare">
+ <javac srcdir="."
+ destdir="."
+ debug="on"
+ deprecation="on"
+ optimize="off"
+ includes="**">
+ <classpath refid="classpath50"/>
+ </javac>
+ <aopc compilerclasspathref="classpath50" classpathref="classpath50" verbose="true">
+ <sysproperty key="jboss.aop.path" value="jboss-aop.xml"/>
+ <sysproperty key="jboss.aop.verbose" value="true"/>
+ <classpath path="."/>
+ <src path="."/>
+ <aoppath path="jboss-aop.xml"/>
+ </aopc>
+ </target>
+
+ <target name="run" depends="compile">
+ <java fork="yes" failOnError="true" className="Driver">
+ <sysproperty key="jboss.aop.path" value="jboss-aop.xml"/>
+ <sysproperty key="jboss.aop.verbose" value="true"/>
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
+ <target name="compile50standalone" depends="prepare">
+ <javac srcdir="."
+ destdir="."
+ debug="on"
+ deprecation="on"
+ optimize="off"
+ includes="**">
+ <classpath refid="classpath50"/>
+ </javac>
+ </target>
+
+ <target name="run.50.instrumented" depends="compile50standalone">
+ <java fork="yes" failOnError="true" className="Driver">
+ <sysproperty key="jboss.aop.path" value="jboss-aop.xml"/>
+ <sysproperty key="jboss.aop.verbose" value="true"/>
+ <sysproperty key="jboss.aop.instrumentor" value="org.jboss.aop.instrument.GeneratedAdvisorInstrumentor"/>
+ <jvmarg value="-javaagent:${aop50jar}"/>
+ <classpath refid="classpath50"/>
+ </java>
+ </target>
+
+</project>
Added: projects/aop/trunk/aop/docs/examples/beforeafter/input.txt
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/input.txt (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/input.txt 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,12 @@
+A $30.00
+B $50.00
+C $0.00
+
+A +$50.00
+A -$10.00
+B -$5.00
+B->C $100.00
+C->A $89.11
+C -$0.11
+B +$51.00
+
Added: projects/aop/trunk/aop/docs/examples/beforeafter/jboss-aop.xml
===================================================================
--- projects/aop/trunk/aop/docs/examples/beforeafter/jboss-aop.xml (rev 0)
+++ projects/aop/trunk/aop/docs/examples/beforeafter/jboss-aop.xml 2007-04-03 04:21:05 UTC (rev 62012)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<aop>
+
+ <aspect class="mypackage.MutexAspect" scope="PER_VM"/>
+
+ <bind pointcut="execution(public void $instanceof{Transaction}->run())">
+ <before name="beforeAdvice" aspect="mypackage.MutexAspect"/>
+ <after name="afterAdvice" aspect="mypackage.MutexAspect"/>
+ </bind>
+
+</aop>
More information about the jboss-cvs-commits
mailing list