| 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

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; Article on Didion; Cost of Living by City; British Slavery; Derrida on Metaphor; African SciFi; Traits in Julia; Alternative Japanese Lit; Pulic Key as Address (Snow); Why Information Grows; The Blindness Of The Chilean Elite; Some Victoriagate Links; This Is Why I Left StackOverflow; New TLS Implementation; Maths for Physicists; How I Am 8; 1000 Word Philosophy; Cyberpunk Reading List; Detailed Discussion of Message Dispatch in ParserCombinator Library for Julia; FizzBuzz in Julia w Dependent Types; kokko - Design Shop in Osaka; Summary of Greece, Currently; LLVM and GPUs; See Also; Schoolgirl Groyps (Maths); Japanese Lit; Another Example - Modular Arithmetic; Music from United; Python 2 and 3 compatible alternative.; Read Agatha Christie for the Plot; A Constructive Look at TempleOS; Music Thread w Many Recommendations; Fixed Version; A Useful Julia Macro To Define Equality And Hash; k3b cdrom access, OpenSuse 13.1; Week 2; From outside, the UK looks less than stellar; Huge Fonts in VirtualBox; Keen - Complex Emergencies; The Fallen of World War II; Some Spanish Fiction; Calling C From Fortran 95; Bjork DJ Set; Z3 Example With Python; Week 1; Useful Guide To Starting With IJulia; UK Election + Media; Review: Reinventing Organizations; Inline Assembly With Julia / LLVM; Against the definition of types; Dumb Crypto Paper; The Search For Quasi-Periodicity...; Is There An Alternative To Processing?; CARDIAC (CARDboard Illustrative Aid to Computation); The Bolivian Case Against Chile At The Hague; Clear, Cogent Economic Arguments For Immigration; A Program To Say If I Am Working; Decent Cards For Ill People; New Photo; Luksic And Barrick Gold; President Bachelet's Speech; Baltimore Primer; libxml2 Parsing Stream; configure.ac Recipe For Library Path; The Davalos Affair For Idiots; 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?

© 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