Saturday, November 13, 2010

JavaBean Property Change Listener With Dynamic Proxy Wrapper

Recently, I was working on a project where my software would receive some Java beans, do something with them, pass them around. The trick was that, besides all the usual stuff, the system had to react on bean property changes. For, example if we had a Person object, and its property "name" is changed, framework would have to execute some code, sync some GUI components, etc.

So, I was quite excited when I found PropertyChangeSupport class in Java API specification. However, functionality provided by this class requires changes in bean class code. I would have to modify the Person class, add code for PropertyChangeSupport object, and add a firePropertyChange method call to each setter method in the bean class (or at least for setter methods of those properties my system cared about). This, wouldn't be a big problem if all bean classes were known in advance and their source code preferably available and open for editing, however, in my case, it wasn't so.

After several failed experiments, including but not limited to AspectJ, I found a solution which you can see int this article - Javassist framework for runtime bytcode manipulation. I used it to generate dynamic proxy wrappers around any Java bean with firePropertyChange called in each of the chosen setter methods. Yeah, I know it's heavy thinking already, so let's get to example.

We have a Java class:

And our generated proxy class would look like this:

And here is how to make a proxy object:

The list contains names of all properties to be bound, so that we can let some property changes be ignored. As simple as that! Now, whenever we change any bound property on the returned object, the assigned listener would do its job. Exactly how should listener class look like depends on the particular system. For the purpose of this tutorial, I created a dummy implementation:

And at any time, if we want our original untracked bean we can do this:

Ok, that's how you use it. Now, how it's made. We had several problems here. First was to create a runtime wrapper proxy around a bean object, then to make our object "trackable" by adding PropertyChangeSupport support (no pun intended). From another point of view, we first had to generate a runtime class, then to instaniate it around our original bean.

So, the solution contains WrapperProxyFactory class with a concrete method createWrapperProxy and abstract methods adjustProxyClass and adjustProxyObject. The concrete method handles all the proxy-wrap-and-delegate stuff and leaves the proxy purpose itself to a subclass implementing abstract methods. In this case subclass is named BoundBeanWrapperProxyFactory. Its adjustProxyClass method alters all bound setters to fire event on each call, and adjustProxyObject adds listeners to wrapper objects. We also have interfaces WrapperProxy and BoundBeanWrapperProxy which expose methods which are added to our proxies in runtime, such as retrieveOriginal.

Separation of these factories did complicate things a little, however a proxy that wraps around a bean and does something else may be useful, too. Then all we have to do is write a different factory subclass.

Anyway, you can download code from the link here or digg it out from my hg repository on Google Code. Some code changes (i.e. package names) may be required for use.

Tuesday, September 21, 2010

Developing From Console

In my previous post I promised to explain how I developed an application while (mostly) avoiding bloated development tools, so here it comes...

First, a brief explanation of the app itself: It is a genetic algorithm application implemented in Clojure, whose goal is to solve a mathematical game. Game solver (my program) gets one target number and six more numbers. The goal is to use these six numbers to create an equation which evaluates to the target number. In this article I will focus on development environment, rather than on domain problem or the program itself, so you can see more details about the game and get the source on project page: (In case you got to this blog from there, just continue reading, and see how it was made :))

Ok, I briefly explained the problem which my application solved, now to get to the post title. Yeah, most of the tools I used to develop it are command line based. Well, actually all but two. Unix-like environments offer a great deal of useful command line tools, so it was a piece of cake to find and install all of them, however most are (as far as I know) available on Windows platform as well.

So, let's see those tools:

Editor - Vim, with limited Clojure plugin meaning that I only used syntax colouring feature and rainbow parens, not the nailgun or any other automatic runner. (I also could've used an easier editor like nano, I just like vim more)

Source Versioning - since I hosted my source on Mercurial, the best and simplest client turned out to be default console based Mercurial client hg.

Build Management and Running - Maven2, default console based (I'm sure leiningen is great, and sure will try it out, but I really don't see anything wrong with maven either). Clojure plugin for Maven offers a clojure:repl command, which creates a REPL with all the maven dependencies set up on the classpath without trouble.

Diff tool - Meld (a GUI app!) - simple, lightweight, intuitive, and looks nice... Much easier to work with than default diff, vimdiff and (personal opinion) aesthetically more appealing than kdiff. It also serves the purpose to show that choosing console tools over graphical ones shouldn't be just for geekness sake, but based on their actual usefulness.

Web Browser - Chrome and Firefox, obvious choice for both testing web applications and reading online documentation (also add whatever browser you wish to test against)...

Music Player (C'mon, who doesn't occasionally need music while programming :)) - Moc, Music On Console (the geekest of them all) a command line based music player that does exactly what it says, plays music - no lyrics plugin, no funky visualisations, no music store support - it just plays the damn music... :-)

These tools (and the command line terminal itself) were the only toolset I used while writing the genetic algorithm application, and I wrote it in a remarkably short time. Why is that? First, we shouldn't forget the choice of programming language and platform. Clojure is a modern Lisp, which means that it gives a huge flexibility and the possibility to write great functionality for brief time and in small number of code lines. Second, the tools I chose are all lightweight, they load in a millisecond, store file in the same time, writing a file doesn't cause rebuild... so I just got rid of all these annoying seconds waiting for Eclipse to finish some automatic task, not to mention time needed to setup all the plugins. There were many times when I had more trouble integrating a tool with Eclipse, than setting up the tool itself, i.e. trying to use a Google Web Toolkit, with both Maven GWT plugin and Eclipse GWT plugin. So, my solution is quite simple - use editor for editing. Period. Use build tool for building, version tool for versioning, etc... "Write (or in my case: Use) programs that do one thing and do it well" This principle isn't anything new, it's been known as a key part of the Unix philosophy, so it isn't really a surprise that most development tools that satisfy it come from Unix world.

Also, as I mentioned in my previous post, there is a tendency in IDE design to encompass the functionality of system's window manager within IDE window, so basically we have to switch between working on different files, REPL, web browser etc. both within IDE and within system window manager. With toolkit I used, only switching I had to do was between terminal windows and a browser. Even the meld tool would pop out and launch from console, and then after seeing diff and merging changes I would simply close it.

Of course, there are drawbacks to this aproach. Some technologies, especially proprietary ones or those that have enterprisey approach (or both!), simply demand some specific enviroment. But, whenever I have the luxury of choosing what to work with it will be whatever is comfortable and makes me most productive.

Thursday, September 16, 2010

Are IDEs bloated by design?

By IDE, i obviously mean, Integrated Development Environment. A tool every programmer out there knows of, and most of us use it. But first, before I start with the topic I just want to make one thing clean - I am not starting another flame war about which IDE is less bloated or more powerful or whatever. The point I am trying to make is that all Integrated Development Environments are inevitabely bloated at some time in their lifecycle, pricipally because of the 'Integrated' part.

Ok, it really helps to have some basic functionalities needed for programming in one place, but the definition of 'some basic' may vary for different people and sometimes for different projects. The core functionalities include code editing (with color coding, folding and other fanciness), automatic compiling in background or at least easy compiling with a single click, and easy running of the written program. Also, core functionality may include linking with libraries, debugging and accessing library documentation.

But then, when we program we don't just write code, run and debug countinuosly. We also use source versioning systems, build managers, testing tools and frameworks. So, IDEs then get features (usually as plugins) for all these functionalities.

And that is not all, many projects contain files with different syntaxes or in different programming languages, i.e. a Java based web application may contain java files, jsp, properties, javascript, css, and plenty of xml. So, our IDE of choice gets support for all these as well.

And at some point, when we finish working on that project and start another one using a different technology stack, we can either reinstall IDE and repeat process of setting up all the plugins, this time for another set of technologies or we can add new plugin to the existing environment setup. So, now our IDE contains support for newest buzzword-compliant soa based web services, ages old database system and an obscure scripting language with support for closures and duck typing.

Ok, I admit that using buzzword software as an example is a bit of a cheating, because it is not really that hard to convince programmers against leveraging state of art game changer software, but you do get my point of where is existing trend leading us.

Next thing, we have embedded web browser in an IDE, so that you can test your webpages without opening a browser, and a system console within a IDE console, which... well, sends commands to the real shell console, and displays output back in IDE... Some people are apparently trying to create an Uber Development Environment, where programmers would never have to minimize The Editor when programming.

It reminds me a bit of those huge fancy hotels where you are being encouraged to spend your entire vacation within hotel compound, swim in the hotel pool, eat only in hotel restaurant, buy souvenirs in specialized gift shops with mass-produced hand-made local products. Well, I'm simply not that kind of a guy. Seriously, I'm always much more in the mood of going to a beach of my choice, eating wherever I want etc. Ok, I'm offtopic in my own topic! :) My main concern was the efficiency and (effective) ease of use, not the matter of convenience vs. choice. But I couldn't help it, I really dislike these hotels :)

Back to the topic.. There already is an article on thedailywtf, describing a phenomenon which I believe is the main factor that causes bloated IDEs in the first place. They called it The Inner-Platform Effect and the key part of the definition is "a result of designing a system to be so customizable that it ends becoming a poor replica of the platform it was designed with". This effect may occur in literally any application that offers support for plugins or similar extensions. Of course, IDE without plugins may become bloated too, but then all the bloating would have to be done by the IDE developers themselves, rather than "general public".

Anyone correct me if I'm wrong, but it does seem to me that the main IDE window is becoming a replacement for our system's window manager. It contains many tabs or small windows and other widgets for organizing code and other stuff in project. Switching tabs between windows/tabs in Eclipse, Visual Studio, NetBeans, etc.. is the new Alt-Tabbing. I'm just not sure what was wrong with the first one. And that is least of the problems bloatware creates us. For example, any modern editor with all the plugins takes a lifetime to load, occasionally may hang while doing some validation of html versus the w3c standards it wasn't even asked to and other whatnots..

Ok, but so far I just ranted against bloated IDEs, and didn't offer any solution to the problem. As the matter of fact, many of you probably don't even see a problem there. If so, I'm happy for you, folks :) Also, it's possible that you do see the same problem, but may see my solution as afflicted with even worse problems.

Anyway, if you visit my blog again, see my next post where I will explain how I used a really simple and quite low tech programming environment to develop a cool app.

Clockwork Fig is unleashed!

I proudly present my personal blog, where I will post about various different things which I find interesting, from programming stuff, tutorials, my personal project, to all other things that are interesting enough to be written about.

I hope you will enjoy reading my posts (or at least find them useful :))