Saturday, June 24, 2006

Variance in C# Generics to Follow Scala

This paper by Burak Emir, Andrew J. Kennedy, Claudio Russo, Dachuan Yu, slated for ECOOP 2006, has proposed modeling variance in C# generics in line very much similar to what Scala does. The proposed notation is based on definition-site declarations (as in Scala) and uses +/- to model covariance / contravariance, as also in Scala.

This proposed extension will make the following declarations possible:

// Covariant parameters used as result types
interface IEnumerator<+T> { T Current { get; } }

// Covariant parameters used in covariant result types
interface IEnumerable<+T> { IEnumerator<T> GetEnumerator(); }

// Contravariant parameters used as argument types
interface IComparer<-T> { int Compare(T x, T y); }


Here is the corresponding syntax in Scala using a covariant type parameter:

class Array[+a] {
  def apply(index: int): a
  ...
}


In order to ensure type-safety through static type checking, the new extension to variance annotations in C# allows covariant parameters only in producer positions in signatures and contravariant paramaters only in consumer positions. These restrictions are, however, overcome through the use of type constraints:

class List<+T> {
  ...
  List<U> Append<U>(U other) where T : U { ... }
  List<U> Append<U>(List<U> other) where T : U { ... }
  ...
}


Quite similarly we have the same solution in Scala by using a polymorphic method with a lower type parameter bound:

class Stack[+a] {
  def push[b >: a](x: b): Stack[b]
    = new NonEmptyStack(x, this)
  ...
}


As a sidenote, it may be mentioned that Java Generics addresses the variance problem by employing wildcards and using use-site declarations (as opposed to defintion-site in C# and Scala).

Friday, June 16, 2006

Does Ruby need AOP ?

With its strong metaprogramming facilities providing interceptors, hotswapping, mixins and hooks for injecting custom codes, it seems that Ruby developers can very well do without a separate vehicle for addressing crosscutting concerns. Bruce Tate, in his book Beyond Java, has opined that for Ruby developers, AOP is not quite as urgent, because you've already got robust tools to deal with these kinds of concerns ... Another Ruby champion David Heinemeier Hansson of Rails fame, has also expressed similar opinion in the same book:
A standardized AOP framework has never really taken off in Ruby because the language itself already supports most of the desirable functionality of AOP.


MetaProgramming - A Substitute for AOP ?

Never! Metaprogramming can at most be the vehicle for implementing AOP. The most important aspect (no pun intended) of AOP is the semantics, which it enforces for the problems which are supposed to be solved by metaprogramming. AOP is NOT about inserting code snippets at various places, it is about the semantics of abstracting the crosscutting behaviors of an application. The man who brought AOP to the world (Gregor Kiczales) was himself an expert of metaprogramming before and he has the following to say on the semantics of AOP :
Another advantage of a direct semantics for AOP is that it helps with abstraction. When we look at a complex object model, it's simpler to think of it as describing the behavior of the objects, rather than describing transformations on method tables that implement the behavior of objects. The same is true of AOP—it's simpler to think in terms of aspects of an object's behavior, rather than transformations on classes, which transform method tables, which implement the behavior of objects.

So, AOP is all about semantics, abstraction and behavior of the application and is at a much higher level of implementation than the raw power of metaprogramming.

Metaprogramming in Ruby - Too Much Power ?

Metaprogramming operates at a much lower level, empowers developers with too much raw power, which may be too potent for most applications. Let us look at the following snippet from Rails code (adopted from Beyond Java book) :

base.class_eval do
    alias_method :render_without_layout, :render
    alias_method :render, :render_with_layout
end


The code snippet displays metaprogramming prowess of Rails, which implements hotswapping behavior of the base class with improved functionality. But, as discussed above, this is too low a level of abstraction. Using AOP we would have had semantics first - a neat aspect consisting of advices operating on pointcuts. No wonder, Ruby has decided to introduce AOP constructs from Ruby2.

AOP - Only for Statically Typed Languages ?

This is a myth. The real truth is that dynamically typed languages have not yet reached the sufficient level of adoption in the community to feel the need of AOP. Hence Ruby programmers are quite content at the extreme power of meta programming features to implement crosscutting concerns in their applications. Once they reach the maturity in acceptance and we start seeing millions of lines of code written in big enterprise applications, they are sure to feel the need for more abstraction power in addressing the crosscutting concerns. Because of large scale adoption, we have rich tooling support for AOP in Java - when the same happens for Ruby and other dynamic languages we will definitely see the emergence of tools which allow us to program in aspects.

TailPiece

Irrespective of what Gavin King thinks about AOP (he recently snubbed AOP as totally overhyped, failed technology), I am a big fan of aspect oriented programming - recently this technology has delivered a world of good to our team in a Java based enterprise application. But that's for another day, another post ..

Thursday, June 08, 2006

Stateful Thinking with JBoss-Seam

A couple of days back I listened to the great interview of Gavin King at JavaPosse. Lots of voices have been burnt over this interview in TSS and elsewhere. In the interview Gavin talks about Hibernate, EJB3, JSF and the latest from JBoss, Seam. He lambasted stateless architectures and dismissed the thought that stateful session beans do not scale as an ancient canard in the Java community. He made some insightful comments regarding the architecture of Seam and how the stateful and contextual components of Seam manage application state for POJOs.

The main reason why the above interview of Gavin has raised so many eyebrows is that it has hit the community right on the nail and has attacked the most pervasive architecture in today's Java EE space. Rod Johnson led Spring community has successfully evangelized the stateless architecture backed by the most mature IoC container, since the dark ages of EJB 1 and EJB 2. In his landmark book, Rod mentions
Applications that don't hold server-side state are usually the most scalable. In a web application, for example, if we need to hold only minimal user state, we might be able to hold it in cookies, avoiding any need for HTTP session state replication.

Give me a break! Can u have a meaningful enterprise application without any requirement for holding server-side state ? What about the conversational applications that thrive on long running business processes necessitating application state management in multiple contexts ? I guess the Extended Persistence Context (EPC) was designed in EJB specifically for this purpose. I personally have been an admirer of the Spring technology and the simple yet powerful programming model that it has evangelized leading to a significant impact in developer's productivity. But Gavin King definitely has a point, which all of us need to ponder over - one size doesn't fit all. As I mentioned in my last blog, the developer community needs to make the proper judgement before deciding whether to eat the elephant or not.

HTTPSession or SFSB ?

This is one of the questions that has been raging the floors and blogs of all Java EE developers. The Spring community thinks SFSBs are sin - maintain state (if required), in HTTPSession and use session state replication for scalability. They suggest minimal state on the server side using fine grained session objects, which can be easily replicated across servers. But, as I mentioned above, how do we handle optimistic transactions, long sessions, conversational applications ? Gavin is justified when he FUDs Spring on this ..
Huh? You don't have SFSBs (or anything equivalent). How could you implement EPC (optimistic transaction) support without difficulty? If you could do this without difficulty, why did you not do it years ago, and save Hibernate users from years of pain with LazyInitializationException?!

Enter Seam - a grand unification of the component models of JSF and EJB3. The mission - Deprecate the stateless architecture that we have learnt to adopt so naturally. Seam adopts SFSBs as the main container of managed application state - a theory that Gavin King believes in from way back in 2004 while ruminating on the notion of "application transactions" in a hotel room in Thailand.

Why does Gavin believe that HTTPSession is NOT the place to hold application state and that doing so is NOT scalable ?

In order to answer this, let us first assume that any meaningful enterprise application needs to maintain server-side state. In a clustered environment, replicating state for transparently managing failover is expensive. Typically SFSBs-are-unscalable-school architects adopt either of the following solutions (based on Gavin's presentation on Seam at JavaOne) :

  • Maintain state in the database. This is very expensive since it involves heavy I/O with the slowest layer in the tier. Inevitably they land up with a second level cache that needs to be kept transactionally consistent between the database and every node on the cluster – even more expensive!

  • Maintain state in HttpSession as JavaBeans. This has 2 problems -


    • The contract for HttpSession does not have dirty-checking - session replication means a bulk copy of the entire coarse grained object across servers. Though implementations like JBoss HttpSession and caching solutions like Tangosol Coherence offer attribute level buddy replication, it is definitely not the standard. Hence u need to re-set the attribute each time you change the bean state, which is extremely bug-prone and difficult to test.

    • A JavaBean is not transactional - hence u need to have an indirection of the session stored JavaBean through SLSBs for implementing business logic.



OTOH, SFSBs are managed by the container, provides complete transaction semantics and JBoss SFSB, being implemented on top of JBossCache provides attribute level replication. Hence stateful session beans provide much richer semantics than the dumb JavaBeans. Cool Stuff! An application which involves long transactions needs to maintain conversational states in multiple contexts - Seam scaffolds all these state management under the hood of stateful session beans as contextual components. Hence what we get is an efficient implementation for EPC. Of course, in order to synchronize the lifecycle of the SFSBs with the session events, we need to maintain a ref/handle/proxy of the bean in the HttpSession. Even the new session scoped beans introduced in Spring 2.0 will not be able to offer an as efficient implementation, since HttpSession is not the suitable place to keep this "big" information and will have the usual problems of clusterability.

Lessons Learnt

Stateful session beans are not as black as they are painted. In fact they may be the best bet to store the application state. And Seam exploits these capabilities to the fullest and provides a very elegant framework to model conversational applications. So, keeping in line with my last post, I would like to end this musing with the belief that we, the developers should not be carried away by the current hype that open source Java has created. The developer community should always try to embrace the standards, critique the standards and make the standards better instead of trading it for an implementation.

Sunday, June 04, 2006

Spring, JBoss and The Elephant

Interface 21 and BEA recently announced the release of Pitchfork, the EJB3 implementation within the Weblogic container, built using Spring. It is actually more than an implementation of EJB3 specification and provides the additional capabilities offered by Spring, viz. full use of AOP and AspectJ integration, advanced DI capabilities etc. Every EJB u build can use all Spring backed services along with JSR 250 annotations and EJB style interceptions.

This release has sparked off a war of words between the Spring and JBoss community. The trail at Raible's blog is an interesting read and provides in depth analysis and invaluable judgement to architects and developers building up their Java EE stack. At the same time it also opens up a new can of worms, enough to put the entire Java EE developer community into a bed of confusion. After struggling with the hell of deployment descriptors and the infamous programming model of EJB2, I had been enlightened with the lights of the landmark book by Rod Johnson, which instantly indoctrinated me to the Spring world of POJOs, Dependency Injection and IoC Containers. I had always felt that Spring + Hibernate make my day. But some of the recent developments in the Java open source world like the tie up of Spring with BEA/WLS has pitchforked me (no pun intended!) into a world of uncertainty. Myself, being a Java developer by heart (of course my CEO thinks otherwise and does not give me a raise for architecting a good piece of Spring bean :-(), can't help but seek replies from the elite community regarding the following questions :

Question 1

Regarding EJB 3, Bruce Tate once mentioned "Don't make me eat the elephant again". We all know, EJB is a standard and being compliant with the standard is like programming to the interface. I don't like to get locked in an implementation. EJB 3 is designed for extension - as Gavin has rightly mentioned in the same trail, we should strive to provide add-ons via extension points provided in the EJB specification and offer them portably on all application servers. JBoss is pledging to provide opensource extension to EJB3 that adds pointcuts, which would spruce up EJB 3's anemic dependency injection functionality. As of this day, JBoss offers an Embeddable EJB3 Container using which u can deploy applications in Tomcat. Next time when I offer my Java EE stack to my client, should I go for the most trusted IoC container (a.k.a. Spring) and run the risk of locking myself to a concrete implementation OR try to eat the elephant again.

Question 2

Is there anything under the hood in Spring's tie up with BEA ? With the open source community raging amock, BEA has started losing grounds, they have lost their innovation trail and has come to the hard realization that they need to have Spring in their arms to beat the time to market of their competitors. But what is the value proposition of Spring in this entire deal - are they trying to trade in their quasi-EJB3 container (quoted from Gavin King in the comments trail in Matt Raible's blog entry) with the standards based implementations used by the huge customer base of BEA and WLS.

Parting Thoughts

The deficiencies of the current EJB3 specfication and implementation have been documented in many burning blogs and articles. OTOH, all is not green in the Spring world either. Spring does not have SFSBs - hence cannot provide an efficient implementation of EPC, modeling conversations in Spring is also broken (I have not yet looked at Spring 2.0) and above all u need to deal with reams of XML for whatever u want to do. Gavin King, trying to desperately defend his stake on the EJB3 specifications, has branded AOP as an overhyped and failed technology - possibly all for the sake of pushing the JBoss camp. Believe it or not, the open source world of the Java community is on fire. They have realized that all innovation happens here but the technology needs to carry the endorsement of Sun for it to reap the commercial benefits. As Peter Thomas has rightly pointed out in his blog, the open source landscape is getting increasingly commercialized nowadays. The developer community needs to make the proper judgement before deciding whether to eat the elephant or not.

Saturday, May 27, 2006

Functional Programming Under the Hoods - Developers Call it LINQ

The May CTP of C# 3.0 introduces LINQ amongst some other additional features of the language like implicitly typed local variables, extension methods, collection and object initializers etc. All of these features have been extensively critiqued here, here and here. But undoubtedly the features on which most blogs have burnt are the lambda expressions and Language INtegrated Query (LINQ). Lambda expressions in C# form the core of LINQ and brings us back the memories of functional programming of Lisp genre. With the current generation afflicted with the perils of Java schools, it will definitely require a change in mindset, a fresh relook at the old pages of Paul Graham to appreciate the underpinnings of the design of LINQ in the new release of C# 3.0 and Visual Basic 9. Think collections as monads, query operators as monad primitives, queries as monad comprehensions and what you get in LINQ is today's incarnation of Lisp, Haskell or ML. As Erik Meijer has mentioned correctly,
Functional programming has finally reached the masses, except that it is called Visual Basic instead of Lisp, ML, or Haskell.


Code-as-Data: Unveiling Lambdas in C# 3.0

Like Lisp, the lambdas of C# 3.0 support the code-as-data paradigm. However, in Lisp or Scheme, it is upto the developer to decide whether to use the code or data through the application of quote and quasi quote. C# 3.0 and VB 9 compiler automatically decides on the code or data for the lambda expression depending on the static type of the context in which the lambda occurs.

Expression<Func<Customer,bool>> predicate = c => c.City == "London";
Func<Customer,bool> d = predicate.Compile();


In the first statement, Expression<T> is a distinguished type, which preserves the lambda in the form of expression trees instead of generating traditional IL-based method body. Thus the lambda is data, instead of code - lispers reminisce of the quoted expression to achieve the same effect. In Lisp you use eval to translate the data into some executable - C# 3.0 offers Compile() over the expression tree, as in the second line above, which makes the compiler emit the IL.

The Grand Unification

The primary goal of LINQ is to unify programming against relational data, objects, and XML. Typically in today's applications, developers employ three disparate models - SQL for relational database programming, XQuery, XSLT etc. for XML processing and OOP for business logic. The LINQ framework presents a unified model using the technology of functional programming under the hoods and exploiting the algebraic nature of collections and operations on collections.

The design of LINQ consists of generic operations on collections abstracted as base patterns of query operators and domain specific extensions for XML (XLINQ) and relational database programming (DLINQ). Some of the experts have expressed concerns that LINQ may once again prove to be a bloat in the language with efforts towards ORM implementations. I have a completely different opinion on this. I have worked on enterprise scale Java EE projects with a relational database at the backend. I have personally burnt my head over performance issues in these applications and have come to the hard realization that you need to write performant SQL queries to have good transaction throughput. And typically developers write these SQL queries as untyped string constants within the Java codebase. Efforts towards using popular ORM frameworks like Hibernate simplify things a little bit, but still you cannot avoid having typeless SQL statements buried within your Java code, so long u have the impedance mismatch of the relational database at the backend. This is where LINQ and DLINQ rocks with the typed lambdas - the developer can write typed queries that work seamlessly over collections of objects, relational tables and XML documents. The ultimate aim of Microsoft is to use the LINQ framework to provide a unified approach to programming data and offering DSL support over multiple tuple-based data sources, resulting in a simpler programming model.

Polymorphic Queries in LINQ

Another exciting new feature that LINQ brings is the IQueryable interface, which allows writing true polymorphic queries that can be executed on an immediate or deferred mode in any target environment. The following example is from The Wayward WebLog :

public int CustomersInLondon(IQueryable<CUSTOMER> customers) {
  int count = (from c in customers
        where c.City == "London"
        select c).Count();
  return count;
}


In case you want to execute the query over a collection of objects ..

List<Customer> customers = ...;
CustomersInLondon(customers.ToQueryable());

And if the query is executed against a remote DLINQ collection, the underlying engine translates it to the appropriate SQL for the underlying database. Actually what goes on underneath is what the functional community calls comprehension. In case of the above query, the comprehension syntax is translated by the compiler into standard query operators.


All the new features in C# 3.0 and Visual Basic 9 bring back strong memories of Lisp and Haskell and rediscovers the joy of declarative programming. It only took a couple of decades to establish them as part of a mainstream language. It remains to be seen if other languages like Java follow suit.

Saturday, May 20, 2006

The Show is Over!

Day 4 at the Moscone Center began with the Sun raazmataaz where all real time applications of Java were at display. Mobile devices with rich Swing UIs, racing cars with Java inside, Java enabled robots etc. lighted up the Moscone Center for the last time in 2006. All of these high tech stuff was being conducted by James Gosling, the father himself, with a smile of satisfaction, that only goes along with an invention. Of course before the tech extravaganza, we had Scott McNealy giving away the Lance Armstrong tshirt to the winner of ride-your-bike competition in this year's JavaOne. Boy, what a shift in the paradigm - Scott was the CEO a month back when possibly he had prepared his keynote for JavaOne 2006. And now he got a 20 minute slot on the last day of the Conference for giving away tshirts!

There were some very good sessions lined up for the last day. I started with the one on EJB 3.0 delivered by Craig McClanahan, Linda DeMichiel and Gavin King. The session took us through the POJO slogan which EJB 3.0 could ultimately get out of its door. Linda described all the major architectural features of EJB 3.0, Craig took us through the JSF integration part, while Gavin King demonstrated some of the advanced applications of transaction handling using the architecture. EJB 3.0 is a much better incarnation than its predecessor, EJB 2.0, which was almost unusable. But still the capabilities of 3.0 are only a subset of what we have in Spring - experts are very sceptical and some of them has procrastinated EJB 3.0 as inferior and a big step backward from Spring. For more details, go through what Rick Hightower has to say in this JDJ article.

On popular demand, an introductory session of Ajax was repeated on this day - the one by Ben Galbraith. I decided to walk into it - at the end of it, I do not regret my decision. It was a very well delivered session with lots of information (mostly introductory though) on Ajax. The guy showed lots of real life examples of Ajax implementations including google maps, google suggest and some cool programming tricks and debugging how-tos.

On the whole, JavaOne 06 demonstrated to the world the awesome community that has been built around this technology platform. It has truly transcended all barriers of life and touched upon all walks of the social fabric. All said and done, the users want more from the technology which promises to be the ubiquitous platform of computing. A more viable licensing policy for Java, more enhanced JVM with support for functional languages, continuations, tail call, higher order functions etc. etc. .. the list goes on. I am always hopeful of a brighter tomorrow ..

And oh, BTW, the bookstore at the Conference was a smashing hit - I myself picked up five books for my collection at a coool discount of 20% ..

JavaOne Day 3 - The Rampdown Begins

Day 3 began with Erich Gamma taking centrestage with mission Eclipse. In the presentation titled "Java in the Trenches - Reflections Along the Eclipse Way", Gamma and John Wiegand took us through the development cycle of the Eclipse platform, which has delivered quality software with impeccable precision on delivery dates. The visuals which they demonstrated for the Eclipse version of agile methodologies reflected upon the enormous experience and process maturity that the team has imbibed over the years.

Gilad - The Saint

Gilad Bracha has a unique way of presenting things. He does not have the aggression of Josh Bloch, rather a very saintly way of taking the hall through the journey. His session entitled "Dynamic Languages on the Java Platform" had a full house. Though there was nothing very new from the content point of view apart from what he has already blogged on this subject, it was a fairly informative session. Typical responses expected as Q&A like tail call support in the JVM were dealt with in a saintly way (of course in the negative) by Gilad. Later after the talk, he has blogged his disappointment at the crowd not asking for Continuations support in the JVM - he had the response ready though. Support of continuations in the JVM has been discussed in many forums and Gilad has categorically turned all of them down citing reasons like cost of implementation and incompatibility with the current Java SE security model. Hence, I guess, people have given up all hope of finding continuation support in a JVM in the near future. This is what Gilad has to say in his blog on this issue
... continuation based web servers are very nice. Seaside is the nicest one I've seen. But ultimately they are just a phase, and we can already see how we will outgrow that phase. Since continuation-based servers won't be all that significant in the long term, and given the huge lead times and costs of adding continuations to the JVM, it makes little sense to support them.

Web servers aside, continuations, though admittedly difficult to implement, has many other uses. The comments section of Gilad's blog entry has ample testimony towards that.

Ajax Ajax

In day 3, also there were lots of sessions on Ajax, RIA, Dojo and Web 2.0. Not all of them were of high quality, but, while the lights are on, go follow the bandwagon. The new kid on the Ajax and SOA combo, JackBe, had Deepak Alur and Dan Malks (both of J2EE patterns fame) moderate a session on "Java Technology, Ajax, Web 2.0 and SOA", which had Craig McClanahan and Rod Johnson (among others) on the panel. I attended the session, which I felt was quite crappy, since none of Craig or Rod ever found the space to get going. And when Ajax is there in the panel discussion topic and u have a full house, nothing, but chaos can only reign!

In another session titled "Using the DOJO Toolkit to Develop AJAX enabled Java EE Web Applications", the speakers did a fairly good job of taking the (once again) full house through the process of using frameworks in an Ajax application. And DOJO seems like a leader in this space.


Apart from the above, I attended some of the other sessions where the main themes were once again GlassFish, NetBeans and how a combination can give us an easier programming model. Motorola, in their general session once again emphasized how they are transforming the mobile world with Java technology. The evening sessions on Day 3 saw a remarkable fall in attendance, since the sessions had to compete with free beer available in the After Dark Bash - no wonder we had some more crappy stuff scheduled during these hours.

Tomorrow I plan to attend a couple of sessions on EJB 3.0, which has been released after it passed the community process. If u consider the pre-Spring era, EJB 3.0 looks to be a solid progress from its demon predecessor towards a scalable component model. But hey, we have been through Spring and the best practices sermons of Rod Johnson - compared to that EJB 3.0 falls far below expectations. However, that's for another day, folks .. for now it is DG signing off from Moscone Center, San Francisco.

Friday, May 19, 2006

JavaOne Day 2 - Josh Rocks, But It's Ajax All the Way

Every year, JavaOne throws up the theme of the show. This year it's Ajax all the way. Every tech session on Ajax is booked, the most notable among them being the flagship session on "An Introduction to AJAX" by the founders of Ajaxian.com, Ben Galbraith and Dion Almaer. As has been mentioned in the conference report by John O' Conner
Using simple but effective examples, the two made a compelling argument for using Asynchronous JavaScript with XML (AJAX) to create dynamic, responsive applications that are easy to deploy and that require nothing more than a common web browser.

Besides this flagship from the creators, there were many other sessions which focussed on Ajax, RIA, SWT and the likes which promise to bring heaven on the client browser.

Josh Rocks!

I attended three sessions by Joshua Bloch, one of them the famous Puzzlers Session with Neal Grafter. Their book "Java Puzzlers - Traps, Pitfalls and Corner Cases" has been doing great in this year's JavaOne, but in their tech session the two wizards set the floor on fire with new additions to the puzzlers collection. Great show and I enjoyed every bit of it. This was preceded by a solo from Josh where he discussed some of the advanced Java patterns and idioms, which he promised to load in the next edition of Effective Java. Cool stuff! The icing on the cake was the BOF on "Collection Connection", which happened to be the eleventh edition of the show. Eleven long years - yet the Collections Framework is evolving, a definite sign of a living language (or perhaps Dynamic Language, as Gilad would like to mention it). The BOF was brightened up by the lumious anecdotes which Josh mentioned while recollecting his struggle with Binary Search in his CMU days. Overall the BOF was extremely enlightening with good indications of what to expect from the Collections Framework in Mustang and Dolphin.

Don't Ignore the Scripters

Two very interesting sessions which I attended on the second day of the conference included the ones on Groovy and JRuby. The Groovy session, led by Rod Cope had entertainments written all over. Some of the crazy things which he demonstrated included opening up new excel worksheets, filling up with data, formatting stuff, generating charts and ultimately putting the entire control within a Swing panel with buttons and callbacks - all with 20 lines of Groovy code! This is developer's productivity, at its best.

In the session on JRuby, the creators, Charles Nutter and Thomas Enebo, were there discussing passionately their experience trying to bring up the most powerful scripting language on planet into the Java Virtual Machine.

Can Java Studio Creator Eclipse the IDE World ?

Sun has come out strong with the message to use the Sun Java Studio Creator. Based on its much hyped NetBeans development environment, the creator has lots to offer as a rapid web application visual development tool. The Creator comes bundled with the Application Server, a database named Derby, data binding facilities through drag and drop, Ajax enabled JSF components, portlets as a project type, bunch of goodies for writing Web Services, themes and what not!. It will be really interesting to find out how the Big Blue responds with all the happenings in its Eclipse world. Tomorrow, I will find out what IBM has to say in the General Session to be addressed by none other than Erich Gamma.

In today's general sessions, both Oracle and BEA, led with their efforts towards contributing stuff to the Java space. BEA mentioned about their "blended strategy" of fusing commercial software and open source software towards development of enterpise tools that will make programming an enjoyable developer experience. The director of developer relations at BEA reiterated that BEA has been a key player in the open-source space. The company is a board member of the Eclipse Foundation and sponsored such projects as Apache Beehive, Apache XMLBeans, Eclipse AspectJ, Eclipse WTP, and more, besides being the first application server to provide certified support for the Spring framework.

Overall, day 2 at JavaOne had the all pervasive theme of Rich Internet Experience with Ajax leading all the way. Amidst all the industry frantics and open source hullahs, Gilad Bracha's session on "Superpackages: Development Modules in Dolphin" went almost unnoticed, with half of the hall empty. It had some important points though, which promise to make modular developments much easier in Java. But, at least for today, Ajax rules !

Thursday, May 18, 2006

JavaOne Rumblings - Day 1

More community partcipation, more Open Source, crying for more compatibility - these sum up the clairvoyance of the chief Java evangelists of Sun Microsystems, as the first General Session of JavaOne 2006 unfolded to a live band playing below the multiplex of gigantic screens in Moscone Center of San Francisco. I am here for the first time to attend the pinnacle of all Java summits and celebrate the technology that Jonathan Schwartz says has become the key ingredient of the digital experience for hundreds of millions of people across the planet. Thank you Anshinsoft for sponsoring me for this trip.

I attended one of the Java University courses titled "How Java EE Patterns Help in Architecting and Designing Robust Java EE Applications". The instructor was very energetic and covered lots of material within the stipulated time frame. But at the end of the day, it was all same old stuff regarding Session Facade, Business Delegate and Transfer Objects. I expected something new related to the upcoming EJB 3.0 stuff, patterns for designing generic frameworks using EJB 3.0 interceptor technology, patterns for exploiting Java 5 annotations etc. With those old patterns which Deepak Alur had documented 5 years ago, the course was a run down of yet another UML based development, the old way, when people used to develop tons of models (read diagrams) only to discover that they have become outdated before the programmers could start writing a single line of code. Give me a break! The waterfall model of producing use-cases, refining use-cases, generating class diagrams, generating sequence diagrams etc. always work in demos and tutorials with a handful of classes, but they never scale in real life applications.

Open Source! Open Source!

All projects in java.net has been open sourced and this was repeated in almost all of the sessions by all leading Java evangelists. Jeff Jackson, SVP, Java Enterprise Platforms and Developer Products, emphasized on more community involvement to support all Java EE initiatives. He called for the following Calls to Action for the audience:

  • Join JCP

  • Download NetBeans and join the NetBeans community

  • Join java.net, and join the projects now open sourced, such as Sun Java Studio Creator 2, GlassFish, Mustang, WSIT (whiz-it)

  • Get the free GlassFish Open Source App Server

  • Visit The Aquarium, a Virtual water cooler for WSIT and GlassFish

  • Contribute to the BPEL Engine into Open ESB

  • Use the Beta of Java SE 6


What does the above imply ? As a developer, do I really care whether Java becomes open source from tomorrow - I have access to all source codes of the Java platform, except the JVM. And 99% of all developers worldwide do not care about the inner workings of the Java Virtual Machine. I fully agree with Cedric, that the one thing that Sun needs to figure out is the licensing and redistribution policies of Java. There are companies like BEA, IBM and Oracle, with bigger stake in Java's success waiting ringside to drive forward with developments in the core platform. It cannot be denied that much of the progress that we have seen on the Java front has been due to community participation - the progress on the core side (i.e. JVM and JRE) has been impeded by Sun itself. Compare it with Microsoft's progress with the .NET platform - there has been a flurry of developments in the recent past with all sorts of creative features being incorporated within the core platform.

Showcasing NetBeans

The first day at JavaOne was dominated by the showcasing of NetBeans - at least three sessions demonstrated how a sample Java EE application can be developed using NetBeans 5.5 in less than 15 minutes. Boy, if application development was really this easy! However, on the whole, Sun has been able to make its presence felt in the IDE space with ample demonstrations of the capabilities of NetBeans and its integration with the entire GlassFish suite.

Back to the POJOs

EJB 3.0 is here! In the technical session on EJB 3.0, it was obvious that the creators admitted the cumbersome programming model of earlier versions of EJB and brought out the POJO based architecture of EJB 3.0. The Java Persistence API of EJB 3.0 has been contributed by BEA through its KODO implementation, which will also form the backbone of the next Weblogic Application Server.

On the whole the main theme of Java EE 5 as evident from the first day's session in JavaOne is to come out with a more user-friendly programming model focussing on the ease of development. I think with all collaborations and community building exercises, this will make life easier for programmers at large and architects in general.

Tomorrow, the second day of JavaOne promises great stuff from Joshua Bloch. I will be back with some more news and fresh perspectives in the next edition of this blog. Till then .. Peace.

Monday, May 08, 2006

Don't Generate Code - Generate Model Implementations Instead

There has been lots of confusions regarding my views on automated code generation, since I wrote my last post. I guess it is the following rumbling that spread across the bad word and insinuated me as one of the crusadors of tool based code generation:
I have never been a fan of automatic code generators, which always tend to produce tons of boilerplates, which could otherwise be refactored much more elegantly using OO frameworks.

To some extent, the lack of expressiveness of my intent has been responsible for this - possibly my ardent readers have missed out the last segment of the above statement which qualifies my disliking to only those code generators which produce tons of boilerplate codes violating the ageold principles of abstraction and encapsulation. That was exactly my point in the last post, where the DAO generator generated lots of Java code which could otherwise be abstracted in an OO framework.

In today's world code generators have a significant role to play in the areas of Model Driven Architecture (MDA). Until recent times, UML had acquired the ignominy of being the unfriendly companion to the project manager - to the extent that we had started talking about Death by UML Fever, where designers produced tons of model documents which became obsolete even before the developers could install the proper plugins of Eclipse. UML 2.0 promises support for MDA - the new MDA-based features allow creation of various architectural modeling styles supporting reusable design patterns.

EMF, the Eclipse Modeling Framework offers MDA capabilities with UML as one of the importers of the model. The model which you design using UML can be directly imported into EMF and Java code for the implementation can be generated directly out of it. The model can be as rich with all sorts of relationships like aggregation, composition, inheritance and association - the EMF code generation module takes care of every iota of the richness and generates Java code as the implementation. Apart from UML, EMF also supports XMI documents, XML Schema and annotated Java as source of model artifact. e.g. We can define an annotated Java interface as follows:

/**
 * @model
 */
public interface Book {
  /**
   * @model
   */
  String getTitle();

  /**
   * @model
   */
  int getPages();
}


EMF code generator will spit out the following as implementation of the above model, a Java interface along with the corresponding implementation class:

public interface Book extends EObject {
  String getTitle();
  void setTitle(String value);

  int getPages();
  void setPages(int value);
}

public class BookImpl extends EObjectImpl implements Book {
  ...
  protected static final int PAGES_EDEFAULT = 0;
  protected int pages = PAGES_EDEFAULT;

  public int getPages() {
    return pages;
  }

  public void setPages(int newPages) {
    int oldPages = pages;
    pages = newPages;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, ..., oldPages, pages));
  }

  ...
}

In the above code fragment (adopted from this series in developerWorks), the generator takes care of complicated semantics like enabling the observer pattern for the set method by notifying any observers of the abstraction through the eNotify() method. Also note the optimization guards implemented by the call to eNotificationRequired(), which, in the degenerate case (no observers) amounts to nothing more than an efficient null pointer check, which is inlined when using a JIT compiler.

The code generator component of EMF, called EMF Codegen, also supports customizable code generation through JSP like templates, JET(Java Emitter Templates) and easy regeneration and merging.

How is the code generator of EMF different from the run of the mill ones which generate boilerplates ?

The heart of the EMF is the ECore Metamodel, which has mapping for every UML construct. Hence when the UML model is translated into Java code, we have a lossless translation which preserves all the richness of the original artifact. An excellent illustration of these capabilities has recently been discussed in a TSS article by Patrik Nordwall. Hence EMF Codegen generates model implementations, as opposed to boilerplates.

So, next time when you think about rolling out your code generator, double check if you are producing code that can be better abstracted through an OO framework. And use your framework model and a lightweight DSL to generate model implementations, rather than boilerplates.

Friday, April 28, 2006

Code Generation, Boilerplates and OO

Of late, I have been playing around with DAOs a little bit and have also been blogging extensively on the implementation aspects of them (e.g. see here and here). Of all the leading vendors that offer DAO implementation, CodeFutures' Firestorm/DAO offers automatic code generation for DAOs from the relational schema. Andy Grove, the CTO of CodeFutures claims in his weblog that the code which FireStorm generates is as efficient and maintenable as hand-written code. In fact he also has a separate blog entry on the debate of frameworks versus code generators, where he mentions about the complexity of maintaining the framework as one of the driving reasons for going to the code generator approach. As an example he mentions that
the real benefit of Code Automation is that if the underlying framework changes substantially (for example going from EJB 1.1 to EJB 2.0) then the code can be re-generated for the new framework.


I have never been a fan of automatic code generators, which always tend to produce tons of boilerplates, which could otherwise be refactored much more elegantly using OO frameworks. Here is what Rod Johnson has to say about automatic generation of DAOs
There shouldn't be vast amounts of boilerplate code in DAOs. ... Using JDBC abstraction layer is better than generating JDBC code from a maintenability perspective. If we see requirement for boring repetitive code, we should apply an OO solution and abstract it into a framework, rather than generate it and live with the resulting duplication.


In one of my earlier posts, I expressed the same concern regarding the level of abstraction that Firestorm generated DAOs provide - I still feel that the code could have been better reengineered had we employed an OO framework based solution. At Anshinsoft we have been working on generic DAOs and adopting a mixed strategy for DAO code generation. All repetitive codes are part of an OO framework, which offers base level abstractions for DAO operations. The generated code only contains the specifics for the particular tables as specializations of the base abstractions.

After going through Andy's weblogs, recently I downloaded a copy of the evaluation version of FireStorm/DAO and started playing with it. I generated some DAO code against a schema and came up with the following implementation of AuthorDao, which I replicate below. The generated DAO implementation class consists of 586 lines of code for a table having 3 columns! Multiply this with the number of tables that can be there in a typical enterprise application, and all jars begin to explode.



/*
 * This source file was generated by FireStorm/DAO 3.0.1
 * on 07-Apr-2006 at 10:13:32
 *
 * If you purchase a full license for FireStorm/DAO you can customize this file header.
 *
 * For more information please visit http://www.codefutures.com/products/firestorm
 */

package com.mycompany.myapp.jdbc;

import com.mycompany.myapp.dao.*;
import com.mycompany.myapp.factory.*;
import com.mycompany.myapp.dto.*;
import com.mycompany.myapp.exceptions.*;
import java.sql.Connection;
import java.sql.Types;
import java.util.Collection;
import org.apache.log4j.Logger;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;

public class AuthorDaoImpl extends AbstractDataAccessObject implements AuthorDao
{
  /**
   * The factory class for this DAO has two versions of the create() method - one that
takes no arguments and one that takes a Connection argument. If the Connection version
is chosen then the connection will be stored in this attribute and will be used by all
calls to this DAO, otherwise a new Connection will be allocated for each operation.
   */
  protected java.sql.Connection userConn;

  protected static final Logger logger = Logger.getLogger( AuthorDaoImpl.class );

  /**
   * All finder methods in this class use this SELECT constant to build their queries
   */
  protected final String SQL_SELECT = "SELECT ID, NAME, PASSWORD FROM " + getTableName() + "";

  /**
   * Finder methods will pass this value to the JDBC setMaxRows method
   */
  private int maxRows;

  /**
   * SQL INSERT statement for this table
   */
  protected final String SQL_INSERT = "INSERT INTO " + getTableName() + " ( ID, NAME, PASSWORD ) VALUES ( ?, ?, ? )";

  /**
   * SQL UPDATE statement for this table
   */
  protected final String SQL_UPDATE = "UPDATE " + getTableName() + " SET ID = ?, NAME = ?, PASSWORD = ? WHERE ID = ?";

  /**
   * SQL DELETE statement for this table
   */
  protected final String SQL_DELETE = "DELETE FROM " + getTableName() + " WHERE ID = ?";

  /**
   * Index of column ID
   */
  protected static final int COLUMN_ID = 1;

  /**
   * Index of column NAME
   */
  protected static final int COLUMN_NAME = 2;

  /**
   * Index of column PASSWORD
   */
  protected static final int COLUMN_PASSWORD = 3;

  /**
   * Number of columns
   */
  protected static final int NUMBER_OF_COLUMNS = 3;

  /**
   * Index of primary-key column ID
   */
  protected static final int PK_COLUMN_ID = 1;

  /**
   * Inserts a new row in the AUTHOR table.
   */
  public AuthorPk insert(Author dto) throws AuthorDaoException
  {
    long t1 = System.currentTimeMillis();
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      StringBuffer sql = new StringBuffer();
      sql.append( "INSERT INTO " + getTableName() + " (" );
      int modifiedCount = 0;
      if (dto.isIdModified()) {
        if (modifiedCount > 0) {
          sql.append( ", " );
        }
    
        sql.append( "ID" );
        modifiedCount++;
      }
    
      if (dto.isNameModified()) {
        if (modifiedCount > 0) {
          sql.append( ", " );
        }
    
        sql.append( "NAME" );
        modifiedCount++;
      }
    
      if (dto.isPasswordModified()) {
        if (modifiedCount > 0) {
          sql.append( ", " );
        }
    
        sql.append( "PASSWORD" );
        modifiedCount++;
      }
    
      if (modifiedCount==0) {
        // nothing to insert
        throw new IllegalStateException( "Nothing to insert" );
      }
    
      sql.append( ") VALUES (" );
      for (int i=0; i < modifiedCount; i++ ) {
        if (i>0) {
          sql.append( "," );
        }
    
        sql.append( "?" );
      }
    
      sql.append( ")" );
      stmt = conn.prepareStatement( sql.toString() );
      int index = 1;
      if (dto.isIdModified()) {
        stmt.setInt( index++, dto.getId() );
      }
    
      if (dto.isNameModified()) {
        stmt.setString( index++, dto.getName() );
      }
    
      if (dto.isPasswordModified()) {
        stmt.setString( index++, dto.getPassword() );
      }
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + sql.toString() + " with values: " + dto);
      }
    
      int rows = stmt.executeUpdate();
      long t2 = System.currentTimeMillis();
      if (logger.isDebugEnabled()) {
        logger.debug( rows + " rows affected (" + (t2-t1) + " ms)");
      }
    
      return dto.createPk();
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Updates a single row in the AUTHOR table.
   */
  public void update(AuthorPk pk, Author dto) throws AuthorDaoException
  {
    long t1 = System.currentTimeMillis();
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      StringBuffer sql = new StringBuffer();
      sql.append( "UPDATE " + getTableName() + " SET " );
      boolean modified = false;
      if (dto.isIdModified()) {
        if (modified) {
          sql.append( ", " );
        }
    
        sql.append( "ID=?" );
        modified=true;
      }
    
      if (dto.isNameModified()) {
        if (modified) {
          sql.append( ", " );
        }
    
        sql.append( "NAME=?" );
        modified=true;
      }
    
      if (dto.isPasswordModified()) {
        if (modified) {
          sql.append( ", " );
        }
    
        sql.append( "PASSWORD=?" );
        modified=true;
      }
    
      if (!modified) {
        // nothing to update
        return;
      }
    
      sql.append( " WHERE ID=?" );
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + sql.toString() + " with values: " + dto);
      }
    
      stmt = conn.prepareStatement( sql.toString() );
      int index = 1;
      if (dto.isIdModified()) {
        stmt.setInt( index++, dto.getId() );
      }
    
      if (dto.isNameModified()) {
        stmt.setString( index++, dto.getName() );
      }
    
      if (dto.isPasswordModified()) {
        stmt.setString( index++, dto.getPassword() );
      }
    
      stmt.setInt( index++, pk.getId() );
      int rows = stmt.executeUpdate();
      long t2 = System.currentTimeMillis();
      if (logger.isDebugEnabled()) {
        logger.debug( rows + " rows affected (" + (t2-t1) + " ms)");
      }
    
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Deletes a single row in the AUTHOR table.
   */
  public void delete(AuthorPk pk) throws AuthorDaoException
  {
    long t1 = System.currentTimeMillis();
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + SQL_DELETE + " with PK: " + pk);
      }
    
      stmt = conn.prepareStatement( SQL_DELETE );
      stmt.setInt( 1, pk.getId() );
      int rows = stmt.executeUpdate();
      long t2 = System.currentTimeMillis();
      if (logger.isDebugEnabled()) {
        logger.debug( rows + " rows affected (" + (t2-t1) + " ms)");
      }
    
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Returns the rows from the AUTHOR table that matches the specified primary-key value.
   */
  public Author findByPrimaryKey(AuthorPk pk) throws AuthorDaoException
  {
    return findByPrimaryKey( pk.getId() );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'ID = :id'.
   */
  public Author findByPrimaryKey(int id) throws AuthorDaoException
  {
    Author ret[] = findByDynamicSelect( SQL_SELECT + " WHERE ID = ?", new Object[] { new Integer(id) } );
    return ret.length==0 ? null : ret[0];
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria ''.
   */
  public Author[] findAll() throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " ORDER BY ID", null );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'ID = :id'.
   */
  public Author[] findWhereIdEquals(int id) throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " WHERE ID = ? ORDER BY ID", new Object[] { new Integer(id) } );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'NAME = :name'.
   */
  public Author[] findWhereNameEquals(String name) throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " WHERE NAME = ? ORDER BY NAME", new Object[] { name } );
  }

  /**
   * Returns all rows from the AUTHOR table that match the criteria 'PASSWORD = :password'.
   */
  public Author[] findWherePasswordEquals(String password) throws AuthorDaoException
  {
    return findByDynamicSelect( SQL_SELECT + " WHERE PASSWORD = ? ORDER BY PASSWORD", new Object[] { password } );
  }

  /**
   * Method 'AuthorDaoImpl'
   *
   */
  public AuthorDaoImpl()
  {
  }

  /**
   * Method 'AuthorDaoImpl'
   *
   * @param userConn
   */
  public AuthorDaoImpl(final java.sql.Connection userConn)
  {
    this.userConn = userConn;
  }

  /**
   * Sets the value of maxRows
   */
  public void setMaxRows(int maxRows)
  {
    this.maxRows = maxRows;
  }

  /**
   * Gets the value of maxRows
   */
  public int getMaxRows()
  {
    return maxRows;
  }

  /**
   * Method 'getTableName'
   *
   * @return String
   */
  public String getTableName()
  {
    return "AUTHOR";
  }

  /**
   * Fetches a single row from the result set
   */
  protected Author fetchSingleResult(ResultSet rs) throws SQLException
  {
    if (rs.next()) {
      Author dto = new Author();
      populateDto( dto, rs);
      return dto;
    } else {
      return null;
    }
    
  }

  /**
   * Fetches multiple rows from the result set
   */
  protected Author[] fetchMultiResults(ResultSet rs) throws SQLException
  {
    Collection resultList = new ArrayList();
    while (rs.next()) {
      Author dto = new Author();
      populateDto( dto, rs);
      resultList.add( dto );
    }
    
    Author ret[] = new Author[ resultList.size() ];
    resultList.toArray( ret );
    return ret;
  }

  /**
   * Populates a DTO with data from a ResultSet
   */
  protected void populateDto(Author dto, ResultSet rs) throws SQLException
  {
    dto.setId( rs.getInt( COLUMN_ID ) );
    dto.setName( rs.getString( COLUMN_NAME ) );
    dto.setPassword( rs.getString( COLUMN_PASSWORD ) );
  }

  /**
   * Returns all rows from the AUTHOR table that match the specified arbitrary SQL statement
   */
  public Author[] findByDynamicSelect(String sql, Object[] sqlParams) throws AuthorDaoException
  {
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      // construct the SQL statement
      final String SQL = sql;
    
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + SQL);
      }
    
      // prepare statement
      stmt = conn.prepareStatement( SQL );
      stmt.setMaxRows( maxRows );
    
      // bind parameters
      for (int i=0; sqlParams!=null && i < sqlParams.length; i++ ) {
        stmt.setObject( i+1, sqlParams[i] );
      }
    
    
      rs = stmt.executeQuery();
    
      // fetch the results
      return fetchMultiResults(rs);
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(rs);
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

  /**
   * Returns all rows from the AUTHOR table that match the specified arbitrary SQL statement
   */
  public Author[] findByDynamicWhere(String sql, Object[] sqlParams) throws AuthorDaoException
  {
    // declare variables
    final boolean isConnSupplied = (userConn != null);
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    
    try {
      // get the user-specified connection or get a connection from the ResourceManager
      conn = isConnSupplied ? userConn : ResourceManager.getConnection();
    
      // construct the SQL statement
      final String SQL = SQL_SELECT + " WHERE " + sql;
    
    
      if (logger.isDebugEnabled()) {
        logger.debug( "Executing " + SQL);
      }
    
      // prepare statement
      stmt = conn.prepareStatement( SQL );
      stmt.setMaxRows( maxRows );
    
      // bind parameters
      for (int i=0; sqlParams!=null && i < sqlParams.length; i++ ) {
        stmt.setObject( i+1, sqlParams[i] );
      }
    
    
      rs = stmt.executeQuery();
    
      // fetch the results
      return fetchMultiResults(rs);
    }
    catch (SQLException _e) {
      logger.error( "SQLException: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "SQLException: " + _e.getMessage(), _e );
    }
    catch (Exception _e) {
      logger.error( "Exception: " + _e.getMessage(), _e );
      throw new AuthorDaoException( "Exception: " + _e.getMessage(), _e );
    }
    finally {
      ResourceManager.close(rs);
      ResourceManager.close(stmt);
      if (!isConnSupplied) {
        ResourceManager.close(conn);
      }
    
    }
    
  }

}


To me, this is reams of boilerplate code with hardly any abstraction for the common SQL operations. Have a look at the method Author[] findByDynamicSelect(...), which gets duplicated for every DAO you generate. Apart from the return type and the exception class, everything is identical across all DAOs! This, I think, is a design smell. As Andy has mentioned in his blog, Code Generators don’t mind writing repetitive code, but all these repetitive stuff goes to swell the bottomline of my application. I have been working on a financials project which has 600 database tables - the amount of boilerplate code that will be generated with the above approach will be enough to stretch the existing jar size by at least 30%. I simply could not afford the decision.

Bye Bye Code Generators - Enter OO

In my earlier post, I had discussed about how generic DAOs have helped us shrinkwrap the core data access functionalities into generic base abstractions - every specific DAO implementation only contains the details of that particular database table. Have a look at the following code generated for a table Employee using our code generator and OO framework concoction :


package com.anshinsoft.pi.dao.app.dao;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;

import com.anshinsoft.pi.core.StringBufferSize;
import com.anshinsoft.pi.dao.DAOBase;
import com.anshinsoft.pi.dao.DAOImplBase;
import com.anshinsoft.pi.dao.DTOBase;
import com.anshinsoft.pi.pix.orm.DbUtils;
import com.anshinsoft.pi.pix.orm.ICriteria;
import com.anshinsoft.pi.pix.orm.NullCriteria;
import com.anshinsoft.pi.pix.orm.SimpleCriteria;


/**
 * The DAO implementation for {@link Employee} class.
 *


 *
 */
public class EmployeeDAO
    extends DAOBase {


  /**
   * Enum for column names.
   */
  public enum ColumnNames {

    PK,
    ID,
    NAME,
    BIRTH_DATE,
    JOINING_DATE,
    DESIGNATION,
    ADDRESS_PK,
    PASSPORT_NO,
    EXPERTISE;

    /**
     * Constructor.
     */
    ColumnNames() {
    }
  }


  /**
   * Constructor.
   *
   * @param impl the concrete implementation of {@link DAOImplBase}
   */
  public EmployeeDAO(DAOImplBase impl) {
    super(impl);
  }

  /**
   * Returns a list of the column names.
   * @return list of column names.
   */
  protected List getColumnNames() {
    ColumnNames[] names = ColumnNames.values();
    List l = new ArrayList(names.length);
    for (ColumnNames name : names) {
      l.add(name.name());
    }
    return l;
  }


  /**
   * Subclasses must override and provide the TABLE_NAME
   * that the bean is associated with.
   *
   * @return the table name.
   */
  public String getTableName() {
    return "EMPLOYEE";
  }


  /**
   * {@inheritDoc}.
   */
  protected ICriteria getPrimaryKeyWhereClause(T employee) {
    try {
      String str =
      BeanUtils.getProperty(employee,
        DbUtils.dbColumn2PropertyName(
        ColumnNames.PK.name()));
      return new SimpleCriteria(
        new StringBuilder(StringBufferSize.SMALL.size())
        .append(ColumnNames.PK.name())
        .append(" = ")
        .append(str).toString());
    } catch (Exception ex) {
      return NullCriteria.getInstance();
    }
  }
}



All mundane SQL operations are wrapped inside DAOBase<T>, all base level functionalities of transfer objects are encapsulated within DTOBase. In case the user wants to add additional behavior to the transfer objects, he can extend one out of DTOBase :

class MyDTOBase extends DTOBase {
// added behavior
}

And this way they can add global behaviors like state management functionalities to all DTOs that they use.

Monday, April 24, 2006

Scala Hosts a Friendly Visitor

GOF tells us that the intent of the Visitor design pattern is to
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

The focus is on defining new operations, and not on allowing a flexible hierarchy of the elements themselves. In fact, the Consequences section of the Visitor pattern mentions that Visitor makes adding new operations easy and Adding new ConcreteElement classes is hard, since adding every new ConcreteElement forces a change in the Visitor interface and hence in all Visitor implementations. Thus the vanilla Visitor implementation in today's mostly used object oriented languages like Java and C++ violates the Open Closed Principle.

What's special in Scala ?

Scala offers three features which enable a Visitor implementation to have piecemeal growth. Both the visitor and the visited hierarchy can be enhanced incrementally resulting in flexible inheritance hierarchies for both of them.

The nuances of the Visitor implementation in Scala is part of the more general Expression Problem, which has been dscribed in the Scala context by Zenger and Odersky.

Let us review the above claim using an example. The following snippet illustrates a sample combination of the Visited and Visitor hierarchy. Here we have only one level of specialization for the Visited and the Visitor abstractions, along with the base contracts for each of them.

trait Base {

  trait Node { // Element base of the hierarchy
    def accept(v: visitor): unit;
  }

  // ConcreteElement specialization
  class File(name: String) extends Node {
    def accept(v: visitor): unit = v.visitFile(name);
  }

  type visitor <: Visitor;
  trait Visitor { // Visitor base of the hierarchy
    def visitFile(name: String): unit;
  }

  // ConcreteVisitor specialization
  trait PrintingVisitor requires visitor extends Visitor {
    def visitFile(name: String): unit =
    Console.println("printing file: " + name);
  }
}

Figure 1 - The Base

Let us see how the above implementation differs from the standard Java Visitor boilerplate. The main problem with the Java/C++ implementation is the fact that the visitor interface has to change with the addition of a ConcreteElement (the visited). This is where we violate the Open Closed Principle - we need to make invasive changes at the contract level, which forces a recursive change down the inheritance hierarchy for all concrete visitor implementations. The Scala implementation above addresses this problem by allowing us to abstract over the concrete visitor type. In order to keep the set of Visited classes open, the Abstract Type visitor is used. Every concrete implementation of Visitor interface such as PrintingVisitor above, implements its bound Visitor. And every Visited element uses the same abstract type visitor for the accept() methods. It is this magic combination of abstract type and mixin composition which allows us to enrich the dual hierarchies incrementally.

In the following sections we will look at how the Scala implementation allows a seamless adding of concrete members to the Visited as well as Visitor hierarchies.


Adding a ConcreteElement (the Visited hierarchy)

// data extension : add Link
trait BaseLink extends Base {

  type visitor <: Visitor;

  trait Visitor extends super.Visitor {
    def visitLink(subject: Node): unit;
  }

  class Link(subject: Node) extends Node {
    def accept(v: visitor): unit = v.visitLink(subject);
  }

  trait PrintingVisitor requires visitor
      extends super.PrintingVisitor
      with Visitor {
    def visitLink(subject: Node): unit =
      subject.accept(this);
  }
}

Figure 2 - Adding a ConcreteElement

Override the abstract type visitor with the extended Visitor trait and include the new visitLink() method - completely non-invasive, yet extensible! The concrete implementation of the new PrintingVisitor extends the trait from the superclass and compose with the extended Visitor trait using Scala mixin composition.

In the above, we claimed that the abstract type visitor allows us to abstract over the concrete visitor types. In the above method visitLink() of PrintingVisitor, the call to accept() has the argument this. But the type PrintingVisitor is not a subtype of the abstract visitor type visitor. The above implementation handles this by the statement requires visitor in the definition of the trait PrintingVisitor. This is called Self Type Annotation, which provides an alternative way of associating a class with an abstract type. The self type specified above is taken as the type of this within the class. Without this feature, the type of this is the usual type of the class itself. In the above implementation, the usage of the self type annotation ensures that the type of this, specified in the argument of accept() is of the abstract type visitor as demanded by the declaration of the Node trait.

Combining Independent Element Extensions

Similar to BaseLink extension above, we can have similar independent extensions in the Visited hierarchy. e.g. we can have a BaseDirectory trait which extends Base with Directory as another Node. I do not go into the details of this implementation, but it will be exactly along the same lines as BaseLink. The important part is the ability to combine independent Element extensions through composition. Scala's powerful modular mixin composition is the answer to all these as the following example demonstrates:

// compose all
trait BaseAll extends BaseDirectory with BaseLink {

  type visitor <: Visitor;
  trait Visitor extends super[BaseDirectory].Visitor
      with super[BaseLink].Visitor;

  trait PrintingVisitor requires visitor
      extends super[BaseDirectory].PrintingVisitor
      with super[BaseLink].PrintingVisitor
      with Visitor;
}

Figure 3 - Composing all Extensions

The abstraction above combines the two independent extensions through mixin composition. In case of such mixin composition, the Scala type system requires that abstract types have to be refined covariantly. Hence BaseAll has to redefine the bounds of the the abstract type visitor through explicit overriding, such that the bound of the new visitor is a subtype of both old bounds.

This is not all - we will see how adding new visitors in the hierarchy combines with the extensibility of the BaseAll trait, resulting in a complete implementation of the Visitor Design Pattern.


Adding a New Visitor to the Hierarchy

Adding new visitors is easy, as the pattern claims - every new operation added simply adds up to the Visitor hierarchy, implementing all the visitor interfaces.

// function extension
trait BaseExt extends BaseAll {
  class RemoveVisitor requires visitor extends Visitor {
    def visitFile(name: String): unit =
    Console.println("removing file: " + name);

  def visitDirectory(name: String): unit =
    Console.println("cannot remove directory: " + name);

  def visitLink(subject: Node): unit =
    subject.accept(this);
  }
}

Figure 4 - Extending the Visitor Interface


Compose Them All - The Grand Visitor

We now have the grand Visitor in place where we can add to Visited and Visitor hierarchies seamlessly ensuring piecemeal growth. The abstractions are open for extension but closed for invasive changes.

Here goes the final usage ..

object VisitorTest extends BaseExt with Application {
  type visitor = Visitor;

  val f = new File("foo.txt");
  val nodes = List(
    f,
    new Directory("bar"),
    new Link(f)
  );

  class PrintingVisitor extends super.PrintingVisitor;
  nodes.elements foreach { x => x.accept(new PrintingVisitor()); }

  class RemoveVisitor extends super.RemoveVisitor;
  nodes.elements foreach { x => x.accept(new RemoveVisitor()); }
}

Friday, April 21, 2006

Project Geometry

How do you ensure that the current Java project that you have been working on uses the correct exception hierarchy for the DAOs ? How do you identify the stamp of your organization when you look at the SVN check outs of a project ? How do you prevent reinventing the wheels of the maven script when you plan the build architecture of the project that you are supposed to manage ?

The answer to all of the above is to have a uniform Project Geometry for your organization. When I talk about the geometry, I mean only the software aspect of the project, the code that gets churned out by the software development team, the documentation artifacts that get generated in the process and the machinery that builds the code and deploys the binary to the desired target platform. The geometry ensures a uniformity not only in the look and feel of the project (the directory hierarchy, package structure, archetypes, build engine etc.), but also the innards of implementation which include the whole gamut from the design of the exception hierarchy down to the details of how the application interfaces with the external services layer. The following rumblings are some of my thoughts on what I mean when I talk about Project Geometry.

Software Reuse

In the article Four Dynamics for Bringing Use Back Into Software Reuse published in the Communications of the ACM, January 2006, Kevin C Desouza, Yukika Awazu and Amrit Tiwana identify three salient dynamics associated with the knowledge consumption lifecycle of a project - reuse, redesign and recode. They define
Reuse is the application of existing software artifacts as is; redesign is the act of altering existing software artifacts; and recoding is the discovery of new software artifacts through construction of software code or system designs.

In each of the above dynamics, there is an implicit assumption of pre-existence of software artifacts which finds place in the current lifecycle through a discovery process - either as-is or in a derived manifestation.

The question is : where from do we get these artifacts that can be reused ?

The Project Container

Every modern day IT organization who delivers software can have a Project Container, a meta-project which helps individual project teams to incubate new projects. The project container evangelizes the best practices for development, deployment and documentation and provides plug-ins and archetypes to kick-start a new project for the organization.

It should be as simple as 1-2-3 .. Let us consider a case study ..

For my organization, the build platform of choice for a Java based project is maven 2 and I should be able to generate a standard project skeleton structure from an archetype which is part of my project container. Here they go ..

  1. Download plugin for bootstrap from the project container repository

  2. Run maven install (mvn install ...)

  3. Setup project home

  4. Create archetype (mvn archetype:create -D... ...)


Boom .. we go .. my entire project hierarchy skeleton is ready with the corporate standard directory hierarchy, package naming conventions, documentation folders and (most importantly) a skeleton Project Object Model (POM) for my project. When I open up my IDE, I can find my prject already installed in the workspace! I can straightway start adding external dependencies to the pom.xml. Maven has really done wonders to the project engineering aspect through its concepts of archetypes, plugins and POMs. I can start defining my own project specific package hierarchy and write my own business logic.

My Project Structure

Any Java based project bootstrapped using the above project container of my organization bears the stamp of its identity. With its families of plug-ins and artifacts, the project container ensures a uniform geometry of all projects delivered from this place. It's really geometry in action - promoting reuse and uniformity of structure, thereby making life easier for all team members joining the project later in the lifecycle. Joel Spolsky talks about the Development Abstraction Layer as an illusion created by the management with its associated services which makes the programmer feel that a software company can be run only by writing code. In this context, the project container takes care of the engineering aspects of the project environment and presents to the programmer a feeling that the software that he delivers is only about writing the business logic. The other machineries like coding conventions (comes integrated with the IDE through container based checkstyles), build engine (again comes with the incubation process), documentation (maven based, comes free with the project container) and project portal (maven generated with container based customization) gets plugged in automatically as part of the bootstrapping process. The best thing is that the process is repeatable - every project based on a specific platform gets bootstrapped the same way with the same conventions replicated, resulting in a uniform project geometry.

Is This All ?

Actually project geometry is extensible to the limits you take it to. I can consider a standard infrastructure layer to be part of my project container for Java based projects. The exception hierarchy, standard utilities, a generic database layer, a generic messaging layer can all be part of the container.

But, what if I don't need'em all ?

You pay only for what you take. The project container repository gives you all options that it has to provide - pick and choose only the ones you need and set up dependencies in your POM. Remember, Maven 2 can handle transitive dependencies, one feature that we all have been crying for months.

The Sky is the Limit!

Taking it to the extremes - the project container can offer you options of implementation of some features if you base your code based on the container's contracts. This implies that the project container is not a mere engineering vehicle - it acts as a framework as well. Suppose in your Java application you need to have an Application Context for obvious reasons. You can design your application's context based upon the contracts exposed by your project container. And you can choose to select one of the many possible implementations during deployment - you can choose to use Spring's IoC container based context implementation or you can select the vanilla flat namespace based default implementation provided by the container itself. Whatever you do, you always honor the basic guideline, that of discovering from the project container and making it suitable for your use, and in the process maintaining the uniform geometry within your project.