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.

21 comments:

  1. Looks nice and simple but this names (BoundBeanWrapperProxyFactory,..) can be intimidating..

    ReplyDelete
  2. This is good and thank you for sharing the information about the Java class. i would like to be a part of it. The java code you have shared it useful.

    ReplyDelete
  3. Thanks for the post, I am techno savvy. I believe you hit the nail right on the head. I am highly impressed with your blog. It is very nicely explained. Your article adds best knowledge to our Java EE Training in Chennai. or learn thru Java EE Training in Chennai Students.

    ReplyDelete
  4. Excellent post!!!. The strategy you have posted on this technology helped me to get into the next level and had lot of information in it.
    Best Devops online Training
    Online DevOps Certification Course - Gangboard
    Best Devops Training institute in Chennai

    ReplyDelete
  5. Thanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information. 
    python Training in Chennai
    python Training in Bangalore
    python Training in Pune

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Thanks for sharing this blog. This very important and informative blog.Tableau Training in Bangalore

    ReplyDelete
  8. Thank you so much for the great and very beneficial stuff that you have shared with the world.

    Become an Expert In Python Training in Bangalore ! The most trusted and trending Programming Language. Learn from experienced Trainers and get the knowledge to crack a coding interview, @Softgen Infotech Located in BTM Layout.

    ReplyDelete
  9. Good Post! it was so good to read and useful to improve my knowledge as an updated one, keep blogging. After seeing your article I want to say that also a well-written article with some very good information which is very useful for the readers....thanks for sharing it and do share more posts like this.
    Data Science Online Training

    ReplyDelete
  10. Good Post! it was so good to read and useful to improve my knowledge as an updated one, keep blogging. After seeing your article, I want to say that also a well-written article with some very good information which is very useful for the AWS Cloud Practitioner Online Training

    ReplyDelete
  11. That’s wonderful. many things to learn. thanks for sharing. this is very informative and interesting for those who are interested in blogging field.

    Java Training in Chennai

    Java Course in Chennai

    ReplyDelete
  12. Great post. keep sharing such a worthy information.
    Appium Training Online

    ReplyDelete