In my opinion, nothing has brought life into Java development like the Spring Framework. Enterprise development in Java 4 years ago had me scratching my head. Why do I need to implement methods in this interface when I don't declare I implement it? Why do I need Entity Beans? Which of the 8 web frameworks should I be using? Why does it take so long to go from fixing a bug to actually testing that it worked? Spring has in some way, shape, or form answered all of these questions. Well except for the 8 web frameworks one.
Spring started with a couple of developers who were as frustrated as I was with the complexity inherent in Java enterprise development. Fortunately for our community, they were and are much smarter and driven than I am and they wound up with a set of tools that simplify almost every aspect of development in a Java enterprise. I think one of the keys of Spring's success has been focusing on simplifying advanced concepts and providing extremely useful tools out of the box. This example shows how Spring has simplified Aspect Oriented Programming which was a rather radical shift for Java developers in the early days of AspectJ. Additionally it provides something that 90% of all Java projects would want out of the box. Simple entered/exited logging and performance monitoring.
This code in it's current state will provide good trace logging for any bean named *DAO or *Service. Change or add the interceptor name to PerformanceTraceInterceptor and it will provide performance metrics using the JAMon performance monitoring utility. All of this provided out of the box with Spring. Stay tuned for more Spring fanboy-ism in the future.
Wednesday, November 21, 2007
Tuesday, November 20, 2007
I've been tasked with optimizing some slowly performing transactions in a system that has been built upon Hibernate. Yesterday I ran across an interesting situation where a single transaction was resulting in 6 separate queries to the database. This may not necessarily be bad, but when the transaction was performing as slowly as it was, we needed to take whatever means we could to speed it up. What was unique to me was that we eliminated all but 2 queries, and we eliminated each one in very different ways.
- Use the second level cache for largely read only data. There was a table that had slipped through the cracks of our investigation that will rarely be updated. A couple of configuration entries later and it will be stored in a second level cache and refreshed on a weekly basis instead of causing an extra query hundreds or thousands of times per day.
- Eagerly fetch associations that are needed every time the transaction is called. The Criteria API in Hibernate allows the user to specify the fetch mode for every association, effectively overriding the default behavior provided by the mapping file. Setting the fetch mode to Eager for this association resulted in an extra left outer join, but it eliminated an extra query per result row.
- Don't haphazardly access collections that are not needed by all of your clients. The transaction in it's previous state would call off to a dependent collection and call the size() method on it to determine how many child records were linked to the parent. This caused every child record in that collection to be loaded by Hibernate, even though very few of the clients actually needed to know the size of this collection. Adding a property to the incoming request to determine if the transaction actually needed to fetch that count and then doing it by simply executing a separate projection based query resulted in much speedier performance for all clients.