Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

J2EE development frameworks

2005, Computer

IT SY STEM S P ER SP EC TI VE S J2EE Development Frameworks • Successful open source frameworks are better tested than inhouse code. • Frameworks usually become popular only if they have something to offer. In-house frameworks are often mandated, while a J2EE project is likely to adopt an open source framework only if it delivers clear benefits. Rod Johnson, Interface21 J ava 2 Enterprise Edition has excelled at standardizing many important middleware concepts. For example, J2EE provides a standard interface for distributed transaction management, directory services, and messaging. In addition, Java 2 Standard Edition (J2SE), which underpins J2EE, provides a largely successful standard for Java interaction with relational databases. However, as the “J2EE’s Lack of Application Programming Support” sidebar explains, the platform has failed to deliver a satisfactory application programming model. Sun Microsystems and the large application server vendors have traditionally responded to this problem by advocating development tools as a way to hide J2EE’s complexity. However, tools for managing J2EE artifacts aren’t nearly as good as tools for working with the Java language, with their sophisticated refactoring capabilities, and J2EE tool support is generally inferior to that of the Microsoft .NET platform. Many J2EE tools are themselves complex, as is the code they generate. Many in the open source community, especially smaller vendors, have chosen the alternative of developing frameworks designed to simplify the experience of building J2EE applications. Popular frameworks such as Struts, Hibernate, and the Spring Framework play an important role in many of today’s J2EE development projects. WHY USE A FRAMEWORK? A software framework is a set of classes that make up a reusable design Despite some uncertainty, open source frameworks are increasingly important to J2EE development. for an application or, more commonly, one tier of an application. Whereas application code calls a class library to perform services, a framework calls application code and thus manages the flow of control. This is often referred to as the Hollywood principle: “Don’t call us, we’ll call you.” The application developer writes code that the framework will then call at runtime. Designing a framework for use in a wide variety of unknown contexts is challenging. However, the framework approach is well adapted to the complexities of J2EE development because it can provide a simple, easy-to-use model for application programmers. Using a well-designed open source framework offers many advantages: • With a good framework, developers write only the code they need to write; they don’t get bogged down working directly with lowlevel infrastructure APIs. This is the key value proposition. • A well-designed framework can provide structure and consistency to an application. The structure will be clear to additional developers joining the project. • An easy-to-follow framework can promote best practice through examples and documentation. J2EE itself defines several frameworks. For example, an Enterprise JavaBeans (EJB) container or Servlet engine relies on the Hollywood principle, with the J2EE runtime instantiating and invoking managed objects. Open source Web application frameworks such as Struts add their own framework over the standard Servlet framework. The emphasis here is on frameworks above J2EE, which provide a simpler programming model or other benefits. OPEN SOURCE FRAMEWORKS EMERGE Most large J2EE projects have traditionally used in-house frameworks to hide the platform’s complexity. Only recently has a consensus emerged about the generic problems that require a generic solution, and around particular frameworks that provide good generic solutions. There is now a clear trend for frameworks to “standardize” more of the infrastructure that formerly was developed on a per-project basis. One reason for J2EE frameworks’ sudden popularity is the platform’s increased maturity. Developers now recognize areas in which the standard APIs are deficient and know from experience how difficult it is to write a good framework to fill the gap. In addition, many high-quality frameworks are January 2005 107 IT Systems Perspectives J2EE’s Lack of Application Programming Support Despite its success in standardizing interaction with many low-level system services, J2EE has largely failed to provide a satisfactory application programming model. For example, Java Transaction API, Java Naming and Directory Interface, and Java Message Service are designed to accommodate middleware vendors; they impose too much complexity on code to be directly used by application developers. Similarly, Java Database Connectivity effectively shields J2SE and J2EE application developers from the proprietary wire protocols used to communicate to databases, and it does a fairly good job making Java code portable between databases. However, JDBC provides a cumbersome programming model if used directly, with rich potential for errors—especially in exception handling and managing resources such as connections. J2EE’s major effort to provide a standard programming model is Enterprise JavaBeans, a component model designed to let developers tap into standard J2EE services such as transaction management, remoting, and thread management. Unfortunately, EJB has proven disappointing in practice—among other problems, it places constraints on the use of inheritance and complicates unit testing. As with other J2EE APIs, productivity and ease of development and testing don’t seem to have figured highly as design criteria. now available that offer outstanding documentation and the support of a focused development team, without imposing licensing fees. Struts The trend toward open source frameworks began with Web applications. In 1999-2000, developers realized the deficiencies of the Java Server Pages “Model 1” approach, in which JSP templates handled incoming requests as well as static template data. This meant that JSPs often contained both business logic and complex HTML or other markup. With no standard framework in place or J2EE specification support, developers responded with their own Front Controller implementations. These moved business logic to Java classes, thereby eliminating the need to maintain such hybrid artifacts. The Front Controller pattern is often referred to as Web MVC after the classic Model View Controller architecture pattern that is common to GUI development in object-oriented languages. (The name is somewhat misleading in that Web MVC views must pull information from the model, whereas in 108 Computer classic MVC, the model pushes events to views.) Initial Front Controller implementations varied greatly in quality. The Apache Software Foundation’s release of Struts (http://struts.apache.org) in 2001-2002 changed all this. While not an ideal Web MVC framework, Struts worked well enough to quickly become the de facto standard. Struts demonstrated all the benefits of open source frameworks such as ease of recruiting personnel familiar with the structure it imposed. By late 2002, it was the natural choice for most J2EE Web applications, and every serious J2EE Web developer was familiar with it. The near-universal adoption of Struts commoditized an important chunk of the J2EE architectural stack. Even conservative organizations accepted its use in a prominent part of their software infrastructure and agreed to the Apache license’s terms. Hibernate The next domino to fall was persistence. J2EE “out of the box” provided two means for accessing persistent stores—most often, relational databases: JDBC, the J2SE standard API for relational database management system access; and entity beans, an EJB component type dedicated to modeling a persistent entity. JDBC’s error-prone programming model inhibited object-oriented design by forcing developers to work with relational concepts in Java code. Entity beans, despite hype from Sun and major J2EE vendors, likewise proved to be cumbersome: Initially, the technology was severely underspecified, not even taking into account management of relationships between persistent objects; it made applications difficult to test; and it offered an inadequate query language. By 2003, developers largely ignored entity beans despite enhancements in EJB 2.0 and 2.1. Early efforts. Solutions to the persistence problem came in the form of object-relational mapping (ORM), which provides transparent persistence for plain old Java objects (POJO), a concept described in the sidebar, “The Noninvasive Framework: Power to the POJO.” Though not unique to Java, ORM is especially popular in the Java community—compared, for example, to .NET developers, who seem to regard it with suspicion. Commercial ORM tools such as Oracle’s TopLink (www.oracle.com/ technology/products/ias/toplink) were well established by the late 1990s, but only a minority of projects used them because they were expensive, complex, and appeared to conflict with the Sunsanctioned entity bean standard. Nevertheless, they usually achieved better results in practice than JDBC or entity beans, thus proving the case for POJO persistence. Java Data Objects, which appeared as a Java Community Process (www. jcp.org) specification in 2001, offered generic POJO persistence to any persistent store (although implementations typically provided their best support for relational databases). However, Sun’s lukewarm attitude toward JDO, coupled with J2EE vendors’ lack of inter- The Noninvasive Framework: Power to the POJO Experience shows that developers don’t like frameworks that impose excessive constraints on their code. Three novel capabilities of emerging J2EE frameworks that can help developers achieve the goal of a POJO-centric application are transparent persistence, inversion of control, and aspectoriented programming. Transparent persistence This capability refers to the persistence of POJOs to durable stores—typically, relational databases—without the objects needing to make significant object-orientation concessions. It bridges the object-relational impedance mismatch with a framework responsible for mapping persistent objects to rows in a relational database management system, generating all the necessary Structured Query Language code to retrieve and store objects. ORM tools use techniques such as reflection, dynamic byte code generation, or byte code enhancement in a postprocessing step to perform this mapping at runtime. Transparent persistence frees domain objects from the responsibility of managing their persistent representation, enabling them to contain business logic where appropriate, without mixing that with persistence operations. It can also greatly increase productivity by eliminating the need to write verbose and often error-prone persistence code. Transparent persistence is a goal rather than a reality, but the best ORM solutions come close to achieving it. Inversion of control A POJO model can be applied to business services through IoC containers. These let business objects be configured at runtime, and enjoy declarative services such as automatic transaction management. Inversion of control is a widely used term that in this case refers to a model in which the framework instantiates application objects and configures them for use. Dependency injection is a pure Java type of IoC that does est in POJO persistence at that time, prevented the technology from achieving popularity. Hibernate arrives. Radical change came in 2002 for two reasons. First was widespread realization that entity beans had failed in practice, and that developers should ignore that part of the J2EE specifications. By retarding rather than advancing the progress of ORM in Java, entity beans remain a prime example of how poor specifications can stifle devel- not depend on framework APIs and thus can be applied to objects that aren’t aware of—or may have been written without knowledge of—the framework. Configuration is via JavaBean properties (setter injection) or constructor arguments (constructor injection). This means that application code doesn’t implement any framework interfaces; the framework uses reflection to configure it. The framework injects dependencies such as collaborating objects or configuration parameters, without application classes needing to perform explicit lookup—as, for example, in the traditional JNDI-based approach to J2EE configuration. Dependency injection is a simple, but surprisingly powerful, concept. Because the framework is responsible for resolving dependencies on collaborating objects, it can introduce a range of value-adds such as indirection to support hot swapping and codeless generation of proxies that represent remote services. Aspect-oriented programming Dependency injection goes a long way toward delivering a POJO application model but fails to address some important requirements, such as the ability to apply declarative transaction management—security checking, custom caching, auditing, and so on—to selected methods. Traditional solutions to this problem all have substantial disadvantages. Using boilerplate code—for example, to start and commit or roll back a transaction—results in the same code being used in multiple methods. In addition, design patterns such as the Decorator end up with cut-and-paste code. And objects can only benefit special-purpose frameworks such as EJB, which provide a fixed set of services, by conforming to framework APIs and implicit contracts. The Spring Framework provides a proxy-based AOP solution that complements dependency injection. AspectJ, AspectWerkz, and other AOP technologies are more ambitious, enabling modification of class byte code for more powerful weaving of aspects into an object model. opment of superior technologies. The second factor was the arrival of Hibernate (www.hibernate.org), the first popular, fully featured open source ORM solution. Hibernate offered fewer features than TopLink but delivered a robust implementation of the most desirable ones, and its focused development team aggressively sought improvements. Hibernate wasn’t particularly innovative, building on the extensive understanding of ORM, but it offered a more intuitive programming model than existing competitors and removed at one stroke the cost and ease-of-use barriers to ORM. Around the same time, new commercial products offered highly efficient implementations of the JDO specification that targeted relational databases, giving developers a rich choice. Meanwhile, TopLink remained a good option, with its license becoming friendlier to developers. January 2005 109 IT Systems Perspectives ORM triumphs. Together, all these factors converged to make ORM the norm rather than the exception by 20032004. Although some projects still built their own persistence frameworks, the existence of Hibernate, TopLink, and leading JDO implementations made this extremely difficult undertaking unnecessary and indefensible. Another part of the application stack was now within the domain of popular frameworks, yet large gaps remained. For example, a typical Web application using Struts and Hibernate still lacked framework support for business logic. Although the J2EE specifications address some of these issues, primarily through EJB, they don’t provide an adequate application programming model. codehaus.org), which combines the PicoContainer IoC container with services. Collectively, these products are referred to as lightweight containers to distinguish them from traditional J2EE approaches. By decoupling a POJO model from J2EE APIs, which are hard to stub at test time, lightweight containers greatly simplify unit testing. It’s possible to unit test in a plain JUnit environment, without any need to deploy code to an application server or to simulate an application server environment. Given the increased—and deserved—popularity of test-driven development, this has been a major factor in lightweight frameworks’ popularity. WHAT’S NEXT? Spring J2EE frameworks have inexorably moved into application frameworks, which aim to provide consistent programming in all tiers and thereby integrate the application stack. The Spring Framework (www.springframework. org) is the dominant product in this space, with adoption comparable to that of Hibernate. Spring essentially combines inversion of control (IoC) and aspect-oriented programming (AOP)—both described in the sidebar, “The Noninvasive Framework: Power to the POJO”—with a service abstraction, to provide a programming model in which application code is implemented in POJOs that are largely decoupled from the J2EE environment (and thus reusable in various environments). Spring also provides an alternative to EJB in many applications—for example, delivering declarative transaction management to any POJO. The Spring approach has proven to deliver excellent results in many kinds of projects, from small Web applications to large enterprise applications. Other products in the same space include HiveMind (http://jakarta. apache.org/hivemind), which is conceptually similar to Spring but has a somewhat different take on IoC, and NanoContainer (http://nanocontainer. 110 Computer Growing recognition and use of J2EE development frameworks is measurably reducing cost in many projects, as well as delivering better speed to market and higher maintainability. Today’s best frameworks offer excellent quality, solid documentation, and numerous books and articles to support their use. Nevertheless, two areas in particular seem set for uncertainty in the J2EE space: the conflict between J2EE “standards” and open source innovation, and the growing importance of AOP. The open source versus standards conflict looms in two areas. In the presentation tier, JavaServer Faces (JSF), backed by Sun and some of the largest vendors, competes with entrenched open source solutions such as Struts. In the middle tier, EJB 3.0 offers a dependency injection capability reminiscent of a subset of Spring’s capabilities, mixed with liberal use of J2SE 5.0 annotations. In both areas, innovation has traditionally come from open source rather than specifications. However, JSF is somewhat indebted to ASP.NET, while the open source Tapestry project (http:// jakarta.apache.org/tapestry)—a mature implementation of many of the same concepts—owes much to Apple’s commercial WebObjects. Likewise, EJB 3.0 seems to be attempting to standardize dependency injection, though it’s unclear what benefit this brings—especially if it results in the loss of important features, which seems inevitable. EJB 3.0 also attempts a new departure in entering the application programming space: an area in which the J2EE specifications haven’t shone to date. Meanwhile, AOP’s importance is steadily increasing within the J2EE community. While adoption isn’t yet widespread, certain uses of AOP, such as declarative transaction management, are already popular. Solutions including Spring and dynaop (http://dynaop. dev.java.net), which offer what might be called “AOP with training wheels,” help to increase awareness of AOP. Fullblown AOP technologies such as AspectJ will likely experience wider adoption in the next few years as well. Significantly, the Java Community Process shows no sign of any move to standardize AOP, although JBoss (www.jboss.com)—which is overtly committed to working through the JCP with the EJB 3.0 specification—is vigorously pursuing proprietary AOP technology. he next-generation J2EE specifications as a whole are embracing a simpler, POJO programming model, similar to that already offered by combinations such as Spring and Hibernate. J2EE developers are sure to benefit from recent trends, which are driven more by practical experience than by marketing hype. This is a welcome change from the platform’s early days, when results often failed to live up to the promise held out by vendors. ■ T Rod Johnson is CEO of Interface21, a J2EE consultancy based in London. Contact him at rod@interface21.com. Editor: Richard G. Mathieu, Dept. of Decision Sciences and MIS, St. Louis University, St. Louis, MO; mathieur@slu.edu