Thursday, January 31, 2008

JMX and Introspection Versus Reflection

The difference between Java introspection and reflection is sometimes confusing and the two terms are often used interchangeably. This is not really a problem in most cases from a practical perspective, but there are cases where it does matter and the difference is interesting to note from an intellectual point of view.

Java SE 6's JMX Platform Server provides both a ReflectionException and an IntrospectionException. Both of these JMX-provided exception classes extend the checked JMX-provider exception JMException. The java.management.ReflectionException extends javax.management.JMException directly while javax.management.IntrospectionException extends javax.management.OperationsException which extends JMException.

There are a few good resources on the differences between introspection and reflection, though for the purposes of most of us writing JMX-enabled code, these are not usually significant.

In Java Reference Guide: RXML, Stephen Haines provides a nice overview of Reflection versus Introspection.

The Java Tutorials Reflection API Trail talks about reflection (including situations in which it is not appropriate) and the Java Tutorials JavaBeans Concepts Lesson also talks about introspection on JavaBeans and the use of "core reflection" to do this.

Dr. Ira Forman and Nate Forman provide a nice article called Java Reflection in Action (same title as their book) that provides an interesting description of Java reflection and introspection. They refer to reflection as "introspection followed by behavior change." This best fits my understanding of the reflection and introspection and seems to align well with the Javadoc descriptions for the JMX classes cited above.

Wednesday, January 30, 2008

Determining Your MBeanServer's MBeanServerId

A common need when using JMX is to know your particular JMX MBeanServer's MBeanServerId (AKA "Agent ID"). The Agent ID is most easily obtained by executing the following code against an MBeanServer.


/**
* Get the MBeanServerId of Agent ID for the provided MBeanServer.
*
* @param aMBeanServer MBeanServer whose Server ID/Agent ID is desired.
* @return MBeanServerId/Agent ID of provided MBeanServer.
*/
public String getMBeanServerId(final MBeanServer aMBeanServer)
{
String serverId = null;
final String SERVER_DELEGATE = "JMImplementation:type=MBeanServerDelegate";
final String MBEAN_SERVER_ID_KEY = "MBeanServerId";
try
{
ObjectName delegateObjName = new ObjectName(SERVER_DELEGATE);
serverId = (String) aMBeanServer.getAttribute( delegateObjName,
MBEAN_SERVER_ID_KEY );

}
catch (MalformedObjectNameException malformedObjectNameException)
{
System.err.println( "Problems constructing MBean ObjectName: "
+ malformedObjectNameException.getMessage() );
}
catch (AttributeNotFoundException noMatchingAttrException)
{
System.err.println( "Unable to find attribute " + MBEAN_SERVER_ID_KEY
+ " in MBean " + SERVER_DELEGATE + ": "
+ noMatchingAttrException );
}
catch (MBeanException mBeanException)
{
System.err.println( "Exception thrown by MBean's (" + SERVER_DELEGATE
+ "'s " + MBEAN_SERVER_ID_KEY + ") getter: "
+ mBeanException.getMessage() );
}
catch (ReflectionException reflectionException)
{
System.err.println( "Exception thrown by MBean's (" + SERVER_DELEGATE
+ "'s " + MBEAN_SERVER_ID_KEY + ") setter: "
+ reflectionException.getMessage() );
}
catch (InstanceNotFoundException noMBeanInstance)
{
System.err.println( "No instance of MBean " + SERVER_DELEGATE
+ " found in MBeanServer: "
+ noMBeanInstance.getMessage() );
}
return serverId;
}


The MBeanServer passed into the method shown above could be a newly created one using one of the MBeanServerFactory.createMBeanServer methods or could be an MBeanServer obtained via a call to ManagementFactory.getPlatformMBeanServer(). This method could be added to any JMX MBeanServer-hosted code to determine the agent ID for that JMX Server.

There are really only two lines of "substantial" code in the example above and they are in bold. Much of the rest of the code is set-up code and exception handling. The exceptions caught in the code above are all checked exceptions, but the code would have been shorter if I had declared the method to simply throw these exceptions or if I had simply caught a general Exception. I caught each individual checked exception intentionally to be more illustrative of what exceptions could get thrown and why they might be thrown.

If the above code is run within code like this:


System.out.println(
"MBeanServerId: "
+ me.getMBeanServerId( ManagementFactory.getPlatformMBeanServer() ));


the output shown (when run on a machine named "HOMER" with the Java SE 6 JMX Platform Server/Reference Implementation) is:

MBeanServerId: HOMER_1201751774839

The long numeral after HOMER_ is a timestamp for the MBean server and so will almost certainly differ for your MBean server.

Tuesday, January 29, 2008

JMX Specifications Optional Pieces and Java SE 6 JMX Platform Server

In a previous blog entry, I wrote about how the Java SE 6 JMX platform implementation also represents the JMX API 1.4 and JMX Remote API 1.4 reference implementations. However, many optional features of the two JMX specifications are not included with the Java SE 6 JMX Platform Server. In the past, these were acquired from the previously separate JMX reference implementation. Now, with the Java SE 6 JMX platform server also being the reference implementation, these optional pieces are often obtained elsewhere and that is the subject of this blog entry.

On the SDN JMX forum thread HtmlAdaptorServer Available with Java 6 JMX 1.4 Reference Implementation?, Daniel Fuchs pointed out that the optional HTML/HTTP adapter formerly available with the JMX 1.2 reference implementation is now available as part of the Project OpenDMK.

The HtmlAdaptorServer is not the only optional JMX feature included with Project OpenDMK. Another useful feature is OpenDMK's support for the JMXMP Connector (implemented in jmxremote_optional.jar). As documented in the Java API documentation for package javax.management.remote, the JMXMP Connector is an optional part of the JMX Remote API specification and is thus not included in the Java SE 6 JMX offerings.

An an alternate JMX implementation, MX4J also offers some of the optional features in the Java Management Extensions specifications.

Monday, January 28, 2008

Making jps and jconsole Work with Java SE 6 on Windows Vista

I recently discovered that the JConsole tool stopped automatically detecting local processes in the JVM in which it was running. I knew that, at the very least, it should show itself in the connection window. The issue was resolved based on the useful information provided by Luis-Miguel Alventosa in the SDN JMX forum thread Cannot see local process list in JConsole in of JDK 6. This blog entry summarizes the recommended steps and displays how the problem was fixed. Note that another forum entry that references the forum entry linked to above is JMX - jconsole connects to local vm only if given PID.

The problem with JConsole was tied to jps as well. This was especially problematic because I could always use JConsole to connect to a particular PID, but I wanted to use jps to help me find that PID. I blogged about the usefulness of jps in this blog entry.

I followed the instructions in the JMX - Cannot see local process list in JConsole of JDK 6. My first screen shot shows the results of running jps. Note that there is no PID shown even though at least jps itself should be shown.



The next screen shot shows that JConsole cannot find any local instrumented Java applications even though it should, at the very least, find itself.



As the above screen shot (two above) demonstrates, I used the echo %TMP% command to determine what the TMP environment variable was set to. I navigated to that directory and went into the hsperfdata_Dustin folder (shown in the next screen shot).



I don't show it here, but I went into the Vista properties for the hsperfdata_Dustin directory and enabled permissions on that directory (they were ALL off). The next two screen shots demonstrate that JConsole and jps now worked for me again.





JConsole and jps weren't working simply because Vista wasn't letting me change files in that %TMP%/hsperfdata_Dustin directory. Once I opened up permissions on that directory, both jps and jconsole worked as expected.

UPDATE (25 November 2008): The blog entry JMX Examples Don't Work Under Windows discusses how the characters used in the TMP environment variable can adversely affect the ability of JConsole to "see" managed applications.

InetAddress Example

The Java class java.net.InetAddress is a useful class that has been available since JDK 1.0. It has been updated in newer versions of Java, but the core class has been around since JDK 1.0.

Here is a simple code example that demonstrates use of this class and the handy information it provides.

package net.sample;

import java.net.InetAddress;
//import java.net.UnknownHostException;
/**
 * This class provides a very simple example of using the java.net.InetAddress
 * class.  It demonstrates methods on the java.net.InetAddress class such as
 * getLocalHost(), getHostName(), getHostAddress(), and getAddress().
 * 
 * In addition this class demonstrates the need to catch the checked exception
 * java.net.UnknownHostException (or an exception above it such as Exception).
 */
public class INetAddressExample
{
   /**
    * Run simple demonstration of the usefulness of the java.net.InetAddress
    * class.
    *
    * @param aArgs The command line arguments; none expected.
    */
   public static void main(final String[] aArgs)
   {
      InetAddress localhost = null;
      try
      {
         localhost = InetAddress.getLocalHost();
         System.out.println( "InetAddress: " + localhost );
         System.out.println( "\ttoString: " + localhost.toString() );
         System.out.println(  "\tCanonicalHostName: "
                            + localhost.getCanonicalHostName() );
         System.out.println( "\tHost Name: " + localhost.getHostName() );
         System.out.println( "\tHost Address: " + localhost.getHostAddress() );
         System.out.println( "\tHost Bytes: " + localhost.getAddress() );
         System.out.println( "\tHash Code: " + localhost.hashCode() );

         // We will now force an UnknownHostException to be thrown.
         InetAddress nonExistent = InetAddress.getByName("nada");
         System.out.println( "Host is: " + nonExistent );  // won't get here!
      }
      catch (/*UnknownHost*/Exception unknownHostException) // checked exception
      {
         System.err.println(  "D'oh!! Unknown Host ("
                            + unknownHostException.getClass().toString()
                            + "): " + unknownHostException.getMessage() );
      }
   }
}

An adapted version of the class shown above is now available on GitHub.

The output from running this is shown in the following screen shot:

I intentionally commented out the UnknownHost portion of the exception to capture a general exception. However, you can uncomment this out along with the import statement for java.net.UnknownHostException and the code will work as well. Either way the exception must be caught because UnknownHostException is a checked exception.

Saturday, January 26, 2008

Motivations and Explanations for Poor Software Decisions

In a previous blog entry called What's In a Name, I wrote about names of concepts in software development that have likely aided in the adoption of the underlying concept. In that blog entry, I used examples like POJO and Ajax to illustrate the point. I also mentioned vendor-driven architecture and resume-driven development as two other examples. These latter two examples describe influences of our software design and development decisions and that is the focus of this blog entry.

In this entry, I want to highlight some of the other common influences on our software development decisions. Each of these influences has a pithy name associated with it in this entry. I did not come up with these names and will try to link to sources that cover these names in more detail, but I do intend to add why I like each name and how it fits.

Because this is a relatively lengthy blog entry, I am listing the titles of each idea here. Note that this entry does not talk about obvious negative effects on software decisions such as insufficient funding, insufficient schedule time, unreasonable management expectations, or even unreasonable customer expectations (the customer is always "right" if they're paying). I am also not talking in this entry about failures due solely to inexperience or lack of skill. Rather, I am talking about what types of motivations and explanations we can find to explain why even bright and talented software developers sometimes make poor decisions with significant negative consequences.

The specific items I will focus on in this entry are:
* Resume-Driven Development
* Magpie Effect
* Vendor-Driven Architecture
* Not Invented Here Syndrome
* Copy-and-Paste Programming
* Lemming Effect
* The Emperor's New Clothes Syndrome
* Maslow's Hammer
* Can't See the Forest for the Trees


Resume-Driven Development

The term resume-driven development refers to development decisions influenced by how the experience will benefit one's resume or, more generally, one's future software development career. Shahid N. Shah covers this concept in his blog entry Resume Driven Development (RDD) [19 January 200] as does Luke Hohmann in his interview with Bill Venners (29 March 2004). Justice Gray also includes coverage of resume driven development in his entry New development methodologies for the 21st century (22 June 2007). This last entry is worth reading for some alternate types of development he cites such as "Cut and Paste Driven Development," "Meeting Driven Development," "Meeting Driven Development," and "Masterpiece Driven Development."

Magpie Effect

Jeff Atwood's blog entry on The Mapgie Developer (6 January 2008) helped provide another nifty name to describe another motivational characteristic present in many software development efforts. In this entry, he likens software developers to magpies because both (software developers and magpies) are typically very bright, but are sometimes distracted from more important things and ideas by new and shiny things and ideas.

The magpie effect (7 January 2008) is similar to resume-driven development in many ways because both are often related to "new" and "exciting" technologies and languages. However, the magpie effect seems less selfish than resume-driven development. While resume-driven development is largely based on selfish interest in padding one's resume, the magpie effect describes a less intentional natural (and often healthy) curiosity in things that are new. I want developers on my team to be inquisitive and always seeking to learn new things and better themselves. However, to avoid the magpie effect, I also want them to learn how to briefly investigate new things and only spend significant time on truly useful things. Also, I don't want my development team being distracted by new things that aren't necessarily any better than what I've already got except for the "newness" of it.

Vendor-Driven Architecture

Also referred to as "Markitecture" (marketing architecture), this concept references architectures and designs based on vendor stiff arming or other strong selling tactics. This is often a result of vendor promises just short of world peace and the end of world hunger. Decisions largely influenced by vendor hype and/or sales pressure often lead to great disappointment when the down and dirty details are much more difficult to manage on a real application with real users than in a little "Hello World!" Tinkertoy demonstration.

Several people have written about vendor-driven architecture. David Linthicum wrote an article on avoiding vendor-driven SOA architectures (9 November 2007) and Arctec Group has provided this interesting and slightly different perspective on vendor-driven architecture (17 February 2005).

Not Invented Here Syndrome

While we don't want to let vendor-driven architecture drive us into poor solutions, we can go too far in trying to do everything ourselves and miss out on the collective experience of many others. Whether the product be commercial or open source, has licensing fees or is freely available, or is large or small, we can benefit from not reinventing the wheel. Some developers think that they can also do something better than anyone else. They may be unwilling to reuse code from anyone even in their own organization. This attitude is often referred to as the Not Invented Here Syndrome.

This syndrome is often manifest by the developer who finds one minor disadvantage in someone else's product and thinks he or she needs to create their own alternative without the disadvantage. In many cases, this results in something with far more significant problems than the product being replaced. Even when the replacement is equal to or slightly better than the already available solution, it often comes at great cost to the project. Often, Not Invented Here Syndrome is a result of developers having inflated opinions of their own work and overly critical opinions of others' work. However, there are also times when this occurs simply because developers do not spend appropriate time researching available offerings.

Michael Nash's Overcoming 'Not Invented Here' Syndrome summarizes this syndrome and some of its costs. Most people understand that there are times when something should be done because great customization is needed or a particularly important characteristic is not emphasized in the currently available offerings. Joel Spolsky has written In Defense of Not-Invented-Here Syndrome (14 October 2001) and emphasizes that core business logic often probably should be invented here. I also like SourceMaking's Cut-And-Paste Programming anti-pattern entry (see also their entry on Reinvent the Wheel). Justice Gray's New Development Methodologies for the 21st Century (cited earlier as well, 22 June 2007) also demonstrates that Cut and Paste Driven Development is the opposite (and equally negative) extreme to the Not Invented Here syndrome.

Perhaps one of the best examples of avoiding the Not Invented Here Syndrome is the Spring Framework. From the beginning, the key participants behind Spring have followed a philosophy of not recreating portions of their framework that were already satisfactorily covered by other available open source products. This is very evident when you download Spring with its dependencies (such as spring-framework-2.5.1-with-dependencies.zip) and look at what those dependencies are.

Copy-and-Paste Programming

I covered Copy and Paste Programming already in the Not Invented Here section above. While it is best to not reinvent the wheel and to make use of better tested frameworks and components when they will take care of the job, a software developer ultimately must (and hopefully wants) to write his or her own code for certain situations. Because the same developers who copy-and-paste the code will likely maintain the code, it is important for the developers to understand "their" code and most copy-and-paste enthusiasts don't take the time to truly understand code they did not write themselves. We should shy away from writing our own frameworks and libraries when sufficiently functional ones exist with a broad user community and its associated testing and support, but likewise we should be willing to write code of our own when it is needed (which is still fairly often in many cases).

Another bad form of copy and paste programming is outlined by James Carr in Rant: Copy and Paste Programming. Carr points out that lazy developers will sometimes copy-and-paste their own code. While the code may be understood by the developer in this case, it is a very poor form of "reuse" because of the CS 101 identified problems of maintaining the same code base in multiple locations.

Whether copy-and-paste is the opposite of not invented here (copying everything from other sources found via Google, other search engines, or books) or the copy-and-paste is copying one's own code (it is invented here), it almost never is a good idea in the long run. It is even dangerous in prototypes because they often morph into production applications.

I remember a representative of a major IDE vendor years ago bragging about how her company's IDE supported reuse because it made copying-and-pasting so easy. My first thought was the obvious "That's not real reuse, or at least not effective reuse" and that was quickly followed by the thought that even if that was good (which it isn't), it was nothing new compared to CTRL-C/CTRL-V.

Lemming Effect

The Lemming Effect (23 November 2007) is a reference to an almost instinctual desire in software developers to do what everyone else is doing. For instance, an early EJB adopter may have have thought to himself or herself, "This is unnecessarily complex and I don't even see the point of using this." However, he or she may have then continued to be inundated with articles, books, bulletin boards, and forums (not so much blogs in those early EJB days) talking about the virtues of EJB and it would be easy for that developer to doubt his or her own experience and just go with the crowd.

The Emperor's New Clothes Syndrome

This is similar to the Lemming Effect and often accompanies the Lemming Effect. However, this more specifically focuses on pressures to adopt a new concept or technology because one or more "experts" (collectively forming the Emperor) advocates the new concept or technology vociferously. If a respected expert is pushing the idea, it is easy for those of us who don't feel so expert in that area to believe the expert's words even over our own contrary experience. There may be many other developers who feel this way, but no one seems to come out and say so.

The Lemming Effect and the Emperor's New Clothes Syndrome often go together and that is a particularly dangerous combination. It takes an extremely confident developer with extremely trusting management and clients to stand up to the peer pressure of the other lemmings and to at the same time stand up to the authority of the "experts."

Every major software development platform has its own examples of The Emperor's New Clothes syndrome. Harshad Oak points this out for the Java world in Java and the Emperors New Clothes (10 May 2006). Charles Cooper made observations of the Emperor's New Clothes related to .NET's earlier days in .Net and the Emperor's New Clothes.

Maslow's Hammer

Maslow's Hammer is the well-known concept that we in the software development community have also known as the Golden Hammer Syndrome.

The idea here is that once a developer learns something new and usually useful in their first application of it, that developer is likely to try to make that same approach work for everything he or she encounters after that. For example, a Java developer may think that everything should be written in Java even when the problem isn't Java-friendly. Some close-to-home examples in my own young development career included the desire to use object-oriented implementation inheritance far more often than I should have in my early days of object-oriented design and then later an overuse, misuse, and abuse of design patterns. It is very easy to see how these have their strengths, but then let them get out of control trying to apply them to just about anything. I think the Singleton design pattern is especially overused and abused in this manner.

It is not surprising that we want to use things that have worked well for us before. In fact, this is often a good thing. However, we need to realize why these approaches worked for us so well before and then apply the approaches to problems with the same needs. Applying the right solution to the wrong problem just won't work. No single technology, framework, approach, pattern, or programming language is best for all situations. When we start bending the problem requirements to match our implementation choice, we should see this as a red flag warning of a potential Maslow's Hammer situation.

Can't See the Forest for the Trees

The expression "Can't see the forest for the trees" is usually used to signify that someone is missing the bigger picture because of his or her focus on much smaller and usually less important details. In software development, this is most commonly manifest as a disproportionate focus on a single characteristic (or "ility") at the expense of other just-as-important (or even more important) "ilities."

In an ideal world, our software would have all the desirable characteristics. It would have characteristics such as flexibility, maintainability, extensibility, simplicity, scalability, reliability,testability, and readability in addition to high performance and other positive characteristics. In the real world, however, we often have to make trade-offs between these characteristics or at least consider all of them in any design decisions. It is all too easy to get so focused on one of these positive characteristics that we neglect the others or neglect the overall system needs.

An example of missing the forest for the trees is such a strong focus on making the software so flexible that it might be easily adapted in case it might so happen that one day years from now someone will need that flexibility. Meanwhile, our current development staff and maintainers must deal with all of the complexity that comes with this flexibility and we may never need to realize any of the benefits of that complexity anyway.

It is becoming commonly accepted in software development that we should not focus on performance first (except for the small percentage of cases where performance is known to be the most important issue). Instead, increasing consensus is that we should strive for other positive characteristics (especially maintainability) and then make improvements for performance as needed. This is not to say that there aren't cases for performance-driven development, but rather is to say that there is no reason to sacrifice code readability and maintainability for performance improvements that might be gleaned from obscure code or tricky design.

In the end, it is not so much a question of whether performance is more important or maintainability is more important. Rather, it is a question of which combination of positive characteristics is most necessary and desirable for our application. We should be prepared to make the overall system best for our clients without regard for a single "ility" unless that single "ility" is overwhelmingly the desired "ility" in our client's case.




UPDATE (9 August 2008): An interesting look at some different (or same but from a more cynical perspective) software development motivations is available at Madconomist.com Wrong Number and is actually a reposting of the original version on the Berkun Blog.

Friday, January 25, 2008

Collection of JMX Best Practices Articles

The following links are to various JMX-related articles on Java Management Extensions (JMX) best practices.

JMX Best Practices
http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/best-practices.jsp
* Sun's collection of JMX best practices.

Apply JMX Best Practices
http://javapro.texterity.com/javapro/200501/?pg=14
(Other links: http://216.104.242.210/javapro/2005_01/magazine/features/cpeltz/, http://www.ftponline.com/javapro/2005_01/magazine/features/cpeltz/, http://evolutionnext.com/blog/2005/10/06/1128611173948.html)

Best Practices and Design Patterns for JMX
http://conferences.codegear.com/article/32535

Making Optimal Use of JMX in Custom Application Monitoring Systems: Some Best Practices and Recommendations
http://jdj.sys-con.com/read/478333_2.htm

Design Patterns for JMX and Application Manageability
http://www4.java.no/javazone/2005/presentasjoner/JustinMurray/Justin_Murray-DesignPatternsForJMX_javazone2005.pdf

Tuesday, January 22, 2008

Java SE 6 and JMX

Java 1.4.2 and Java 5 delivered huge advancements for Java developers, but Java SE 6 has provided several very nice new features. I covered two of the features of Java 6 (built-in annotations processing and built-in JAXB support) in my Oracle Technology Network article Better JPA, Better JAXB, and Better Annotations Processing with Java SE 6.

Many of the new Java SE 6 features are covered in the book Java 6 Platform Revealed. Two features not covered in the book are JAX-WS support in Java SE 6 and the new additions Sun introduced for JMX in the Java platform. The managing and monitoring improvements in Java SE 6 are also discussed in the article What's New in Java SE 6. This blog entry focuses on the JMX enhancements because Java SE 6's addition of JMX to the platform improved significantly upon the JMX support first included with the Java 5 platform.

Before the advent of Java 5, the JMX reference implementation was available as a separate download. When JMX was included with J2SE 5, it was referenced as the "platform JMX implementation" and was distinct from the JMX reference implementation. With Java SE 6, the JMX implementation delivered as part of the platform was also considered the JMX reference implementation.

The JMX 1.4 Specification explains the history of the JMX reference implementation and the platform JMX implementations for J2SE 5 and Java SE 6. As described in Section 1.2.1 ("Reference Implementation") this specification (which is stored in the Java SE 6 documentation under http://java.sun.com/javase/6/docs/technotes/guides/jmx/JMX_1_4_specification.pdf),
there was no separately available JMX reference implementation as of JMX 1.3 and the JMX 1.4 RI (reference implementation) is included with Java SE 6. Thus, the platform JMX implementation in Java SE 6 is also the reference implementation of JMX. That definitely makes things less confusing than in the J2SE 5 situation where the reference implementation was separate from the J2SE 5 platform JMX implementation.

Section 1.2.3 ("JMX APIs as part of the Java Platform") of the JMX 1.4 Specification outlines the historical versioning of JMX specifications and the Java platforms. This section of the specification explains that the core JMX API and the JMX Remote API were included with the Java platform for the first time in J2SE 5 as JMX API 1.2 and JMX Remote API 1.0. In Java SE 6, both are included as JMX API 1.4 and JMX Remote API 1.4.

Sun also enhanced its support for JConsole from what was originally provided in J2SE 5. The improvements to JConsole in Java SE 6 include the Attach API, the Plugin API, and new (and I think improved) look and feel.

Differences between the man page documentation for J2SE 5 JConsole and Java SE 6 JConsole also point out a significant change in JConsole between the two versions. When you compare the man page documentation for both versions you'll notice that the note about JConsole being experimental and possibly being unavailable in future versions of the JDK is removed for the Java SE 6 documentation.

In addition to its improvements to JConsole, Java SE 6 also brought improvements to JMX by taking advantage of the newly added Attach API to remove the need to use the -Dcom.sun.management.jmxremote when running clients meant to connect to a JMX server.

Java SE 6 further improved upon platform JMX support by adding the MXBean. Other improvements to JMX via Java SE 6 include improved threading/concurrency support and additional support for SSL with remote connectors.

As I described in a previous blog entry, Sun's Java SE 6 SDK has delivered many useful features that make the Jsva developer's life easier. A more complete listing of the Java SE 6 enhancements to JMX is available here.

Monday, January 21, 2008

Java: No Importing of Type from Unnamed Packages

There is a little corner case in Java that many Java developers may not run into very often if at all, but it can be frustrating when one does have to deal with it. The Java Language Specification (JLS) describes "unnamed packages" in Section 7.4.2 ("Unnamed Packages"). Sometimes referred to as the "default package" or the "anonymous package," the "unnamed package" refers to the package to which all compilation units (classes, interfaces, etc.) belong if they do not explicitly list a package. Most of us do not run into issues with the "unnamed package" because we tend to use named packages for our classes and interfaces. In fact, the Java Language Specification states that unnamed packages are primarily intended for beginning developers or for small, temporary Java applications.

The problem that I have run into with classes in unnamed packages is trying to access these classes from classes in explicitly named packages. In other words, when a third party provides classes without explicit package declaration, our classes in named packages cannot access those third party classes. Section 7.5 of the JLS explicitly states that a compiler error will result from trying to import a type from an unnamed package.

The most recent encounter I have had with this was when I tried to incorporate the JTop class that is delivered with Sun's Java SE 6 SDK as an example of using the JConsole Plugin. Neither the JTopPlugin class nor the JTop class has an explicitly named package and therefore both automatically are considered part of the unnamed package.

It is a relatively trivial manner to include the JTop functionality in one's own JConsole tab by importing JTop into one's JConsolePlugin class. However, this won't work "out of of the box" if one's JConsolePlugin class is declared as part of a named package. To make it work, one must either put one's own class in the unnamed package or else must make a minor modification to the JTop class to add a package declaration statement to the class. I prefer the latter. For example, I can add a package declaration statement like package jtop; at the top of the JTop.java file to make it part of a named package.

An interesting read related to a named package importing a type from an unnamed package is contained in the Bug 4361575 ("Correct scoping and diagnostics for import declarations") write-up. There is an explanation in there about importing an unnamed package's type from a named package. Perhaps more interesting is the reader feedback underneath the main bug entry. It is clear that this is not a very popular feature with Java developers, especially those who had code break during the transition from Java 1.3 to 1.4.

Another interesting read is top threads plugin for JConsole.

Friday, January 18, 2008

Aging JMX Books

It is difficult to find a "new" book exclusively covering Java Management Extensions (JMX). Here are some JMX books that are available with their release dates.

Java Management Extensions (O'Reilly, June 2002)

Java and JMX: Building Manageable Systems (Addison-Wesley, December 2002)

JMX Programming (Wiley, August 2002)

JMX in Action (Manning, October 2002)

JMX: Managing J2EE with Java Management Extensions (Sam's, January 2002)

Pro JMX: Java Management Extensions (Apress, February 2004)

In late January 2008, all of the above-listed JMX books have release dates between 2002 and 2004. It is somewhat surprising to me that there have not been any newer books released (or at least newer editions of these books) because several advancements have been made in the JMX world since the last one of these was released.

Here are some reasons why we may have not seen a newer edition of a JMX book:

1. Publishers may feel the changes have been minor enough not to warrant a new book. After all, the information in the current books is not incorrect and these books still provide the basics and gist of using JMX. However, this might change when JMX 2.0 is released. Also, these books did have the JMX Reference Implementation (JMX RI) to talk about and many of the classes and interfaces in JMX RI were migrated with only relatively minor changes to the J2SE 5 and Java SE 6 platform support of JMX.

2. Publishers may feel that articles and blogs have covered the improvements and enhancements to JMX well enough to not warrant a new edition of their books.

3. Publishers may feel that most JMX developers have their needs covered with the current books and that the advances in JMX tools render new editions of these books unnecessary.

4. Publishers may feel (perhaps even from experience with the current editions) that JMX books do not sell particularly well and that the cost to publish a newer edition is unlikely to be covered in additional revenues.

UPDATE (04 February 2008): I stumbled across the blog of the author of the book Java Management Expressions (O'Reilly, 2002) cited above and noted that this fourth reason seems to be accurate, at least in one case. In his blog entry JMX Back from the Dead, Perry states that O'Reilly is not interested in a second edition of the book because of "poor" sales of the first edition. I really like this particular JMX book and my biggest complaint about it is that it pre-dated JMX Remote API (JSR-160) and so does not address remote access much outside of page 20 of the book. I hope that Perry is able to provide information on his blog about JMX Remote API in the future because I like his style of covering JMX.


So, what are some JMX enhancements that are not covered in these books or receive only very little coverage in these books? I don't own copies of all of these, but based on their release dates, I believe that most of the following items are either not covered at all or are not covered very thoroughly in these first edition JMX books.

1. J2SE 5 (1.5) incorporates "platform MBean server," delivered out-of-the-box with Java 1.5. As part of this, the JVM itself is instrumented, allowing for significantly greater access to the JVM for performance tuning and other needs. JConsole is included as an experimental example client-side JMX tool. These and several other J2SE 5 JMX-related improvements changed JMX from being a largely Java EE technology (though certainly not limited to Java EE) to being being an all-inclusive Java management technology more generally accessible and useful to Java SE developers.

2. Java SE 6 further improves built-in JVM support for JMX with Attach API, JConsole Plug-in, MXBean, generification of JMX API, and other useful JMX enhancements. JConsole enjoys some improvements and becomes a full-fledged tool. Java SE 6 includes enhancements such as SwingWorker and the Service Provider Interface (SPI) that facilitate with these JMX improvements.

3. Spring Framework provides significant JMX support, including metadata annotations that allow for easy setting of metadata to be displayed in JConsole and other JMX tools.


It would be nice to have a single JMX book covering these new developments in JMX, but fortunately there are many good online resources that cover these new developments.

JMX 2.0 (JSR 225) is anticipated to be released as part of Java SE 7. It will likely include Spring-inspired annotations support for metadata on standard MBeans. I hope that we'll see new JMX books released at that time that bring coverage of all these developments in the JMX world to a single source.

Thursday, January 17, 2008

The Impact of Oracle Acquiring BEA

The January 16 announcement of Oracle acquiring BEA was a huge announcement. Its effect was lessened slightly by the same-day announcement that Sun Microsystems is acquiring MySQL.

With Oracle acquiring BEA, Oracle Corporation, which already has JDeveloper and contributes heavily to Eclipse, will have another Java IDE (the Eclipse-based BEA Workshop) on its hands. It is difficult to imagine Oracle maintaining all three IDEs, though they might see it only as two with future versions of Workshop using much of their contributions to Eclipse.

While it would surprise me if Oracle maintains JDeveloper, Workshop, and independent Eclipse contributions in the future, it would be even more surprising if they maintain two application servers (WebLogic and OC4J) as well as two SOA platforms built on those application servers (AquaLogic and Fusion). My guess is that they will be combined and it would not surprise me if the combined products had more AquaLogic/WebLogic base than Fusion/OC4J base. What I will miss most, if this happens, is the ability to use the sleek OC4J Standalone development application server. I like its small footprint, its decent standards compliance, and its easy to use command-line and web-based administration interfaces.

I hope that we will hear from the Oracle/BEA combination soon about the future direction of these significant products. I am also looking forward to hearing what is said at the upcoming RMOUG Training Days 2008 and Collaborate08 conferences about this major announcement.

Wednesday, January 16, 2008

Spring and JMX: BeanFactory Versus ApplicationContext

When using the Spring Framework, one can use the BeanFactory interface or the ApplicationContext interface to instantiate and configure/wire beans for use in a Spring-based application.

ApplicationContext extends BeanFactory and adds significant new functionality. The Spring Reference (PDF) recommends using ApplicationContext rather than BeanFactory in most cases, especially for support of enterprise functionality.

I have run into this difference when using Spring's JMX support. It is a trivial matter to wire Spring beans to an MBean server using an ApplicationContext such as FileSystemXmlApplicationContext or ClassPathXmlApplicationContext.

Another difference between BeanFactory and ApplicationContext is support for Aspect-Oriented Programming (AOP) as discussed in this blog entry related to an omission in the second edition of the book Spring in Action.

Other discussions regarding use of ApplicationContext versus BeanFactory can be found in Spring Best Practices, BeanNameAutoProxyCreator and BeanFactory Versus Application Context, Practical Spring (Page 8), Introduction to the Spring Framework, and Overview of the Spring Framework.

The article Spring: Creating Objects So You Don't Have To goes into more depth on BeanFactory and ApplicationContext.

Tuesday, January 15, 2008

jps - Java Virtual Machine Process Status Tool

Once of those nifty tools introduced with Java 1.5 is the jps tool (Java Virtual Machine Process Status Tool). The blog entry Using jps to Find JVM Process Information shows some of the information available via this handy tool. This tool has almost completely replaced my use of ps -ef | grep java when working with Java in Unix or Linux.

The snapshot below (click on image to see larger version) shows some of the basic options of jps in action.



One use of the jps command is in conjunction with the handy JConsole tool to identify the PID of the JVM for to which JConsole should be run against. The document Using JConsole - Java SE Monitoring and Management Guide explains that the ps commands can be used with Linux or Unix systems and that the Task Manager can be used in Windows. However, it points out that jps can be used on all of these operating systems. This universal nature of the jps command makes it very attractive. Not only can it be used on all of these operating systems, but it provides useful output. I especially like the output from the command jps -lm.

Monday, January 14, 2008

Oracle XQuery and the fn:doc-available Function

When using Oracle XQuery implementation, one important point to understand is that the fn:doc function returns an empty sequence if the specified resource is not found. This would be a problem if there was no way of knowing the difference between a resource that could not be found and an XQuery that did not match any results. Fortunately, Oracle's implementation of fn:doc-available function can be used to test for the availability of the resource. The screen shot shown next (click on it to see larger version) shows use of fn:doc-available against a URL with file:/// that returns true because the resource is found. However, as shown in the screen shot, when I fail to specify the file:/// protocol, false is returned. I also showed trying to use fn:doc against this same URL to demonstrate the return of the empty sequence rather than an error message. This behavior is as documented in Using XQuery with Oracle XML DB (Chapter 18 of Oracle XML DB Developer's Guide).



The screen shot specifically demonstrates use of XQLPlus to show use of fn:doc and fn:doc-available, but this behavior should be the same for all Oracle XQuery implementations.

Had I included the file:/// protocol in the URI to fn:doc, but with an invalid file location, an error would have been returned as shown in the next screen shot image:



So, Oracle XQuery implementations that are told to look for a file (with the file:/// protocol) and cannot find that file will report an error. On the other hand, if the URL resolves to something other than the file system (such as the default XML DB repository) with a non-valid value, an empty sequence is returned. The function doc-available returns false in both cases (file not found and non-file URI with no matching resource). Note that the XQuery implementations can also find documents in the database's XML DB repository and this is why file:/// is not a default (and C:\ cannot be found in the repository).

Use of doc-available is also recommended before fn:doc that accesses file system files (with file:///) because doc-available returns "false" for files that are wrong format (such as binary files or files with encoding other than UTF-8) and for files that are text but not XML. If fn:doc is used directly on the binary files an exception will be thrown with the message "Invalid UTF8 encoding." Likewise, if fn:doc is used directly on a non-XML text file, an exception will be thrown with the message "Start of root element expected." Using fn:doc-available in a conditional before using fn:doc in an XQuery script helps avoid these exceptions.

Specification details on fn:doc and fn:doc-available can be found in the XQuery 1.0 and XPath 2.0 Functions and Operators document.

JFreeChart 1.0.9 Released

Dave Gilbert recently announced the release of JFreeChart 1.0.9. The release notes for this release are conveniently available in the General JFreeChart Forum.

I am pleased to report that the sample code associated with the Oracle Technology Network (OTN) article Visualize Your Oracle Database Data with JFreeChart works properly using this new release.

Saturday, January 12, 2008

JPA and Spring Tutorials and References

The Spring Framework and the Java Persistence API (JPA) go well together. This blog entry is a simple list of tutorials and references that discuss use of JPA in conjunction with Spring.

Simplest Spring Example

This entry contains a very simple example using the Spring Framework that is meant to show a minimum amount of code while at the still same time illustrating how Spring's XML configuration interacts with Spring Beans and with the Java application driving the entire example.

The SimpleSpringBean.java code for the simple bean class is shown next. Note that there is nothing Spring-specific about this class.

package marx.spring;

/**
 * Simplistic example of a Spring-loaded bean.  Perhaps most important to notice
 * for this example is that there is no use of Spring-specific code in this bean
 * and "Spring" only appears in the class name and package name and neither
 * requires its presence.  In other words, this is a boring old Java class, but
 * it can still be easily Springified.
 *
 * @author Dustin
 */
public class SimpleSpringBean
{
   private String action = "DefaultAction";
   public String getAction()
   {
      return this.action;
   }

   public void setAction(final String aNewAction)
   {
      System.out.println("Changing " + this.action + " to " + aNewAction + "!");
      this.action = aNewAction;
   }
}

The class to start the Spring container and take advantage of our bean and Spring configuration, SimpletonSpringExample.java, is shown next:

package marx.spring;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

/**
 * Simple example of Spring Framework in action.
 *
 * @author Dustin
 */
public class SimpletonSpringExample
{
   /**
    * Main application for showing simple Spring example.
    *
    * @param aArgs Command-line arguments; only expecting Strings to be set to
    *              Spring-loaded bean.
    */
   public static void main(String[] aArgs)
   {
      BeanFactory factory =
         new XmlBeanFactory(new FileSystemResource("config/SimpleSpring.xml"));
      SimpletonSpringExample simpleton =
         (SimpletonSpringExample) factory.getBean("beansIsBeans");
      final int numberOfCommandLineArgs = aArgs.length;
      for ( int i=0; i < numberOfCommandLineArgs; ++i )
      {
         simpleton.setAction(aArgs[i]);
      }
   }

The executable class whose code is shown immediately above starts up a Spring container via the XmlBeanFactory, which provides an instantiation of the bean whose code was shown earlier.

The beansIsBeans string in the code above ties to an ID in the XML configuration file and that is how Spring knows which bean to instantiate. Here is that XML file (config/SimpleSpring.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
   <bean id="beansIsBeans"
      class="marx.spring.SimpleSpringBean">
      <property name="action" value="Spring Default" />
   </bean>
</beans>

Spring supports configuration with mechanisms other than XML (such as via Java, properties files, and Groovy; books, articles, blog entries, and discussions with colleagues lead me to believe that XML (including XML Schema-based configuration) is still the primarily used format for Spring configuration.

The output confirms Spring's injection of the bean (click on image to see larger version).

The output shows that the bean was originally instantiated with its single property set to "DefaultAction" as set in the class member declaration. The output showing this value changing from "DefaultAction" to "Spring Default" is the Spring container injecting the "Spring Default" value as prescribed in the Spring XML configuration file. The remainder of the value changes are from the setAction calls performed directly on the bean instance returned from Spring.

This example has shown a minimal Spring-based application. As shown in the bean source code, that bean did not need to know anything about its being used as a Spring bean. Spring is designed to be as least intrusive as possible. This was also a main point of my coverage of the Spring Framework used with Oracle JDBC in the Oracle Technology Network (OTN) article Add Some Spring to Your Oracle JDBC Access (November 2005).

Staying Grounded

With all of the buzz words, trendy terms, and desire to do the "next big thing," it is difficult in the software development world to avoid being caught up in the rush. Therefore, I always appreciate "contrarian" articles and blog entries that help to remind me of reality and somewhat control my enthusiasm for new things just because they are new. I have no use for argumentative posts with no substance, but appreciate the article or blog entry that shows well thought-out contrarian points of view and makes me question some of my own software development biases and perceptions.

One of the earliest articles I recall that did this for me was the SoftwareReality.com classic 101 EJB Damnations. Looking back now, it would be easy to dismiss this article as "obvious," but those of us who were fighting with EJB development and deployment at that time recall what the environment was like. Articles such as this one were largely dismissed and authors of such articles were largely abused. Similarly, Rod Johnson's One-on-One J2EE Design and Development was a major contrarian perspective in the "everyone must do EJB" environment.

What is interesting about that latter example is that the author of One-on-One J2EE Design and Development would turn that work into the Spring Framework, which is now more closely associated with the mainstream than with any type of contrarian point of view. Both of the examples I cited here required the authors to invest significant effort into learning problems of early EJB through hard-earned experience and then to articulate these successfully. Another characteristic of such works is that they often place the author in a position of easy ridicule from those who have "drunk the Kool-Aid" for whatever is popular at the time and enjoy bashing anyone with a different opinion.

I am not saying the mainstream is always wrong and contrarians are always right. Rather, I am saying that the mainstream can be wrong at times and contrarian points of view can help all of us to improve our skills, the tools we use, and our ability to satisfy customer needs. We should encourage diverse points of view so that we can either strengthen our current understanding when it is correct or realign our understanding when it is not quite on the mark. Therefore, I like to read articles that challenge my assumptions and preconceptions in addition to those that support my opinions and experiences.

The following are some of the articles (in no particular order) that have had the most effect on me in terms of challenging assumptions (or strengthening my own contrarian points of view). In several cases, I may not be in 100% agreement with the author, but I think the point they make is worth considering and should not be quickly dismissed.


101 EJB Damnations
http://www.softwarereality.com/programming/ejb/

Perils of the Singleton
http://www.softwarereality.com/design/singleton.jsp

Annotations: Don't Mess with Java
http://www.softwarereality.com/programming/annotations.jsp

The Perils of Pair Programming
http://www.regdeveloper.co.uk/2007/01/31/perils_pair_programming/

Why Extends is Evil
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

Why Getter and Setter Methods are Evil
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

The Myth of Self-Describing XML
http://www.oceaninformatics.biz/publications/e2.pdf

Java Multiple Interface Basics

Everyone once in a while, I like to write up a quick blog entry on a basic topic that I get fairly frequently asked about or otherwise talk to people about. One significant and basic Java concept that I find is often not well understood, especially by people relatively new to Java, is that of the Java interface. In this blog entry, I am going to show a class that implements two Java interfaces. Both interfaces are very simple and actually define only a single method each. What makes the example even more interesting is that the method is defined exactly the same in each interface with an identical method signature. The implementation class's method with the matching name implements the same-named method in both implemented interfaces.

The first code sample is for the Java interface InterfaceOne.java:


package interfaces;

public interface InterfaceOne
{
void doSomethingSwell();
}


While it doesn't get much easier than the code example shown above, InterfaceTwo.java is just as easy and is shown next:


package interfaces;

public interface InterfaceTwo
{
void doSomethingSwell();
}


Both InterfaceOne and InterfaceTwo define a method with the same signature. The next code sample shows Java class Implementation.java that implements both interfaces.


package interfaces;

/**
* This class demonstrates how multiple Java interfaces specifying the same
* method (same name and other signature characteristics) can be implemented by
* a single class.
*/
public class Implementation implements InterfaceOne, InterfaceTwo
{
public Implementation()
{
System.out.println("Implementation Constructor");
}

@Override
public void doSomethingSwell()
{
System.out.println("Implementation.doSomethingSwell");
}

public static void doOnlyForOne( InterfaceOne aOne )
{
System.out.println("doOnlyForOne(InterfaceOne)");
}
/*
// This must be commented out so as not to be ambiguous because this
// Implementation class extends both interfaces and so trying to pass an
// instance of this class to this method with both versions uncommented
// results in an ambiguity error.
public static void doOnlyForOne( InterfaceTwo aTwo )
{
System.out.println("doOnlyForOne(InterfaceTwo)");
}
*/

public static void main(String aArgs[])
{
final String lineBreak = System.getProperty("line.separator");
System.out.println(lineBreak);

System.out.print("Direct Implementation: " );
Implementation me = new Implementation();
me.doSomethingSwell();
doOnlyForOne(me);
System.out.print("Direct Implementation is instance of InterfaceOne? ");
System.out.println( me instanceof InterfaceOne );
System.out.print("Direct Implementation is instance of InterfaceTwo? ");
System.out.println( me instanceof InterfaceTwo );
System.out.println( lineBreak );

System.out.print("InterfaceOne: ");
InterfaceOne one = new Implementation();
one.doSomethingSwell();
doOnlyForOne(one);
System.out.print("Implementation 'one' is instance of InterfaceOne? ");
System.out.println( one instanceof InterfaceOne );
System.out.print("Implementation 'one' is instance of InterfaceTwo? ");
System.out.println( one instanceof InterfaceTwo );
System.out.println( lineBreak );

System.out.print("InterfaceTwo: ");
InterfaceTwo two = new Implementation();
two.doSomethingSwell();
// Must comment out line below once the doOnlyForOne expecting an
// InterfaceTwo was commented out.
//doOnlyForOne(two);
System.out.print("Implementation 'two' is instance of InterfaceOne? ");
System.out.println( two instanceof InterfaceOne );
System.out.print("Implementation 'two' is instance of InterfaceTwo? ");
System.out.println( two instanceof InterfaceTwo );
}
}


To make the Java class and the two interfaces it implements compile, I needed to comment out the portion of the code that describes a second doOnlyForOne method. Although this commented-out method had a different argument type (InterfaceTwo rather than InterfaceOne), the Implementation class implements both and so the compiler has no way of knowing which one is appropriate. The output when trying to compile the code without that second doOnlyForOne method commented out is shown next (click on this image to see larger version):



Commenting out the ambiguous method removes the error shown above, but now there is an error because the call to doOnlyForOne(InterfaceOne) no longer applies to the Implementation instance that is assigned as InterfaceTwo on instantiation. When this code is not commented out, the following error is seen:



With the call to doOnlyForOne(InterfaceTwo) commented out, the code compiles and the executable can be run. The next image shows the execution of this simple code and the output.



When the output is compared to the code, we see evidence of many of the basic principles of Java interfaces. Among other things, we can see that an Implementation class is known to be an implementation of both interfaces (using instanceof) even when it is only treated as a single interface. We also see in this example that a single implementation method can satisfy multiple interfaces' declaration of that method if the signatures all match. Finally, the example demonstrated the nuance of multiple implemented interfaces that can lead to ambiguous methods calls for seemingly unrelated interfaces if appropriate naming is not used.

When I am explaining Java interfaces to someone new to Java, I usually like to show that person use of a Java collection directly versus using its interface and then demonstrate how much easier it is to swap out collection implementations if interfaces are what are passed around and returned from methods. However, simple examples like those shown above also seem to go a long way toward explaining how these nifty Java interfaces really work.

Thursday, January 10, 2008

Why I Don't Care for JSF

I recall in 2001 as Struts was just starting to take off in popularity that the next big thing was being advertised as JavaServer Faces. I have followed this specification's progress off and on since then, but have been disappointed with JSF implementations each time I have made a real effort to learn to JSF. I have wanted to like it because it is a standard specification and many vendors have been pushing it. Unfortunately, each time I work with JSF, I leave disappointed. It is difficult to summarize all the frustrations and issues, but I think it boils down to truly being far more difficult than it should be. The difficulty of applying JSF is more obvious when it is compared to alternatives such as Flex, OpenLaszlo, Ruby on Rails, WebWork, Tapestry, and even several other Java web frameworks.

It almost seems unfair to compare Flash-based web applications developed with either Flex or OpenLaszlo to JSF. After all, Flex and OpenLaszlo enjoy the ability to compile into applications that run in an environment that supports highly fluid animation and allows developers to code free of concern about browser idiosyncrasies. Flex and OpenLaszlo both allow for developers new to these frameworks to easily begin working with the frameworks and quickly master the basics of each framework. Both OpenLaszlo and Flex provide rich component sets and both are heavily based on standards (XML and ECMAScript).

If an application must be a browser-based application, it is difficult to think of an easier way to accomplish this than by leveraging the abstraction provided by Flash and acquired easily with OpenLaszlo or Flex. While I think Flash-based web applications are easier to build and maintain than DHTML/Ajax-based web applications, the JSF-based applications seem to be the most difficult of all.

I am being relatively kind in my treatment of JSF in this blog entry. Matt Raible, who certainly knows a thing or two about Java-based web development, stated "... JSF sucks. Especially when used with JSP - which is what most folks are doing. JSF continues to be the most over-hyped under-used framework in Javaland." Ouch. Painful but true. Matt also points out something that really irritates me as well regarding JSF; it simply takes too long to be what it wants to be and other frameworks and tools are leaping ahead.

Adam Winer is much nicer about JSF, but acknowledges it is more difficult than it should be in his blog entry Usability Problems in JSF.

In The Real Problem with JSF, Spencer Uresk states that the real problem with JSF is people making misinformed statements about it. While there may be some truth to that, it is my experience that JSF is the most difficult to use of any of the web frameworks that I have tried (and I have tried several). So, while it admittedly may be just me, I personally don't have much use for the seemingly unnecessary complexity of JSF. This is driven home even more whenever I try JSF in the same relative time frame that I work with Flex or OpenLaszlo.

To be fair, some JSF implementations are better than others. However, I grow weary of people arguing about JSF's advantage being its standardization. My experience has been that many JSF implementations have trouble implementing even the core functionality correctly or completely. Some of the commercial (or formerly commercial) JSF frameworks are significantly better, but many of them use proprietary features to be better and that reduces the argument of a standardization advantage for that particular JSF implementation.

Frederic Simon beat me to the punch on comparing JSF to earlier versions of Enterprise JavaBeans. The push from Sun and vendors to use "the standard" despite its many flaws and relative problems compared to other available frameworks feels like EJB 1.x and 2.x being foisted upon us all over again. The Spring Framework and other forces led to making EJB usable and I'd like to think that all these other innovative web frameworks will have the same positive effect on JSF. Unfortunately, many of us have heard the JSF hype repeatedly and been burned repeatedly as we gave it another try. Just as many are reluctant to give up their Spring-based applications to even try the vastly improved EJB 3, it is likely that many of us will be very reluctant to try JSF again if one of these alternative frameworks is satisfying our needs.

In the article Improving JSF by Dumping JSP, Hans Bergsten points our that using JSP as one of JSF's main views is problematic. In that article, he encourages use of other view technologies in conjunction with JSF.

The article Java Opinions: Geary vs Raible on JavaServer Faces provides a nice summary of some of the discussion regarding JavaServer Faces and summarizes my thoughts on it. While it could be argued that it is the implementations that are the problem rather than the specification itself, that doesn't help me feel much better if the implementations are all I have to use. Even if one or two is a decent implementation and the rest are more trouble than they're worth, it reduces the value of a "standard" because I cannot easily switch between them or rely on the same behavior across them.

Matt Long writes of his frustration with JSF in Nobody Users JavaServer Faces and he compares it to ASP .NET (which I have not used). He says, "As much as I despise ASP .NET, it is a dream compared to JSF." He adds, "And that brings me to the point. JSF is a technology that looks good on paper, but when it comes to actually using it, it stinks." This is echoed by others critical of JSF (including me) who like many things about it conceptually, but find it much dissatisfying in practice. Matt also mentions another telling characteristic of JSF -- even the "introductory tutorials" must use long code samples and explanations even for the most basic of applications. I liked a quote from a person providing feedback to this article (and defending JSF): "That said, in it's current offering it's much more a bare fundamental technology on which interesting things can be built, than a ready to use high-level framework." Since 2001, JSF has consistently seemed to be "almost there."

I think most people who have used JSF directly would have a hard time arguing that JSF simplifies web development. However, one of the big arguments for JSF has been that tools would make it easier to use and this is where vendors seemed to really be interested from the beginning. After all, any chance to sell a tool to make a complicated framework or language easier to use is better for a vendor's business than a framework that does not need a tool. One of the facets of the Agile Manifesto is "Individuals and Interactions over processes and tools." If I have my choice, I'd rather have something simple to write manually (and still use tools if I choose to) rather than something that is so complicated or tedious (EJB 1.x, EJB 2.x, XML Schema, etc.) that they almost necessarily require use of tools.

I have heard proponents of JSF argue that simply reading a good book on JSF will overcome the many complaints with JSF. The problem with this argument, in my opinion, is that one probably doesn't need to read a good book to get well under way with OpenLaszlo or Flex. Admittedly, a good book comes in handy as one progresses with either of these frameworks, but I did not find myself relying nearly as much on these books as I needed to rely on my JSF book for even simple things (or things that should be simple).

From its beginning, one of the mantras of JSF has been its desire to allow for a flexible architecture in which view technologies could be easily swapped. For those who truly need this, the complexity of JSF may be justified if the ease of swapping view technologies becomes reality. Generally speaking, with great flexibility comes great complexity. Why endure the complexity if you don't really need the flexibility?

I am curious to see if JSF is able to survive and eventually thrive. To do so, it may have to go through a evolution or even revolution like EJB did. It seems like the best bet for a successful and less painful JSF experience is to use a framework like JBoss Seam, Oracle's Application Development Framework (ADF), or Apache Beehive (former BEA product). Note, however, that Seam and ADF offer much more than simply JSF implementations.

There is already tough competition for JSF in the web development community and the rise of Silverlight and JavaFX to emulate Flash will likely make the competition for web developers' hearts and minds even more fierce. There is much I like about Java (both SE and EE), but I have serious doubts about the viability of JSF in the near-term future without significant changes. JSF has certainly come a long way, but I question whether it has come along far enough fast enough to remain a viable option compared to the many other choices out there. Just as "being the standard" was not enough for earlier versions of EJB, this cannot continue to be the main advantage of JSF if it is to be successful.

We all know that the major players in web (Google, Amazon, etc.) using Ajax technologies and Flex. Do they use JSF as well? I don't know and it certainly doesn't seem to be advertised as well if they do.

This blog entry is not meant to belittle anyone who has had success with JSF. After all, we each should select technologies that work best for us, for our clients, and for the problem at hand. For example, those who need their application rendered on many different platforms/devices and have access to or willingness to write the appropriate render kits, JSF may be the best alternative.

UPDATE (28 January 2008): Ed Burns, co-lead of the JavaServer Faces specification, left a feedback message below with this reference to a JSF 2.0 requirements scratch pad. It is reassuring to see active work to improve JSF. It will be interesting to see if JSF can compete with the increasingly popular Flex+Java combination as well as with JavaFX if that starts getting heavy adoption.

This blog entry is meant to be a simple summary of things I have experienced with JSF, especially when compared to Flex. While my experience leads me to strongly prefer Flex or OpenLaszlo over JSF for web-based applications, I believe just as strongly in the principle of "To each his or her own!" In addition, I'd like to see JSF succeed because, when all else is equal (or even very close to being equal), I do prefer to develop to the standards-based product.

Here are some other interesting opinions on JSF. I have mixed some positive reviews of JSF with the negative ones.

Ed Burns Blog ADDED 28 January 2008

JSF for Nonbelievers: Clearing the FUD about JSF

What to do about Java and JSF?

JSF: The Ultimate in Flexibility? Or Complexity?

Developing Web Applications with JavaServer Faces

JavaServer Faces: Web Applications Made Easier

JavaServer Faces Versus Tapestry

GAME OVER - Java Sever Faces (Added 3 May 2008)

Is JSF Fixable? (see feedback as well for interesting counterarguments) [Added 5 November 2008]

JSF Anti-Patterns and Pitfalls (see feedback as well) [Added 20 December 2008]