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

C[omp]ute

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

Not The Onion: Google Fireside Chat w Kissinger; Bicycle Wheels, Inertia, and Energy; Another Tax Fraud; Google's Borg; A Verion That Redirects To Local HTTP Server; Spanish Accents For Idiots; Aluminium Cans; Advice on Spray Painting; Female View of Online Chat From a Male; UX Reading List; S4 Subgroups - Geometric Interpretation; Fucking Email; The SQM Affair For Idiots; Using Kolmogorov Complexity; Oblique Strategies in bash; Curses Tools; Markov Chain Monte Carlo Without all the Bullshit; Email Para Matias Godoy Mercado; The Penta Affair For Idiots; Example Code To Create numpy Array in C; Good Article on Bias in Graphic Design (NYTimes); Do You Backup github?; Data Mining Books; SimpleDateFormat should be synchronized; British Words; Chinese Govt Intercepts External Web To DDOS github; Numbering Permutations; Teenage Engineering - Low Price Synths; GCHQ Can Do Whatever It Wants; Dublinesque; A Cryptographic SAT Solver; Security Challenges; Word Lists for Crosswords; 3D Printing and Speaker Design; Searchable Snowden Archive; XCode Backdoored; Derived Apps Have Malware (CIA); Rowhammer - Hacking Software Via Hardware (DRAM) Bugs; Immutable SQL Database (Kinda); Tor GPS Tracker; That PyCon Dongle Mess...; ASCII Fluid Dynamics; Brandalism; Table of Shifter, Cassette and Derailleur Compatability; Lenovo Demonstrates How Bad HTTPS Is; Telegraph Owned by HSBC; Smaptop - Sunrise (Music); Equation Group (NSA); UK Torture in NI; And - A Natural Extension To Regexps; This Is The Future Of Religion; The Shazam (Music Matching) Algorithm; Tributes To Lesbian Community From AIDS Survivors; Nice Rust Summary; List of Good Fiction Books; Constructing JSON From Postgres (Part 2); Constructing JSON From Postgres (Part 1); Postgres in Docker; Why Poor Places Are More Diverse; Smart Writing on Graceland; Satire in France; Free Speech in France; MTB Cornering - Where Should We Point Our Thrusters?; Secure Secure Shell; Java Generics over Primitives; 2014 (Charlie Brooker); How I am 7; Neural Nets Applied to Go; Programming, Business, Social Contracts; Distributed Systems for Fun and Profit; XML and Scheme; Internet Radio Stations (Curated List); Solid Data About Placebos; Half of Americans Think Climate Change Is a Sign of the Apocalypse; Saturday Surf Sessions With Juvenile Delinquents; Ssh, tty, stdout and stderr; Feathers falling in a vacuum; Santiago 30m Bike Route; Mapa de Ciclovias en Santiago; How Unreliable is UDP?; SE Santiago 20m Bike Route; Cameron's Rap; Configuring libxml with Eclipse; Reducing Combinatorial Complexity With Occam - AI; Sentidos Comunes (Chilean Online Magazine); Hilary Mantel: The Assassination of Margaret Thatcher - August 6th 1983; NSA Interceptng Gmail During Delivery; General IIR Filters; What's happening with Scala?; Interesting (But Largely Illegible) Typeface; Retiring Essentialism; Poorest in UK, Poorest in N Europe; I Want To Be A Redneck!; Reverse Racism; The Lost Art Of Nomography; IBM Data Center (Photo); Interesting Account Of Gamma Hack; The Most Interesting Audiophile In The World; How did the first world war actually end?; Ky - Restaurant Santiago; The Black Dork Lives!; The UN Requires Unaninmous Decisions

© 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
features.


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" />
  </c:forEach>
</c:if>

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

Mixin
-----

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
implementation:

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()
implementation.

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
code.

Andrew


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

_______________________________________________
compute mailing list
compute@...
https://acooke.dyndns.org/mailman/listinfo/compute

Comment on this post