Showing posts with label Software Development. Show all posts
Showing posts with label Software Development. Show all posts

15 December, 2007

Spring AOP: Dynamic Proxies vs. CGLib proxies

Spring's AOP is proxy-based. Spring provides two different options to create the proxies. One is based on JDK dynamic proxies and works with interfaces, the other one utilizes CGLib and is based on classes. (That's why the property is called proxyTargetClass respectively proxy-target-class.) For the moment I just want to provide a quick summary on the pros and cons of both options:

JDK dynamic proxies:

  • The class has to implement interfaces. Otherwise you will get ClassCastExceptions saying that $Proxy0 can not be casted to the particular class.

  • Eventually dynamic proxies force you to program to interfaces since you can not cast the proxy to the class - a feature I really like about them.


CGLib proxies:

  • The proxies are created by sub-classing the actual class. This means wherever an instance of the class is used it is also possible to use the CGLib proxy.

  • The class needs to provide a default constructor, i.e. without any arguments. Otherwise you'll get an IllegalArgumentException: "Superclass has no null constructors but no arguments were given." This makes constructor injection impossible.

  • The proxying does not work with final methods since the proxy sub class can not override the class' implementation.

  • The CGLib proxy is final, so proxying a proxy does not work. You will get an IllegalArgumentException saying "Cannot subclass final class $Proxy0". But this feature is usually not needed anyway. (This issue might be solved in the future.)

  • Since two objects are created (the instance of the class and the proxy as instance of a sub class) the constructor is called twice. In general this should not matter. I consider changing the class' state based on constructor calls a code smell anyway.

  • You have CGLib as additional dependency.


Both options suffer from some issues (not really issues, but you have to be aware of them):

  • Most important proxy-based AOP only works from "outside". Internal method calls are never intercepted.

  • Second, the object has to be managed by the Spring container. Instantiating it yourself using new does not work.

  • The proxies are not Serializable.


Regarding performance of the one or the other method I have read different things. I remember having read a blog post about CGLib proxies being better, one of the comments says dynamic proxies are. Actually the Spring reference has a paragraph on this itself:
There's little performance difference between CGLIB proxying and dynamic proxies. As of Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future. Performance should not be a decisive consideration in this case.

I emphasized the last sentence by intention.

Especially for enforcing programming to interfaces and allowing constructor injection I strongly prefer the JDK dynamic proxies.

07 August, 2007

1,000th post

Nothing that really matters to the general public I guess. But I made my 1,000th post yesterday in the Spring forums. At the moment it's the community I'm most active in after I worked with Spring on my last two major projects.

The first project was a major refactoring. The web application was mainly separated into a web tier based on Apache Cocoon and a business tier without a container or distinct architecture. I introduced Spring for the dependency injection in the business tier and replaced the home-grown transaction framework with a JTA-based solution. Besides the database we access a Corba server and the file system transactionally so we need distributed transactions and two-phase commits. I wrote an XAResource/ JCA implementation for Apache Commons Transaction. Unfortunately I can't release this stuff as open-source but have to reimplement it when the time allows it. I use Jencks which integrates the Apache Geronimo transaction and connection management, so I don't need a full-blown JEE server, but I can use Spring and Apache Tomcat.

The second project was a portal. Starting from scratch was really nice. I could reuse my JTA/ JCA stuff and added JMS to the picture. As portal server Liferay 4.1.2 was chosen - and I learned to hate it quite fast. So many issues especially (but not only) with IBM DB2. Lately I switched to 4.3.0 - and I am quite happy with it. They have improved tremendously and now I can also recommend it. For the portlets I used Spring Portlet MVC which was really new at that time and had still the one or the other issue. But in contrary to Liferay (this improved a lot as well) and especially Hibernate (that's a topic on its own) I really got help from the community and issues got fixed really fast. That's when it makes fun to live on the bleeding edge and is not only frustrating.

Getting more and more used to the different parts of Spring I also started to share my knowledge. First it have been the custom scopes (which I used in both projects) and proxying (mostly for declarative transactions), later I added Spring MVC in general, Spring Portlet MVC in particular and the PropertyEditors to the picture. And so that's what I focus mainly on in the Spring forums.

Actually my home community is Apache Cocoon. That's were I started in end of 2000 and I became a committer in mid 2003. Unfortunately, by not working really with Cocoon for the last two years I lost more or less track of its development. I still try to bring me in from time to time though (as lately by propagating PropertyEditors as in Spring ;-) ). I'd like to work more again in this community again in the future, especially with the forthcoming next version 2.2.

15 July, 2007

There is always insufficient information ...

From a long experience on several mailing lists and forums I can tell you there is (nearly) always insufficient information. So thanks go actually to Andrew Stevens for the name of this blog. I laughed sooo much about his post on the Cocoon users list.

But what makes a post actually a good post?

1. Have in mind there are no dumb questions. Even if it has been asked a hundred times. This only means that the answer might be hidden too much in the documentation (a problem the Cocoon documentation suffers from a lot). The users must be taken seriously and so their documentation needs. If the code gets an end in itself the project will get obsolete. So listen to the users.

2. That's actually more a 1b. RTFM. Really, please try to solve an issue you have first on your own. Read the documentation, reference, manual, whatever it is called. Search the mailing lists. Use Google or your search machine of choice. Rarely that issue hasn't occurred before (though somebody must be always the first one obviously). Even if you can not solve the issue on your own having read the documentation will help you to understand (and later explain) the issue better.

3. Give your post a meaningful subject. "Help" is not a good one. Any mentioning of "urgent" is useless, you won't get your answers faster. Don't waste people's time with reading stuff they are actually not interested in.

4. Give context to your issue. Maybe you are trying to achieve something in a completely unusual way - if not even a dead end. Since nobody might have tried it that way and can't help you with your actual issue they might know alternative solutions or workarounds though. It makes it also easier to try to understand your issue.

X. Use an appropriate way of writing and styling your post. You should only post in plain text to mailing lists. That's not because all developers are purists, it's a matter of readability in the mailing list archives. Reading a HTML-mail in the archive is like reading the HTML-source of a web-page - or even worse since < and > are often escaped to &lt; and &gt;.
In forums it's the other way around. Reading code in variable-width fonts is really hard, not to forget that the code loses its indentation since the whitespaces get collapsed in HTML.

XX. To be completed ...