[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("&gt;&gt;&gt; Retrieved concurrency lock");
+   
+         // part 2: proceed to joinpoint execution
+         result = invocation.invokeNext();
+   
+      // part 3: release lock after joinpoint execution
+         System.out.println("&lt;&lt;&lt; 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 &lt;any-method-name&gt;(@JoinPoint &lt;any Joinpoint type&gt;)
+</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>
+&#64;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>
+&lt;bind pointcut="execution(public void $instanceof{Transaction}->run())"&gt;
+      &lt;before name="beforeAdvice" aspect="mypackage.MutexAspect"/&gt;
+      &lt;after name="afterAdvice" aspect="mypackage.MutexAspect"/&gt;
+&lt/bind&gt;
+</pre>
+</p><p>
+As you can see, you just need to declare a usual bind tag, and add to it 
+<tt>&lt;before&gt;</tt> and <tt>&lt;after&gt;</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("&gt;&gt;&gt; Retrieved concurrency lock");
+   
+         // part 2: proceed to joinpoint execution
+         result = invocation.invokeNext();
+   
+      // part 3: release lock after joinpoint execution
+         System.out.println("&lt;&lt;&lt; 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("&gt;&gt;&gt; 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("&lt;&lt;&lt; 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("&gt;&gt;&gt; Retrieved concurrency lock");
+      }
+   }
+   
+   public void afterAdvice(@JoinPoint Joinpoint joinPoint)
+   {
+      synchronized(lock)
+      {
+         locked = false;
+         lock.notify();
+         System.out.println("&lt;&lt;&lt; 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] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Depositing US$ 50.00 to account A
+     [java] &lt;&lt;&lt; Releasing concurrency lock
+     [java] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Transfering US$ 100.00 from account B to account C
+     [java] &lt;&lt;&lt; Releasing concurrency lock
+     [java] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Withdrawing US$ 10.00 from account A
+     [java] &lt;&lt;&lt; Releasing concurrency lock
+     [java] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Transfering US$ 89.11 from account C to account A
+     [java] &lt;&lt;&lt; Releasing concurrency lock
+     [java] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Depositing US$ 51.00 to account B
+     [java] &lt;&lt;&lt; Releasing concurrency lock
+     [java] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Withdrawing US$ 0.11 from account C
+     [java] &lt;&lt;&lt; Releasing concurrency lock
+     [java] &gt;&gt;&gt; Retrieved concurrency lock
+     [java] Withdrawing US$ 5.00 from account B
+     [java] &lt;&lt;&lt; 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