-=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- (c) WidthPadding Industries 1987 0|255|0 -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=-
SoCoder -> Blogs Home -> Blogs


 
JL235
Created : 13 April 2008
Edited : 13 April 2008

Aspect-Oriented Programming



Consider the following...

I have a GUI, which when working should look like

However it actually looks like

Something is wrong, it is broken. First I'm going to presume this is the GUI part to blame. So I want to find out what options are being set on the window, which is created using a JFrame.

Before I continue, for those who don't know:
  • in Java you typically use methods that start with 'set' in order to set values in a class. setLocation, setSize, setMenuBar, setEtc.
  • You can also make GUI's in Java using Swing, a framework for making applications. It's classes include JFrame for a window frame, JButton for buttons, JLabel for a text label, JList for a list and so on.
  • The Swing libraries are contained in the package javax.swing in the Java API.

So I want to know as the program is running, which of these set methods are being called and what their parameters are. Lets look at the API:

Highlighted are the set methods for JFrame, 11 methods in total. However it also has a further 41 set methods inherited from it's superclasses. So I want to watch in total, 52 methods!

How could I easily do this?

Inheritence

I could just make a subclass of JFrame and override all 52 methods with my own. They will print out the method name and it's parameters and then call the correct set method in it's super class. This example overrides just 3 of the set methods:

This works, however there are a few problems:
  • First each method needs to be indevidually written.
  • If each method is approximately 6 lines, then that is 312 lines of code for the class
  • What if the JFrame API changes? Then my code is wrong.
  • What if I miss or mislabel a method or parameter? With 52 methods, that's highly likely
  • How do I watch other components too? JLabel, JButton, Jtext area. I'll need to write indevidual watching subclasses for them too (another 300 lines each?).
  • Need to change the original project to use my watching classes instead of the JFrame
  • Need to the project back when I go to release the application

A better solution is needed.

AspectJ

AspectJ is an aspect-oriented language extension to Java that I have been looking at recently. It allows you to add aspects (bits of code) to be run before, during or after a point-cut (a method call, loop, throwing an exception, object initialisation, etc).

Using AspectJ I can add my own aspect that will cut in just before the methods I've selected are called. In this case the methods are any that begin with set in the javax.swing.JFrame class. So here is the aspect oriented way of doing this:

These 13 lines will do exactly the same and works on all 52 set methods in JFrame, including those in it's super classes. It also ensures that all set methods are caught. So how is this solution better? Everything that was bad about the last solution is fixed by this one.

It works by first placing a pointcut on all set methods in the JFrame class (which includes it's superclass). When that pointcut is reached (like if I called frame.setLocation) then it will call the 'capture()' method below. This then just prints out the current name and arguments of the current method being called.

The typical output for the aspect could be:

One thing you might notice is that these are being called from firerename.Main and not javax.swing.JFrame. That is because the Main class is overriding the JFrame class, and so when it calls a method of the JFrame it is also recorded. Something else that the inheritence option does not do.

How would I extend this to include all Swing components? (Like JTabbedPane, JButton, JLabel, JEtc).
Easy, just change the line:

to

For example the output might be now:


This will now tie into all the set methods of any class in javax.swing that starts with a J.

Conclusion

That's quite a powerful ability for only 13 lines of code. I really like the look of AspectJ, the idea of being able to automatically tie into a large variety of methods. It's designed to allow the user to easily design and build modules which extends across multiple classes, like the logging system I built above. The main advantage being that it drastically reduces code reuse and all the logging code is now placed together in one place, in one file.

 

Comments


Monday, 14 April 2008, 14:49
mike_g
I guess it could be useful, but so far I have not experienced a situation where I would need something like this.
Tuesday, 15 April 2008, 15:17
Yo! Wazzup?
I haven't read the whole thing, and this is kind of off topic

but I cant get the grid thing to work in swing...

I ask for a 3X3 grid and it gives a 3X2 grid?
Tuesday, 15 April 2008, 15:54
codingmonkey
looks very powerful, indeed.

and Java?
Tuesday, 15 April 2008, 15:59
JL235
YO: What grid?

CodingMonkey: and Java?, and?
Tuesday, 15 April 2008, 16:27
mike_g
but I cant get the grid thing to work in swing...
I ask for a 3X3 grid and it gives a 3X2 grid?

I guess youre talking about some other program you wrote and I guess would that you are talking about the grid layout? To display it correctly (3*3) you and you would need to add 9 components to the container. If you want blank spaces in your grid you could just add an empty JPanel to pad it out. Might not be the best way, but its worked for me.
Tuesday, 15 April 2008, 16:40
codingmonkey
"AspectJ is an aspect-oriented language extension to Java that I have been looking at recently"

very powerful and nice GUI
and in the utilization of Java, with AspectJ.
Wednesday, 16 April 2008, 06:19
Yo! Wazzup?
This is what I did;
I made a grid layout that should be 3X3.
Then I added 4 blank components to it to space it out.
Then I added a button that I wanted centered.
It gives me a 3 down, 2 across grid with 4 blank spaces then a button o.O
Wednesday, 16 April 2008, 07:22
mike_g
Well like I said, just add another 4 empty components to the grid and it should display correctly. Tbh I don't think using a grid layout is the best way to be going about this, but lets not hijack this topic If you still have problems getting your layout right just post your code in another thread, and one of us here should be able to help.
Wednesday, 16 April 2008, 08:47
JL235
I concurr, on both points. I'd personally use a BorderLayout with the button in the centre, although I only use the BorderLayout. I'm sure there are also options for centreing components in say a FlowLayout.
Wednesday, 16 April 2008, 14:58
Yo! Wazzup?
My basic point is not that "there are other ways to do it", because I know there are. My point is that what if one time we actually need the gridlayout thing?

Sorry for hijacking BTW
Wednesday, 16 April 2008, 15:51
JL235
Then use it. It does work, just not the way your expecting. You need to remember that your GUI will be packed down. You do actually have a 3x3 grid, it's just that because the bottom sections were empty then their size is packed down to be as small as possible and so contain nothing. Put something in them and they are not empty.

Plus in this example I don't think it's so much that there are other ways to do it, but that there are better ways to do it.
Thursday, 17 April 2008, 14:01
Yo! Wazzup?
Got it