-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html> <head>
-<title>AspectJ Exercises</title>
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<!-- This file represents the Exercises for the hands-on AspectJ
+ tutorial. It is commonly checked into CVS with identifying
+ information for the latest conference (such as presenters
+ and publication information). -->
+
+<!-- When you use it for your own purposes, don't forget to
+ modify at the very least anything that says
+ id="copyright" or class="presenter" -->
+
+<!-- Also, the gif included at the end is somewhat fragile,
+ so be careful with different paper sizes. -->
+
+
+<head>
+ <title>Hands-on Programming with AspectJ — Exercises</title>
+ <style type="text/css">
+div.instruction { padding: 0.5em; border-width: 1px; border-style: solid }
+body { background-color: #FFF; margin: 2em }
+body { font-family: "Gill Sans MT", "Gill sans", "Trebuchet ms", Verdana, sans-serif; }
+.newpage { page-break-before: always }
+pre { margin-left: 1em; border-left-style: solid; border-width: 1px; padding-left: 1em;}
+h2 { margin-top: 4ex; }
+h3 { margin-top: 4ex; border-bottom-style: solid; border-width: 1px }
+.presenter { text-align: right }
+@page {
+ size: 8.5in 11in;
+ margin: 3in;
+ marks: cross
+}
+@media print {
+ body { font-size: 10pt }
+ #copyright {
+ font-family: "Times New Roman", "Times Roman", fixed;
+ font-size: 8pt;
+ display: normal;
+ position: absolute;
+ bottom: 1in;
+ border-style: none
+ }
+}
+@media screen {
+ #copyright { display: none }
+}
+ </style>
</head>
-<body bgcolor="white">
-<h2>Hands-on Aspect-Oriented Programming with AspectJ</h2>
+<body>
+
+<h1>Hands-on Programming with AspectJ</h1>
+
+<div class="presenter">Erik Hilsdale</div>
+<div class="presenter">Mik Kersten</div>
+<div class="presenter">http://www.eclipse.com/aspectj</div>
+
+<h2>Overview</h2>
-<h3>Organization</h3>
+<p> In this tutorial you will solve some canonical programming
+tasks using AspectJ. The tasks progress from writing
+non-functional, development-only aspects to writing aspects that
+augment a deployed program with crosscutting features. This
+follows the same progression most users see in their own adoption
+of AspectJ. </p>
-<p> This tutorial consists of the attendees solving AspectJ
-programming tasks (with unit tests) in pairs or triples and discussing
-the answers with the group and with the tutorial presenters. The
-exercises work with a figure editor together with JUnit test cases.
-They progress, as most users do in their adoption of AspectJ, from
-non-functional, development-only aspects to aspects which augment a
-deployed program with crosscutting features. </p>
+<p> Since this is a hands-on tutorial, you will be working with a
+live AspectJ distribution. The example code we will be working
+with is a simple figure editor, along with JUnit tests for each
+exercise. We will break up into groups of two to three people
+per computer to foster discussion within the group as well as
+with the presenters. </p>
+
+<p> If you have a laptop running a recent version of Windows,
+MacOS or Linux, feel free to bring it along. We will provide CDs
+and other installation media for a standalone AspectJ system,
+including the figure editor code these exercises are based on and
+unit tests for the exercises. If you don't have a laptop with
+you, don't worry about it. </p>
<p> These notes consist of four sections of exercises, a quick
reference to AspectJ syntax, and a UML diagram of a figure editor
-program. While you should feel free to have a quick look through
-these notes before the tutorial, please do not try to seriously read
-or do the exercises; you'll learn a lot more by working through it in
-groups. </p>
-
-<h3>Command-line usage</h3>
-
-<p> At the beginning of the tutorial we will make available a binary
-package that includes the tests, the base code, JUnit, and a
-distribution of AspectJ. All it needs is information about where Java
-lives (so set your JAVA_HOME environment variable). It assumes that
-you unzip it in c:\ (on Windows) or in your home directory (on Linux):
-If you put it somewhere else, edit setpaths or setpaths.bat, as
-appropriate. Once all this is done, run <code>setpaths.bat</code> or
-<code>source setpaths</code> to export some other needed environment
-variables. </p>
-
-<p> All the files in the program are listed in base.lst, including
-test cases and an empty answer aspect,
-<code>answers/Answer.java</code>. Therefore, if you write your
-answers there, all you need to do is compile base.lst, either in an
-IDE or with </p>
-
-<blockquote><PRE>
+program. </p>
+
+<div class="instruction"> If you receive these tutorial notes
+early, feel free to have a quick look, especially at the UML
+diagram and quick reference. But you'll be cheating yourself if
+you try to do the exercises early; you'll learn a lot more by
+working through it in groups during the tutorial proper. </div>
+
+<div id="copyright">
+Copyright is held by the author/owner(s). <br />
+OOPSLA\9204, October 24-28, 2004, Vancouver, British Columbia, Canada <br />
+2004 ACM 04/0010
+</div>
+
+<h3 class="newpage">Command-line usage</h3>
+
+<p> While the AspectJ system is well integrated with a number of
+IDEs, it can also be used as a command-line compiler. The
+standalone package we provide (containing the tests, the base
+code, JUnit, and a distribution of AspectJ) needs information
+about where Java lives (so set your JAVA_HOME environment
+variable). It assumes that you unzip it in c:\ (on Windows) or
+in your home directory (on Linux): If you put it somewhere else,
+edit <code>setpaths</code> or <code>setpaths.bat</code>, as
+appropriate.
+</p>
+
+<p> Each time you open a new shell window run
+<code>setpaths.bat</code> or <code>source setpaths</code> to
+export some other needed environment variables. </p>
+
+<p> In general, all the files in the program are listed in
+<code>base.lst</code>, including test cases and an empty answer
+aspect, <code>answers/Answer.java</code>. Therefore, if you
+write your answers there, all you need to do is compile
+<code>base.lst</code>, either in an IDE or with </p>
+
+<pre>
$ ajc -argfile base.lst
-</PRE></blockquote>
+</pre>
<p> Before you move onto another exercise, though, make sure to copy
your answer into a different file so we can discuss the answers
together:
</p>
-<blockquote><PRE>
+<pre>
> copy answers/Answer.java answers/2a.java (Windows)
$ cp answers/Answer.java answers/2a.java (Unix)
-</PRE></blockquote>
+</pre>
<p> After building the system, you should invoke Java on the compiled
test class. On the command-line, this this would be </p>
-<blockquote><PRE>
+<pre>
$ java tests.Test2a
-</PRE> </blockquote>
-
-<p> (For these exercises, when we give examples of execution we will
-show the command-line use, but of course if you are using JBuilder,
-Forte/NetBeans, Emacs, or Eclipse, use the appropriate compile and
-execute tools.) </p>
+</pre>
<p> The default test, <code>tests.Test</code>, performs some
rudimentary tests on figure elements, and so is a useful test to run
-periodically. Looking at the JUnit tests for each exercise may also
-be helpful. </p>
-
-<p> Again, we will be looking at some solutions and having discussion,
-which is much more difficult without incremental solutions. So when
-you go from one exercise to the next, make sure to save your work in a
-file and go on to work in a different file, even if you plan to
-duplicate some code. </p>
-
-<h3>Environment</h3>
-
-<p> You may use whatever editor or environment you choose to work
-through these exercises. We provide a simple code-browser that can
-work well as an editor for these short exercises, in addition to
-providing better visualization of how aspects affect the system: </p>
-
-<blockquote><PRE>
-$ ajbrowser base.lst
-</PRE></blockquote>
-
-<p> With the browser you can edit code (including the
-<code>answers/Answer.java</code> file), and after saving hit the build
-button to start an ajc compile. We recommend you start up another
-shell, though, to run the JUnit tests (and don't forget to run the
-<code>setpaths</code> script when you open the new shell): You could
-set up the run button to run a test through the Options menu, but
-we've found this is fairly cumbersome. </p>
+periodically. You should also look at the JUnit tests for each
+exercise as you do it. </p>
+
+<p> Again, we will be looking at solutions and having discussion,
+which is much more difficult without incremental solutions. So
+when you go from one exercise to the next, <strong>save your
+work</strong> in a file before going on to the next exercise
+even if you plan to duplicate some code. </p>
+
+<div class="instruction"> When we give examples of execution in
+these exercises we will show the command-line use, but of course
+you should use the appropriate compile and execute tools if you
+are using the AspectJ browser, Emacs, or Eclipse. </div>
<!-- ============================== -->
-<br style="page-break-after: always" />
-<h2>1. Static Invariants</h2>
+<h2 class="newpage">1. Static Invariants</h2>
<p> The easiest way to get started with AspectJ is to use it to
enforce static invariants.
</p>
-<h3>a. Catch old tracing</h3>
+<h3>1.a. Find old tracing</h3>
-<p> <strong>Sample Exercise</strong>: The main point of this exercise
-is to make sure your configuration works. Type in the answer below
-into your answer file, make sure you get the desired compile-time
-error, remove the offending line, and make sure you pass the JUnit
-test. </p>
+<div class="instruction"> <strong>Sample Exercise</strong>: The
+main point of this exercise is to make sure your configuration
+works. Type in the answer below into your answer file, make sure
+you get the desired compile-time error, remove the offending
+line, and make sure you pass the JUnit test. </div>
<p> <strong>Task:</strong> Signal an error for calls to
<code>System.out.println</code>.
<p> The way that we are all taught to print "hello world" from Java is
to use <code>System.out.println()</code>, so that is what we typically
use for one-off debugging traces. It's a common mistake to leave
-these in your system longer than is necessary. Type in the aspect
-below to force an error at compile time if this mistake is made.
+these in your system far longer than is necessary. Type in the aspect
+below to signal an error at compile time if this mistake is made.
</p>
+<p> <strong>Answer:</strong>
+</p>
+
+<pre>
+package answers;
+
+import figures.*;
+
+aspect Answer1a {
+ declare error
+ : get(java.io.PrintStream System.out) && within(figures..*)
+ : "illegal access to System.out";
+}
+</pre>
+
<p> When you use this on the given system, you'll find one incorrect
trace in <code>SlothfulPoint</code>.
</p>
-<blockquote><PRE>
+<pre>
$ ajc -argfile base.lst
./figures/SlothfulPoint.java:38 illegal access to System.out
1 error
-</PRE></blockquote>
+</pre>
-<p> Remove the illegal tracing call.
-</p>
+<p> Note that this answer does not say that the <em>call</em> to the
+<code>println()</code> method is incorrect, rather, that the field get
+of the <code>out</code> field is illegal. This will also catch those
+users who bind System.out to a static field to save typing. </p>
+
+<p> After you have successfully used this aspect, edit your
+program to remove the illegal tracing call. </p>
<p> Make sure your program still passes the JUnit test
<code>tests.Test</code> (which it should also pass at the beginning of
all exercises) before continuing. </p>
-<blockquote><PRE>
+<pre>
$ java tests.Test
....
Time: 0.03
OK (4 tests)
-</PRE></blockquote>
-
-<p> <strong>Answer:</strong>
-</p>
-
-<blockquote><PRE>
-package answers;
-
-import figures.*;
-
-aspect Answer1a {
- declare error
- : get(java.io.PrintStream System.out) && within(figures..*)
- : "illegal access to System.out";
-}
-</PRE></blockquote>
-
-<p> Note that this answer does not say that the <em>call</em> to the
-<code>println()</code> method is incorrect, rather, that the field get
-of the <code>out</code> field is illegal. This will also catch those
-users who bind System.out to a static field to save typing. </p>
-
-<br style="page-break-after: always" />
+</pre>
-<h3>b. Mandate setters</h3>
+<h3 class="newpage">1.b. Mandate setters</h3>
<p> <strong>Task:</strong> Signal a warning for assignments outside
of setter methods. </p>
<p> <strong>Tools:</strong> <code>set</code>, <code>withincode</code>,
-signature <code>void set*(..)</code>
+the <code>void set*(..)</code> pattern
</p>
-<p> One common coding convention is that no private field should be
-set outside of setter methods. Write an aspect to warn at compile
-time when such an illegal assignment expression exists. </p>
+<p> One common coding convention is that no private field should
+be assigned to outside of setter methods. Write an aspect to
+signal a warning at compile time for these illegal assignment
+expressions. </p>
<p> This is going to look like
</p>
the assignment is outside the <em>text</em> of the setter.
<p> Make sure your program still passes the JUnit test
-<code>tests.Test</code> before continuing. Make sure you get 11
+<code>tests.Test</code> before continuing. Make sure you get eleven
warnings from this. Wait to fix them until the next exercise. </p>
-<h3>c. Refine setters mandate</h3>
+<h3>1.c. Refine setters mandate</h3>
<p> <strong>Task:</strong> Allow assignmnents inside of constructors.
</p>
-<p> <strong>Tools:</strong> signature <code>new(..)</code> </p>
+<p> <strong>Tools:</strong> the <code>new(..)</code> pattern</p>
<p> Look at some of the warnings from the previous exercise. Notice
that a lot of them are from within constructors. Actually, the common
-coding convention is that no private field should be set outside of
+coding convention is that no private field should be assigned to outside of
setter methods <em>or constructors</em>. Modify your answer to signal
an actual error at compile time (rather than just a warning) when such
an illegal assignment expression exists. </p>
the convention is violated twice in the figures package. You should see
the following two errors:</p>
-<PRE>
+<pre>
.\figures\Point.java:37 bad field set
.\figures\Point.java:38 bad field set
2 errors
-</PRE>
+</pre>
<p>Rewrite these two occurrences so as not to violate
the convention. Make sure your program still passes the JUnit test
<code>tests.Test</code> before continuing. </p>
-<h3>d. Congratulations</h3>
-
-<p> You've taken your first steps. At this point, check the people to
-your left and right. If they're stuck somewhere, see if you can help
-them. </p>
+<div class="instruction"> Congratulations, you've taken your
+first steps. At this point, check the people to your left and
+right. If they're stuck somewhere, see if you can help them.
+Try to resist moving on to the next section until we discuss
+solutions as a group. </div>
<!-- ============================== -->
-<br style="page-break-after: always" />
-<h2>2. Dynamic invariants</h2>
+<h2 class="newpage">2. Dynamic invariants</h2>
<p> The next step in AspectJ adoption is often to augment a test suite
by including additional dynamic tests.
</p>
-<p> Tutorial attendees typically progress at different speeds through
-these questions. Throughout this tutorial, if you finish early, see
-what the people around you are doing and if they need help. Feel free
-to help them out of naked self-interest; we promise you'll learn a lot
-about AspectJ by explaining it. </p>
+<div class="instruction"> Tutorial attendees typically progress
+at different speeds through these exercises. Throughout this
+tutorial, if you finish early, see what the people around you are
+doing and if they need help. Don't help them out of charity,
+help them out of naked self-interest—we promise you'll learn a
+lot about using AspectJ by explaining it. </div>
-<h3>a. Check a simple precondition</h3>
+<h3>2.a. Check a simple precondition</h3>
-<p> <strong>Sample Exercise</strong>: We've provided the answer to
-this exercise below to get you started. </p>
+<div class="instruction"> <strong>Sample Exercise</strong>: We've
+provided the answer to this exercise to get you started. Feel
+free to think a bit, but don't get stuck on this one. </div>
<p> <strong>Task:</strong> Pass <code>tests.Test2a</code>.
</p>
aspect,
</p>
-<blockquote><PRE>
+<pre>
$ java tests.Test2a
.F..F....
Time: 0.04
FAILURES!!!
Tests run: 7, Failures: 2, Errors: 0
-</PRE></blockquote>
+</pre>
<p> But after compiling in the aspect...
</p>
-<blockquote><PRE>
+<pre>
$ ajc -argfile base.lst answers/Answer.java
$ java tests.Test2a
Time: 0.04
OK (7 tests)
-</PRE></blockquote>
+</pre>
<p> <strong>Answer:</strong>
</p>
-<blockquote><PRE>
+<pre>
package answers;
import figures.*;
}
}
}
-</PRE></blockquote>
+</pre>
-<h3>b. Check another precondition</h3>
+<h3>2.b. Check another precondition</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test2b</code>. </p>
<p> Look at <code>tests/Test2b.java</code> to see exactly what we're
testing for. </p>
-<h3>c. Check yet another precondition</h3>
+<h3>2.c. Check yet another precondition</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test2c</code>. </p>
call.
</p>
-<h3>d. Assure input</h3>
+<h3>2.d. Assure input</h3>
<p> <strong>Task: </strong> Pass <code>tests.Test2d</code>.
</p>
}
</pre>
-<br style="page-break-after: always" />
-<h3>e. Check a postcondition</h3>
+<h3 class="newpage">2.e. Check a postcondition</h3>
<p> <strong>Task: </strong> Pass <code>tests.Test2e</code>
</p>
during move, we need some way of getting access to the coordinates
both before <em>and</em> after the move, in one piece of advice. </p>
-<h3>f. Check another postcondition</h3>
+<h3>2.f. Check another postcondition</h3>
<p> <strong>Task: </strong> Pass <code>tests.Test2f</code>
</p>
<!-- ============================== -->
-<br style="page-break-after: always" />
-<h2>3. Tracing</h2>
+<h2 class="newpage">3. Tracing</h2>
<p> Tracing is one of the classic AspectJ applications, and is often
the first where AspectJ is used on deployed code.
</p>
-<h3>a. Simple logging</h3>
+<h3>3.a. Simple logging</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test3a</code>.</p>
<code>Log</code> (with an import from <code>support.Log</code>)
and call <code>Log.log(String)</code></p>
-<h3>b. Exposing a value</h3>
+<h3>3.b. Exposing a value</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test3b</code>.</p>
but also the target object, with the form
</p>
-<blockquote><pre>
+<pre>
<em>thisJoinPointInfo</em> at <em>targetObject</em>
-</pre></blockquote>
+</pre>
-<h3>c. More specialized logging</h3>
+<h3>3.c. More specialized logging</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test3c</code>.</p>
group. The <code>args</code> pointcut allows you to select join points
based on the type of a parameter to a method call. </p>
-<p> Look at the test case for details about the tested log message.
+<p> Look at the test case for details about the required log message.
</p>
-<h3>d. Logging extended to checking an invariant</h3>
+<h3 class="newpage">3.d. Logging extended to checking an invariant</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test3d</code>.</p>
To do so, associate a boolean flag with each Point using an inter-type
declaration, such as </p>
-<blockquote><pre>
+<pre>
boolean Point.hasBeenAdded = false;
-</pre></blockquote>
+</pre>
<p> Check and set this flag with the same kind of advice from your
answer to problem (c). Throw an <code>IllegalStateException</code> if
the point has already been added.
</p>
-<h3>e. Better error messages for 3d</h3>
+<h3>3.e. Better error messages for 3.d.</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test3e</code>.</p>
-<p> <strong>Tools:</strong>
-</p>
-
<p> Extend your solution to problem (d) by using the string
representation of the Point's containing group as the <code>msg</code>
part of the <code>IllegalStateException</code>. </p>
<!-- ============================== -->
-<br style="page-break-after: always" />
-<h2>4. Caching</h2>
+<h2 class="newpage">4. Caching</h2>
<p> Computation of the bounding box of <code>Group</code> objects
needs to deal with all aggregate parts of the group, and this
computation can be expensive. In this section, we will explore
various ways of reducing this expense. </p>
-<p> <strong>Optional</strong>: In all of these exercises, you should
-only deal with points that are added directly to Groups, rather than
-those that are added "indirectly" through Lines and Boxes. You should
-handle those points contained in Lines and Boxes only if time permits.
-</p>
+<div class="instruction"> <strong>Optional</strong>: In all of
+these exercises, you should only deal with points that are added
+directly to Groups, rather than those that are added "indirectly"
+through Lines and Boxes. You should handle those points
+contained in Lines and Boxes only if time permits. </div>
-<h3>a. Make a constant override</h3>
+<h3>4.a. Make a constant override</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test4a</code>.</p>
around advice intercepting the method.
</p>
-<h3>b. Make a constant cache</h3>
+<h3>4.b. Make a constant cache</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test4b</code>.
</p>
state for every <code>Group</code> object.</em> </p>
-<h3>c. Invalidate, part 1</h3>
+<h3>4.c. Invalidate, part 1</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test4c</code>.
</p>
<code>move()</code> method of <code>Group</code> is called.
</p>
-<br style="page-break-after: always" />
-<h3>d. Invalidate, part 2</h3>
+<h3 class="newpage">4.d. Invalidate, part 2</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test4d</code>.</p>
slightly different than the problem in 3c: Here you care about fields,
where there you cared about method calls. </p>
-<h3>e. Invalidate, part 3</h3>
+<h3>4.e. Invalidate, part 3</h3>
<p> <strong>Task:</strong> Pass <code>tests.Test4e</code>.</p>
trap: Remember that whenever a point moves it should invalidate the
caches of <em>all</em> enclosing groups. </p>
-<hr>
+<div class="instruction">
+
+<p> Congratulations! Not only have you learned about how to
+program in AspectJ, you have worked through exercises paralleling
+a common AspectJ adoption strategy. You should be able to
+pick up AspectJ and use it to improve your own software's
+crosscutting modularity. </p>
+
+<p> You can find the current binaries, source, documentation and
+an active user community for AspectJ at</p>
+
+ <blockquote>
+ http://www.eclipse.org/aspectj
+ </blockquote>
+
+</div>
+
+<img style="newpage" src="figures_classes.gif" height="900" alt="" />
+
</body> </html>