Java
Remove JSP Whitespace
02:45 PM -
permalink
I just found Matt Raible's post on removing whitespace from JSP pages after rendering using Tomcat. This was perhaps the most annoying thing about HTML output from JSP pages and I'm glad to have cleaner output and less of it.

Thanks Matt!
Null is Not an Exception
10:10 AM -
permalink

When I first learned how to program, object oriented tools didn't exist. Instead for years procedural programming was all I had. As a result my "object-oriented" code tends to smack of procedural code quite often and I have to re-factor to optimize for re-use, modularity and testing.

So it comes as no surprise that post procedural programmers like myself will sprinkle their Java code with poor usage patterns that hark back to earlier days. One example is the absence of proper exception throws. More specifically, using null as an acceptable error condition.

When coding in say C, the programmer will return a particular numerical error code from a function if something was amiss during execution. The calling function was then fit to deal with the error code as it saw fit. This worked but was problematic as the codes were only visible at runtime and only had context if there was a list to match these codes. Those of you who program in Microsoft ASP code and see meaningless error codes such as 502345 know what I'm talking about. Sure you can look it up, but what a freakin' pain.

One of my favourite features of Java is the Exception object. Exceptions are basically object based errors which methods are defined to throw. Utilizing exceptions are often misunderstood. Frequently programmers will simply throw the offending Exception up to the calling method. This isn't great from a data coupling point of view but the worst of these offending implementations is the null return.

The null return is prevalent even in the JDK. It is the absence of a return value from a method because something didn't go right. java.util.Hashtable's get method is an example of the null error. The get method JavaDocs specifies that the return value is "null if the key is not mapped to any value in this hashtable". In other words, if something goes wrong, we're not going to throw an exception but just return null.

Null is like the faceless exception. Something clearly didn't go right because we got null back, but unless we go and look up what this means we're not sure what happened. Changing the method to provide a compile time context makes it much easier to understand what happened and handle it based on context.

// Using null as a return errorObject item = hashtable.get(key);
if(item == null){   
// handle error
}
// Using an Exception as a return error
try{   
Object item = hashtable.get(key);
}catch(ObjectNotFoundException ex){   
// handle exception
}

The amount of code makes very little difference but now we have context for the situation. Hashtable is fairly common so I'm sure you're used to seeing null come back, but if you're using an unfamiliar method and don't remember to check for null you're compile will proceed cleanly and eventually your program will spit up the dreaded NullPointerException.

Where are you? JSR-179
09:00 AM -
permalink
Location based services on cell phones have always ranked high on the list of killer application for portable devices. In the Java world this is embodied in the JSR-179 specification tabled by Nokia and released in September of 2003. That's great news for developers, except it's been almost two years since it's release and only a few phones I can find support it (from Nokia, Motorola and Siemens) and the Nokia ones are not even on the market yet.

So far I've only found the N91 on the Nokia UK site, the Nokia 6265 and 6265i are listed as having support for JSR-179 but I haven't yet found them on any Nokia website and the Motorola i605 (gps) and i830 (gps) only available through Nextel. I also found some Siemens phones from here (CX65, C65, S6V, S65). Russell Beattie mentioned the N91 in April pointing out among other things that it had WiFi, but didn't mention the location capabilities.

Problem number two might involve the carriers. I believe the carrier must support the passing of triangulation information if the phone isn't GPS based. It's in the carrier's best interest to enable this data but privacy advocates might not agree with me. The bottom line is of course that if you don't want to use location based applications, you don't have to. Jay Goldman also pointed out that 911 requirements may force a carrier to provide this information though that doesn't necessarily mean that the handset applications will have access to it.

Two years seems like enough time to integrate this JSR with a phone but perhaps the development timelines didn't allow for it. Furthermore, I don't see anyone marketing this to developers with any great amount of gusto. Location based applicatons are going to be a huge opportunity in the mobile software market, but it's a tipping point technology that requires a push from the carriers with a platform from the manufacturers.

In the mean time I'll start researching the capabilities on Rogers, Bell and Telus networks in Canada. Any information is appreciated.

Error Pages Phone Home
11:00 PM -
permalink
I always cringe when a customer runs into a problem with their website or web application before I do. Because I'm not perfect, my software isn't either, but it's difficult to explain that to a customer when they're staring at a Tomcat stack trace.

JSP error pages are fairly useless for the average user in their default state. Generally the user is greeted with a cryptic number, error message and stack trace that is hardly useful in reaching their goal and they have no choice but to back up and try other options, hunt for the webmaster's email or most likely give up and leave. Software errors while avoidable are bound to occur. In your JSP application there are several things you can do to improve this situation.

First, set-up a custom error page for catching exceptions. Add the following to your web.xml file pointing to a JSP page to handle the error.

<error-page> 
<exception-type>java.lang.Exception</exception-type>
<location>/error.jsp</location>
</error-page>


It's best to base the error page off the same general design as all your other site pages with a graphic difference to indicate a problem has occured. In Foundation we use a simple stop sign symbol with an exclamation mark. It's important to explain to the user that an error has occurred and it doesn't hurt to add an apology.

It's then best to indicate that the maintainer of the website has been notified of the error and will look into it. Furthermore it's helpful to provide either an email link or a form to allow the user to contact the webmaster or customer support if they require immediate assistance or if they feel they can provide more details.

Now, how do we as the webmaster know the error occurred?

A JSP error page has access to the offending exception. It simply exists within the JSP page as the variable "exception". We can extract the error message and stack trace from the exception to begin to build a simple report detailing the problem that occurred.

StringBuffer sb = new StringBuffer(); 
// append error message
sb.append(exception.getMessage());
sb.append("\n");
// append stack tracce
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
exception.printStackTrace(pw);
sb.append(sw.toString());
sb.append("\n");


Stack traces are great but receiving an error report with a stack trace doesn't do much to tell you what happened at the time the error occurred, so let's dig for some more data.

We would like to know what page the error occurred on. We can retrieve that from the request object.

// append request URL 
sb.append("Request URL:");
sb.append(request.getRequestURL());
sb.append("\n");

Knowing the page is great but page state can be helpful. We can then append all request parameters that accompanied the request.

// append parameters 
sb.append("Parameters:");
Enumeration enum = request.getParameterNames();
int numValues = 0;
while(enum.hasMoreElements()){     
numValues++;     
String name = (String)enum.nextElement();
String value = request.getParameter(name);
sb.append(name);
sb.append(":");
sb.append(value);
sb.append("\n");
}
if( numValues == 0 ){     
sb.append("No parameters");
}
sb.append("\n");


Finally it's helpful to see where the user was coming from by pulling the referrer URL from the request header. Since we're pulling request headers we might as well add them all in the report. Headers include cookie information and what type of browser the user has.

In addition to all this wonderful information you could also add session and page context information if you wished depending on what servlet features your web application utilizes.

Now, how do we notify ourselves when an error occurs? There are many different ways of reporting errors. I find Log4J the simplest. By configuring a simple log4j.properties file and placing it in my root classes folder I can catch all Log4J errors and have them emailed to me via the SMTPAppender.

log4j.appender.mailer=org.apache.log4j.net.SMTPAppender
log4j.appender.mailer.Threshold=ERROR
log4j.appender.mailer.BufferSize=10
log4j.appender.mailer.from=error@domain.com
log4j.appender.mailer.SMTPHost=localhost
log4j.appender.mailer.subject=Website Name Error
log4j.appender.mailer.to=support@support-domain.com
log4j.appender.mailer.layout=org.apache.log4j.PatternLayout
log4j.appender.mailer.layout.ConversionPattern=%t %-5p %d{dd MMM yyyy HH:mm:ss,SSS} %c{2} - %m%n
log4j.logger.com.package=ERROR, mailer

In the JSP file, log the error using the StringBuffer we created our report with above.
// create the logging category 
Category cat = Category.getInstance("com.package.jsp.error");
// log error
cat.error(sb.toString());


Alternatively you could use something like the Jakarta Mail Tag Library to send an email.

The astute readers will note that without the localhost mail server running this plan isn't going to work. I will leave it as an exercise or a later article to devise a strategy for monitoring both client websites and their respective services such as databases and mail servers to ensure all necessary services are always running.

You'll be amazed at how much better your customers will feel when you call them ahead of time to let them know that you noticed a problem and are already taking care of it. Problems occur. But being proactive about as much as you can will go a long way to improving your customer relationship and peace of mind.

Ajax: It's About the User
11:20 PM -
permalink
Most programmers design for programmers or most programmers program for themselves. Call it laziness, call it self-serving, most programmers will develop as it suits them. This form of development is not always what suits the end user from a usability point of view. Most often the final product is a result of the least amount of programming or the simplest design pattern.

The Ajax name was first mentioned by Jesse James Garret from Adaptive Path in Ajax: A New Approach to Web Applications in which Jesse explained that Ajax is a new methodology to building web applications by leveraging dynamic browser display technologies including CSS, DOM and JavaScript, specifically the XMLHttpRequest object. These technologies have been with us for a while but the power of such technologies has remained under the radar until Google introduced Google Suggest and Google Maps recently.

Since then several Ajax posts have been made by bloggers either denouncing it for it's disruptive affect on well respected design patterns or brainstorming on techniques to harness it's power.

The Ajax concept is not a replacement for the traditional model of web browsing. Too often we have seen developers design for themselves with previous web technologies and as a result producing harmful interface reprocutions such as breaking the back button with frames and Flash because it suited their definition of an enhanced "user experience". Ajax can shine through enhancement of page components by minimizing on full data updates and screen redraws when most of the page remains consistent. It can also enhance the interface controls and add drag and drop capabilities. These additions are not so harsh as to confuse the user into thinking that the interface has changed pages. In both of the Google examples the enhancements clearing improve the application without the user being confused by the page state.

"But users shouldn't be using the web for applications" some say. Wrong. Users will use what they deem fit. Millions of people don't use web based email systems because there is no alternative. They use these services because they are compelling. A more compelling experience than the alternative desktop or downloadable option. Java applets had their time but incompatibilities and slow download and initialization times make it extremely frustrating and difficult for users to adopt and accept applets.

Testing and architecture can be modeled to a better interface. By enhancing existing tools we can provide a suitable development and testing environment while simultaneously providing an experience that the user wants. Let's not make our laziness hurt the user experience.

Check in the Source, Not the Output
09:25 AM -
permalink
David Walend is searching for a place to store his Javadocs. One of the questions that most people ask is "Should I store my Javadocs in CVS?" My answer? Don't. CVS as Dave essentially concludes is for source code. It's power is in the fact that it tracks differences between versions of each file and can mark sets of files for release or branches.

All your Javadocs and class files should be constructed after you have checked out the source from CVS and have run a build either for the entire project or specifically for class files or Javadoc files.

If you need to make a release of your compiled code or your Javadocs available then make a proper release, either in unpacked format on a website or within a zipped package for you end user. Same goes for end release jar files and war files. Only check in binaries like jars if the code relies upon it at compilation time.

It's nice to have all your files in a central storage location but lets not cram everything in just because we can.
Ajax
10:20 PM -
permalink
Among other things, Ajax is a cleaner, a town near Toronto and a soccer team and now, Ajax is the new acronym coined by Adaptive Path to describe a rich web interface combining XHTML, CSS, DOM, XMLHttpRequest and JavaScript.

Ajax is a concept who's time has finally come to the mainstream. We now have browsers which support enough of the web standards to be able to support richer web interfaces.

Marc Logemann argues that rich web applications would be better architected as client side applications in Swing or C#. I think the use of client side applications has slowed as we shift intelligence and CPU cycles outward. Not every application is suited to live on the server side but building richer interfaces to web sites or web applications fills in the middle ground between client side and server side.

Round trip delays have always prevented web applications from rivaling client side applications. The ease of an instant on always updated application is the appeal in using a web application. By leveraging Ajax concepts we can provide the user with a much more responsive experience.

JSP Buffering and Error Pages
10:30 PM -
permalink
Sometimes when a JSP page errors out it doesn't redirect to the specified error page but displays the error page inline. In that case the page buffer has most likely been filled and because data has already been sent to the browser and the server cannot send a redirect command.

In these cases increase your JSP page buffer size with the page directive's buffer attribute. The default is 8kb. Increase it to something that your page will most likely not fill.
<%@ page buffer="50kb" %>
Google Page Rank in Java
11:15 PM -
permalink
Adrian Spinei has provided the code to calculate a URL's Google Page Rank value using Java. Awesome!
Sun's Internal Java Memo.
12:56 AM -
permalink

Now making the rounds in Slashdot, blogs and email the internal memo from Sun regarding problems with the Java language.

Being a Java developer I have a bias towards Java. The memo however, is justified in a lot of its comments. Don't run for the hills just yet though. This is constructive criticism that should be looked upon as a way to make some serious improvements and think about the next evolution of Java. Slashdot readers love to dump on Microsoft whenever internal critique comes about, but I'd be more scared of a company that thinks their product is perfect and makes no serious examinations of its flaws.

The idea of Java is fantastic but the implementation falls short first in the area of performance and second in implementation. It's time to stop making excuses and put up or shut up. That said I'm still sticking with Java. The ability to rapidly develop applications with easier debugging and a fantastic library and documentation at my disposal is enough to sell me.

In response to the major points:

"The JRE is very large"

This is a bit misleading in my opinion. I think what they mean is that the JVM can take a significant amount of memory during runtime and is slow with several applications noted. I assume this since a compiled "Hello World" class file would not be anywhere near 9MB as indicated. The size of the JVM is an issue that is separate from the language itself but quite effectively points out that the model for bytecode execution needs some serious examination. The scope of this is quite beyond my level of understanding of the JVM at this point in time. Comparing to Python may be significant although I'm not familiar with Python to determine if it is appropriate.

"Extensions do not support modularity".

Convenience dictates that extensions (javax.*, etc) be put into the main JRE distributions. I think this unnecessary inclusion of optional classes is wasteful. The various Java packages are separate enough that developers can include the .jar files along with their application. This also creates dependency problems as packages such as XML parsers that were once in an application's library are now in the JRE and conflicts arise. I don't know how to back out of this scenario other than to stop adding unnecessary extensions and give precedence over application libraries.

"It is not backward-compatible across minor releases"

The JRE release number has always confused me. JRE 1.2 is Java 2 1.0. Huh? Shouldn't this be Java 2.0? Well yes and no depending on where you draw the lines. In a lot of cases there is backwards compatibility but not in all as the memo points out. Regression tests would be nice. Upgrade to a 2.0 or better yet 3.0 to avoid confusion with Java 2 and start over from there. Make sure that all methods and classes are backwards compatible and that point releases are either an addition of functionality or major bug fixes.

Jboss Theory
10:30 AM -
permalink

I saw Marc Fleury speak at the latest Toronto Java Users Group meeting. Marc has great ideas about the next level of EJB that's produced in the Jboss product he brought into reality. Most of the room was trying to grasp the concepts while Marc kept pushing more ideas out at us, myself included.

I'm now busily working with the new Jboss 3.2 beta and learning about the 3.x interceptor concepts.

Read Marc's Blue paper "Why I Love EJB" for more information on Jboss concepts and the future of Jboss and EJB.

TheServerSide.com also has a video interview with Marc.

New Java Needed?
01:51 PM -
permalink
10 Reasons We Need Java 3.0
JavaOne Keynotes
03:14 PM -
permalink
I stumbled across the JavaOne keynotes video archive. Of what I've seen so far I liked Paul Saffo's Thursday keynote. Fast forward approximately 1 hour 2 minutes into the Thursday video to watch Paul's keynote. He reminds us that just because everyone claims it will happen doesn't make it so. He encourages developers to seek out the mountain tops to bring forth new technology.
The Server Side
10:00 PM -
permalink
The Toronto Java Users Group had Floyd Marinescu present "The design and implementation of TheServerSide.com J2EE Community". Floyd is the architect behind TheServerSide.com and gave a fantastic presentation showing a good framework for building dynamic web sites based on J2EE. I'm going to start implementing some of those features behind my Cocoon sites. Check out his site when you have a chance.
Apache Tomcat 4.0 Final Released
10:25 AM -
permalink
Via a Slashdot article, Apache Tomcat 4.0 has been released. I think it's time I put JServ to bed.