Making the move to Google Apps

Sunday, October 28, 2007

For some time now I’ve set up my various email addresses to forward to a Gmail account so that I have a very fast searchable archive of emails that is backed up and I also like the convenience of being able to use Outlook when I’m at my desk and webmail when I’m not. The only problem with this setup is that whenever I reply to emails they are sent from my personal Gmail address “on behalf of” my work email address. That just doesn’t look professional so this morning I decided to sign up with Google Apps. Not a big decision really since the free Google Apps account provides everything I need, including 4GB of email storage.

If you’re not familiar with Google Apps, it lets you use Gmail and other Google services such as Calendar, Docs and Chat with a custom domain name. It was incredibly easy to set up. I had to upload an HTML page to my server containing a Google generated identifier so that I could prove to Google that I own the domain. Next, I had to update my DNS settings with MX records pointing to Google’s mail servers. Google then automatically verified that I had set this up correctly. After that there was a delay of around an hour before the new Gmail account was activated.

So I now have a fully managed email service with plenty of storage and arguably the world's best webmail experience and it hasn't cost a penny. Gmail also works very well with my Blackberry phone. Google have very recently added IMAP support to Gmail as well, which now gives me a choice of using Google's spam filtering (which is actually pretty good) or downloading spam emails to my client for filtering there with Cloudmark (the ultimate spam solution in my opinion).

I'm pretty pleased with this setup so far.


IntelliJ IDEA & Maven

Tuesday, October 23, 2007

I started using the new 7.0 release of IntelliJ IDEA a couple of days ago and I'm loving the support for creating projects based on Eclipse or Maven project files.

I've had some exposure to Maven in the past but have only recently started using it myself. Maven doesn't really do anything that I couldn't already do using Ant but it does mean I no longer have to spend time setting up large Ant build files each time I start a new project and it also reduces the size of my subversion repositories now that third party dependencies are stored in my Maven repository.

One of the most compelling reasons for moving to Maven though is the release management process. Again, it doesn't do anything that I wasn't already doing manually but it really simplifies the process of building releases and tagging them in source control and also enforces it to a degree i.e. unit tests must pass before it will let you create a release.

I'm certainly going to use Maven for all future simple jar/war projects but I haven't yet tried using Maven on more complex projects that have lots of ant tasks. However, Maven can be invoked from Ant so I'm sure it won't be an issue.

SimpleDateFormat and Thread Safety

Wednesday, October 10, 2007

It never fails to surprise me that so many developers are unaware that SimpleDateFormat is not thread-safe. It seems like almost all J2EE projects I work on have code that uses instance variables or static instance variables to store a SimpleDateFormat that is then used throughout the code base without any concurrency control. Here’s a classic example:
public class MyService // could be a web service or a session bean
{
public void someBusinessMethod(String datestring, ...) {
Date date = GlobalConst.DATE_FMT.parse(datestring);
// rest of code omitted
}
}
This is particularly nasty because the code may well run without producing any exceptions but could easily parse the date incorrectly. If you don't believe how likely this is, here's some code to prove the point:
public class ProveNotSafe {
static SimpleDateFormat df
= new SimpleDateFormat( "dd-MMM-yyyy" );
static String testdata[] = {
"01-Jan-1999", "14-Feb-2001", "31-Dec-2007"
};
public static void main(String[] args) {
Runnable r[] = new Runnable[ testdata.length ];
for (int i = 0; i < r.length; i++) {
final int i2 = i;
r[i] = new Runnable() {
public void run() {
try {
for (int j=0; j<1000; j++) {
String str = testdata[i2];
String str2 = null;
/*synchronized(df)*/ {
Date d = df.parse(str);
str2 = df.format( d );
}
if (!str.equals(str2)) {
throw new RuntimeException(
"date conversion failed after "
+ j + " iterations. Expected "
+ str + " but got " + str2 );
}
}
} catch (ParseException e) {
throw new RuntimeException( "parse failed" );
}
}
};
new Thread(r[i]).start();
}
}
}

When I run this code, I get the following output:
java.lang.RuntimeException: date conversion failed after 3 iterations.
Expected 14-Feb-2001 but got 01-Dec-2007
Note that "01-Dec-2007" isn't even one of the strings in the test data. It is actually a combination of the dates being processed by the other two threads!

If I uncomment the synchronized keyword then of course it runs without exception.

If I want to quickly remove these issues from a code base I usually create a simple replacement class like this that wraps SimpleDateFormat.

public class ThreadSafeSimpleDateFormat {

private DateFormat df;

public ThreadSafeSimpleDateFormat(String format) {
this.df = new SimpleDateFormat(format);
}

public synchronized String format(Date date) {
return df.format(date);
}

public synchronized Date parse(String string) throws ParseException {
return df.parse(string);
}
}

Labels:


Hibernate Conclusions

Monday, October 1, 2007

A while ago, I posted a couple of blog entries about the fact that I was going through the learning curve with Hibernate. Since then I have talked to some friends who have used Hibernate on large projects and I have also been prototyping an application using both Hibernate and Spring JDBC to understand the pros and cons of each approach.

My initial reason for learning Hibernate was to make sure I knew enough in an interview situation if it came up. I also needed to recommend a persistence technology for a couple of projects that I am involved in and having heard so much about Hibernate I assumed that it would be a good fit.

The biggest advantage that I can see with Hibernate is that it allows for rapid prototyping and development of new applications. That alone might be sufficient reason to use it on some projects. However, once you get past the simple initial requirements of persisting objects and get to the point where you need to run complex queries across a number of tables and perhaps use aggregate functions and other SQL capabilities, things get much more complex because Hibernate uses its own HQL query language that the runtime translates into SQL and this forces the development team through yet another learning curve. Another issue with this approach is that you can’t simply develop and test SQL and then paste the working SQL into your source code or configuration files but have to then re-code them in HQL.

Spring JDBC isn’t directly comparable to Hibernate because it doesn’t have the same goals (it doesn’t provide caching or object relational mapping for instance). However, it is certainly an alternative choice for implementing persistence. Spring JDBC provides a very small abstraction layer over raw JDBC and does this in an elegant way. Setting up a new project does require more thought and effort than using Hibernate but that time is paid back once more complex application functionality is developed.

However, the real surprise for me was how the performance and scalability compared between the two approaches. I spent a couple of days building a realistic subset of the application I was recommending the technology for and then ran benchmarks against a large database on dedicated test hardware. The results showed that Hibernate didn’t scale at all well compared to Spring JDBC for this application.

I posted some questions to the Hibernate forum to validate the approach I had taken and I received the rather terse and unhelpful reply “This is called 'A useless microbenchmark' and has been addressed a thousand times.” from a member of the Hibernate team. I did some reading of the Hibernate Performance FAQ and found some interesting statements in there, such as "We claim that Hibernate performs well" and "Many people try to benchmark Hibernate. All public benchmarks we have seen so far had (and most still have) serious flaws.". It almost seems like it is taboo to question Hibernate performance. I don't understand this defensive stance since most developers would recognize that there is a trade off between ease of use and performance.

The bottom line for me is that for my application, Spring JDBC scales much, much better, which will save significant hardware dollars (or pounds). Spring JDBC also doesn't require much investment in terms of learning curves and I can have full control over the SQL I use which in turn will help me squeeze maximum throughput out of the hardware that is available to me.

If you're considering using Hibernate on your projects I highly recommend running some performance tests based on your application requirements before getting in too deep.

[14th Oct 2007] Wow! This article has certainly attracted more attention than I expected. I would like to draw attention to that fact that I state in the above article that Hibernate does not scale well for *this* *particular* *application*. Many people seem to think I'm saying that Hibernate doesn't scale well, period. That's not what I'm saying so please read again before posting comments :-)

Labels: , , ,