| Andrew Cooke | Contents | Latest | RSS | Twitter | Previous | Next


Welcome to my blog, which was once a mailing list of the same name and is still generated by mail. Please reply via the "comment" links.

Always interested in offers/projects/new ideas. Eclectic experience in fields like: numerical computing; Python web; Java enterprise; functional languages; GPGPU; SQL databases; etc. Based in Santiago, Chile; telecommute worldwide. CV; email.

Personal Projects

Lepl parser for Python.

Colorless Green.

Photography around Santiago.

SVG experiment.

Professional Portfolio

Calibration of seismometers.

Data access via web services.

Cache rewrite.

Extending OpenSSH.

C-ORM: docs, API.

Last 100 entries

Small Success With Go!; Re: Quick message - This link is broken; Adding Reverb To The Echo Chamber; Sox Audio Tools; Would This Have Been OK?; Honesty only important economically before institutions develop; Stegangraphy via PS4; OpenCL Mess; More Book Recommendations; Good Explanation of Difference Between Majority + Minority; Musical Chairs - Who's The Privileged White Guy; I can see straight men watching this conversation and laffing; When it's Actually a Source of Indignation and Disgust; Meta Thread Defending POC Causes POC To Close Account; Indigenous People Of Chile; Curry Recipe; Interesting Link On Marginality; A Nuclear Launch Ordered, 1962; More Book Recs (Better Person); It's Nuanced, And I Tried, So Back Off; Marx; The Negative Of Positive; Jenny Holzer Rocks; Huge Article on Cultural Evolution and More; "Ignoring language theory"; Negative Finger Counting; Week 12; Communication Via Telecomm Bids; Finding Suspects Via Relatives' DNA From Non-Crime Databases; Statistics and Information Theory; Ice OK in USA; On The Other Hand; (Current Understanding Of) Chilean Taxes / Contributions; M John Harrison; Playing Games on a Cloud GPU; China Gamifies Real Life; Can't Help Thinking It's Thoughtcrime; Mefi Quotes; Spray Painting Bike Frame; Weeks 10 + 11; Change: No Longer Possible To Merge Metadata; Books on Old Age; Health Tree Maps; MRA - Men's Rights Activists; Writing Good C++14; Risk Assessment - Fukushima; The Future of Advertising and Surveillance; Travelling With Betaferon; I think I know what I dislike so much about Metafilter; Weeks 8 + 9; More; Pastamore - Bad Italian in Vitacura; History Books; Iraq + The (UK) Governing Elite; Answering Some Hard Questions; Pinochet: The Dictator's Shadow; An Outsider's Guide To Julia Packages; Nobody gives a shit; Lepton Decay Irregularity; An Easier Way; Julia's BinDeps (aka How To Install Cairo); Good Example Of Good Police Work (And Anonymity Being Hard); Best Santiago Burgers; Also; Michael Emmerich (Vibrator Translator) Interview (Japanese Books); Clarice Lispector (Brazillian Writer); Books On Evolution; Looks like Ara (Modular Phone) is dead; Index - Translations From Chile; More Emotion in Chilean Wines; Week 7; Aeon Magazine (Science-ish); QM, Deutsch, Constructor Theory; Interesting Talk Transcripts; Interesting Suggestion Of Election Fraud; "Hard" Books; Articles or Papers on depolarizing the US; Textbook for "QM as complex probabilities"; SFO Get Libor Trader (14 years); Why Are There Still So Many Jobs?; Navier Stokes Incomplete; More on Benford; FBI Claimed Vandalism; Architectural Tessellation; Also: Go, Blake's 7; Delusions of Gender (book); Crypto AG DID work with NSA / GCHQ; UNUMS (Universal Number Format); MOOCs (Massive Open Online Courses); Interesting Looking Game; Euler's Theorem for Polynomials; Weeks 3-6; Reddit Comment; Differential Cryptanalysis For Dummies; Japanese Graphic Design; Books To Be Re-Read; And Today I Learned Bugs Need Clear Examples; Factoring a 67 bit prime in your head; Islamic Geometric Art; Useful Julia Backtraces from Tasks; Nothing, however, is lost with less discomfort than that which, when lost, cannot be missed

© 2006-2015 Andrew Cooke (site) / post authors (content).

Static Mixins at the Presentation Layer with AspectJ and JSP

From: "andrew cooke" <andrew@...>

Date: Fri, 2 Dec 2005 09:38:27 -0300 (CLST)

A quick note on an interesting pattern I stumbled across yesterday.
It's very obvious in retrospect, but I think it's also an interesting
illustration of AspectJ in use, showing both its good and bad

Background, Database Layer

I have some information in my database that I want to display in the
user's browser (don't we all?).  These are three integers - labelled
red, yellow and green - that "score" someone's performance (green is
good, red bad and yellow intermediate).

So I have a transport object - a bean - that is a transparent carrier
of this information (and other related values).  The database layer
supports reading and writing instances of this object.

This transport bean is very simple - a collection of private fields
with public setters/getters (largely auto-generated by Eclipse) that
provide dynamic access to the fields via introspection (what a bean
is, really).

Presentation Layer

At the presentation layer (inside a JSP tag) I decided to display the
information as an LED bar display (like you see on cheesy hi-fi).
However, the numeric values of these scores can be large, so I decided
to make the number of bars proportional to the log of the value (more
exactly; 1 + log2(n)).

Within the tag I would like to access these logarithmic values using
JSP's expression language.  So my tag code looks something like:

<c:if test="${value.red > 0}">
  <c:forEach begin="1" end="${value.logRed}">
    <img src="<c:url value="/themes/red.png"/>" alt="-" title="bad" />

To do this, I need a getLogRed() getter on my object.  But my
transport bean only has a getRed() method.


Enter AspectJ.  In the part of my source tree related to presentation
I define an AspectJ mixin that adds the lgoarithm calculations.  This
is done in three steps.

First, I define an interface that provides the new functionality (I'll
only include red here, but in practice all three colours are present):

public interface LogColour {
  public int getLogRed();

Second, I add that interface to the transport bean, along with a dummy

public aspect LogColourMixin {

  declare parents : TransportBean
  implements LogColour;

  public int LogColour.getLogRed() {return -999;}


Third, I define a "pointcut" that identifies when this method is
called, and an "advice" that does the appropriate calculation (this
goes inside LogColourMixing defined above; Tk is a static toolkit):

  pointcut beanRed(TransportBean bean):
    call(public int LogColour.getLogRed()) && target(bean);

  int around(TransportBean bean): beanRed(bean) {
    return Tk.log2(bean.getRed());

Note here that the pointcut and advice are both parameterised with a
TransportBean instance.  This gives us access to the bean inside the
advice so that we can call the getRed() method.

Coding Style

The use of mixins here is completely gratuitous.  I could equally well
have added the getLogRed() method directly to the transport bean.  Or
I could have used some kind of facade.

However, this approach helps separate the different concerns.  The
presentation mixin lives with my presentation source and is not
referred to by the transport, database or business logic layers.  As
it happens, the database layer also uses a mixin to add a table key to
the object; that doesn't appear in the transport, business or
presentation code.

It Doesn't Work

While the code above does work in my test case, the tag failed!
Inside the tag, the getLogRed() method is returning -999.  The advice
is not being applied.

This is due to an implementation detail of AspectJ.  The addition of
the interface is achieved by modifying the class file - it is a static
change.  The pointcut and advice, however, are dynamic; they are
implemented by inserting tests in *calling* code.

The dynamic interception works fine in my tests because I am using
AspectJ-aware Eclipse.  But the tag files are compiled in the server
(Tomcat), which knows nothing about AspectJ and so doesn't add the
appropriate indirection.

(One solution to this is to pre-compile the tags using AspectJ).

Ugly -999

And that dummy method implementation is ugly!  Here it is again:

  public int LogColour.getLogRed() {return -999;}

Why can't that be:

  public int LogColour.getLogRed() {
    return Tk.log2(getRed());

Because getRed is part of the parent!  I cannot find a way to acccess
the parent class statically from within the method.  The above, and
this.getRed() both give compilation errors.

Overlapping Interface Pattern

A better solution struck me on the way home from work today.  This
makes the mixing completely static and removes the ugly dummy method:

public interface LogColour {
  public int getRed();
  public int getLogRed();

public aspect LogColourMixin {
  declare parents : TransportBean
  implements LogColour;

  public int LogColour.getLogRed() {
    return Tk.log2(getRed());

(I did say it was obvious in retrospect...)  All I have done is
include the getRed() method in the mixin interface.  This already
exists in TransportBean, so I don't need to re-implement it, but by
adding it to the mixin I can now call it from within the getLogRed()

This works fine when called from code compiled in the server because
the changes are all confied to static modifications in the called
code; the calling code does not need any dynamic interceptions.

So by following this pattern I have a simple mixin: easier to
understand; more efficient; and works when called from Aspectj-unaware


`__ _ __ ___  ___| |_____   personal web site: http://www.acooke.org
/ _` / _/ _ \/ _ \ / / -_)  list: http://www.acooke.org/cute
\__,_\__\___/\___/_\_\___|  aim: acookeorg; skype: andrew-cooke

compute mailing list

Comment on this post