Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, December 29, 2008

Preventing NullPointerException

When a NullPointerException (NPE) is thrown, it can be hard to trace back to the bug that causes it, especially if it comes from an instance variable of a mutable class, where the execution of buggy code may have finished long before the NPE is thrown. With the wide adoption of the best practice of immutability and IoC container, it is not seen as frequently as before and most of the time it is easy to locate the bug, such as a missing setter injection in the Spring application context. Probably as a result, recently some developers seem to have relaxed on null checking as I have seem some codes in an open soure project that completely lacks both null checking and documentation of the preconditions on methods.

This week, I have seen two good practices (IMHO) of null checking and related documentation:

The first is a static method named T checkNotNull(T reference, String referenceName) in class Preconditions I found in the Activity Stream project. This class is modelled after a similar class from Google Collections API. Note that it does not share any of its source code.

This reminds me of the static methods void notNull(Object object) and void notNull(Object object, String message) from Validate class in Apache Commons Lang that are used a lot in my previous job for null checking:

import static org.apache.commons.lang.Validate.notNull;
...
public class Foo
{
private final Bar bar;

public Foo(Bar bar)
{
notNull(bar, "Bar must not be null.");
this.bar = bar;
...
}
...
}

The T checkNotNull(T reference, String referenceName) has the advantage of returning the parameter, thus it can be assigned right after the null checking:

import static com.atlassian.streams.util.Preconditions.checkNotNull;
...
public class Foo
{
private final Bar bar;

public Foo(Bar bar)
{
this.bar = checkNotNull(bar, "Bar");
...
}
...
}

Similar to null checking, quite often there is also a need to guard against empty String, blank String (containing only whitespaces, see StringUtils), empty Collection, null-containing Collection (containing a null element), empty Array, null-containing Array and empty Map, etc.

Luckily, Validate provides most of these checks:
  • void notEmpty(Collection collection, String referenceName)
  • void noNullElements(Collection collection, String referenceName)
  • void notEmpty(String string, String referenceName)
  • void notEmpty(Object[] array, String referenceName)
  • void noNullElements(Object[] array, String referenceName)
  • void notEmpty(Map map, String referenceName)

Unfortunately, they all return void and cannot be chained, and it can force you to write your own little static method to do all the checks, or use it before the proper check:

import static org.apache.commons.lang.Validate.*;
...
public class Foo extends Bar
{
public Foo(List list)
{
super(notEmptyNoNullElements(list));
}

private static notEmptyNoNullElements(Collection collection)
{
notEmpty(collection);
noNullElements(collection);
}
...
}

So I have added the following methods to Preconditions:
  • <T, C extends Collection<T>> C notEmpty(C collection, String name)
  • <T, C extends Collection<T>> C noNullElements(C collection, String name)
  • <T, C extends Collection<T>> C notEmptyNoNullElements(C collection, String name)
  • <T> T[] notEmpty(T[] array, String name)
  • <T> T[] noNullElements(T[] array, String name)
  • <T> T[] notEmptyNoNullElements(T[] array, String name)
  • <K, V> Map<K, V> notEmpty(Map<K, V> map, String name)
  • String notBlank(String text, String name)

The other example is actually in the Google Gadgets API. All the optional parameters are prefixed with "opt_", making it very obvious. So instead of just documenting in javadoc, we can also given a more intention-revealing name to parameters, such as:

/**
* Do something.
* @param bar Used to do something. Cannot be <code>null</code>. Mandatory...
* @param baz Used to do something. Can be <code>null</code>. Optional...
*/
public void foo(Bar bar, Baz optBaz)
{
...
}

Finally, Preconditions probably should not sit in streams-core. It would be more useful if it is moved to some core projects, such as atlassian-core, so that different teams do not have to reinvent the wheel.

Saturday, June 14, 2008

Which is the hottest Java web framework that people want to learn?

A recent post on The "Break it Down" Blog, Which is the Hottest Java Web Framework? Or Maybe Not Java? has attracted lots of attention, including that of Java Web Frameworks Guru Matt Raible.

The author excluded Tapestry and Stripes because of the high noise from the common usage of these terms.

Some readers, including myself, commented that the high search rate may reflect that some frameworks, like JSF, especially JSF 1.1, are so bad that people encounter problems all the time and have to rely on Google to search for solutions.

In order to find out how people really like to learn about those frameworks mentioned in the post, I tweaked the search terms a bit by adding the word "tutorial", as I reckon anyone who wants to learn a web technology is likely to search for a tutorial on that technology, only if they speak English...

And here are the result.

Comparing JSF, Struts 2, Spring MVC / Spring Webflow, JBoss Seam and Apache Wicket:

As we can see, JSF is much more popular than all other Java web frameworks and is very popular in India, Hong Kong, Czech, Singapore and the Philippines. Struts 2 ranked second, slightly better than Spring MVC and Seam. And Wicket didn't even have enough search volume to rank.

Then I compared Struts 2, Spring MVC / Spring Webflow, JBoss Seam, Tapestry and Grails:

Basically, there is little search volume for tutorials on Grails, Tapestry and Stripes (not shown in this image). This is probably an indication that the official website for these frameworks have good documentation and tutorials, where JSF is only a specification and you have to find tutorials elsewhere.

Here the interesting observation is: Struts 2 is very popular in India and Brazil; Seam is far more popular in Austria, Spring MVC is especially popular in London and Grails has been taken up quite well in Germany. And surprsingly, even Australia has more search volumes for these frameworks than the United States.

Finally, I compared Ruby on Rails, Adobe Flex, JSF, Struts 2 and Spring MVC / Spring Webflow:



Hmmm, Ruby on Rails, Adobe Flex and JSF are popular to the same level. However, the popularity of JSF has been on a plateau for the past few years and has begun to decline. Ruby on Rails also starts to show signs of decline, while Flex is rising sharply.

And Ruby on Rails are very popular in San Francisco and San Jose, CA, the Philippines and Sweden. And Flex is rather popular in Brazil and Europe.