Category Archives: J2EE

Java Class.forName(String className) and JDBC

A reader asked a question via a comment a couple months ago that I didn’t really have an answer for (and had always kind of wondered the same thing). In the original post (which showed how to use JDBC with ColdFusion), I used the following snippet of code:

Class.forName("jdbc.DriverXYZ");
Connection con = DriverManager.getConnection(url,
  "myLogin", "myPassword");

and the reader wanted to know what the Class.forName(..) method did. The most common answer you’ll hear is that it loads the database driver, which, while technically true, is shallow. Where does it get loaded? How does it happen? And why?

To answer the question I started with the JavaDoc for the Class.forName() method. According to the documentation, the method:

… attempts to locate, load, and link the class or interface

I wasn’t perfectly clear on what “locate, load, and link” meant, so I did a little digging through the Java Language Specification. According to chapter 12 of the JLS:

Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler, and constructing, from that binary form, a Class object to represent the class or interface.

Next, again according to the JLS, it must be transformed from it’s binary representation to something the Java virtual machine can use, this process is called linking. Finally, the class is initialized, which is the process that executes the static initializer and the initializers for static fields declared in the class.

So then back to the original problem, when Class.forName() is called with an argument like this:

Class.forName("org.gjt.mm.mysql.Driver");

the classloader attempts to load and link the Driver class in the “org.gjt.mm.mysql” package and if successful, the static initializer is run. The MySQL Driver (download the source code) static initializer looks like this:

static {
  try {
    java.sql.DriverManager.registerDriver(new Driver());
  } catch (SQLException E) {
    throw new RuntimeException("Can't register driver!");
  }
}

So it calls a static method in the java.sql.DriverManager class which apparently registers a copy of itself when it loads.

So now I understand the where and the how, what about why? To understand the why you have to look at the next line in the initial code example:

Connection con = DriverManager.getConnection(url,
  "myLogin", "myPassword");

The DriverManager class (view DriverManager source here) returns a database connection given a JDBC URL string, a username and a password. In order to create that connection, the DriverManager class has to know which database driver you want to use. It does that by iterating over the array (internally a Vector) of drivers that have registered with it (ie: the registerDriver(Driver driver) method illustrated above) and calls the acceptsURL(url)) method on each driver in the array, effectively asking the driver to tell it whether or not it can handle the JDBC URL.

So there you have it. Class.forName explained.

del.icio.us poster

Last month I wrote about a quick utility which uses the delicious-java and Apache XML-RPC libraries to grab posts from my del.icio.us account and post them to my Metaweblog enabled (in my case Movable Type) blog. I’m not sure that it’s useful unless you have your own server or always on desktop PC, but I wasn’t satisfied with the original product, so I updated it with better documentation, a license (GPL), an Ant build file and the ability to edit the format of the posts using a Velocity template. Oh, and it’s all in Subversion now. You can read all about it by checking out the del.icio.us poster project page.

Fun with Axis / SOAP, Java and Calendar

The fun with dates didn’t stop at the last post. This one took longer to track down but I learned alot more from it. I’m working on both sides of an Apache Axis SOAP implementation where the server side system persists events and client applications can query to find events and CRUD events against this server side application. So the server presents an event:

...
public class EventRemote {
private String name;
private String address;
private Calendar eventdate;
...
// getters & setters omitted
}

and methods that allow client applications to search for events and create / retrieve / update and delete them:

...
public class EventManagerRemote {
public void updateEvent(EventRemote event) {
...
}
public void createEvent(EventRemote event) {
...
}
public EventRemote findEventByID(long eventid) {
...
}
// other methods omitted
}

For the last couple weeks the clients and servers had no problems, create, retrieve, update, delete and search all worked as expected. But recently a user requested a change to the UI of the client system which resulted in a change to the way the client application needed to format the eventdate (a Calendar object). In the past the client would retrieve the event and then format the eventdate property using a SimpleDateFormat:

EventRemote event = manager.findEventByID(12);
Calendar eventdate = event.getEventdate();
SimpleDateFormat formatter = new SimpleDateFormat("M/d/yyyy h:m aa");
String strdate = formatter.format(eventdate.getTime());

So if my event was today (June 30, 2005 at 7:30pm), the above snippet would print:

6/30/2005 7:30 PM

The change to the client I mentioned above meant that I needed to access each element of the Calendar object separately, so instead of having one big datetime string, I need to know that the month was June, the date ’30’, the year ‘2005’ and so on. Since the getMonth()/Day()/Year() methods of the Date class have been deprecated since v1.1, I had to use the Calendar class get(int field) methods. Not a problem, there’s some different things you have to work through in the Calendar class (ie: the month field has values that range from 0 to 11 instead of 1 to 12), but it’s doable:

EventRemote event = manager.findEventByID(12);
Calendar eventdate = event.getEventdate();
int day = eventdate.get(Calendar.DATE);
int year = eventdate.get(Calendar.YEAR);
...
int hour = eventdate.get(Calendar.HOUR);
int minute = eventdate.get(Calendar.MINUTE);
int am_pm = eventdate.get(Calendar.AM_PM);

I printed out the results (again assuming a date of June 30,2005 at 7:30pm) and instead of getting that same date I got this:

6/30/2005 11:30 PM

which was exactly 4 hours ahead of the time I wanted. I dug into Axis source code and saw that the CalendarDeserializer class explicity sets the TimeZone of the returned Calendar object to GMT (to make it UTC right?). Understandably, this causes the HOUR property of the Calendar object to jump four hours ahead (I’m in EST, GMT/UTC is currently 4 hours ahead of EST, it’ll be 5 hours during the winter months, explanation). The workaround (although I’m not sure it’s a good idea), was to set the TimeZone of the returned Calendar object back to EST. This probably doesn’t make alot of sense without seeing some sample code:

Calendar calendar = new GregorianCalendar(2005, 5, 30, 19, 30);
String utcformat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
SimpleDateFormat zulu = new SimpleDateFormat(utcformat);
String serializeddate = zulu.format(calendar.getTime());
// string gets sent along the wire via soap
// CalendarDeserializer parses date string
Calendar deserial = Calendar.getInstance();
Date deserialdate = zulu.parse(serializeddate);
deserial.setTime(deserialdate);
// CalendarDeserializer explicitly sets TZ to GMT
deserial.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat formatter = new SimpleDateFormat(utcformat);
// will print '2005-06-30T19:30:00.000Z'
System.out.println(formatter.format(deserial.getTime()));
// will print '11', should print '7'
System.out.println(deserial.get(Calendar.HOUR));

So I understand that the date gets sent along the wire in UTC format, which strips out timezone information the date was originally encoded with, my question is this: why does the HOUR property of the Calendar object reflect UTC time (ie: 11:30pm) while the formatted time reflects EST time (7:30pm)?

Fun With Java dates

Sorry for not posting anything other than links recently, the kid is wearing me out almost as much as working with Java dates. I haven’t had to work with java.util.Date and java.util.Calendar all that much, most of the time it’s been pretty simple stuff but for whatever reason this past week has been spent waist deep in the Calendar and Date API’s trying to fix a bug in a deployed application. The code I was using looked something like this:

// date entered by user through a combination
// of drop down lists
String strdate = "12/6/1975 5:30 PM"
SimpleDateFormat formatter = new SimpleDateFormat("M/d/yyyy H:m a");
Date eventdate = formatter.parse(strdate);
System.out.println(formatter.format(eventdate));

and out of that I expected to see a date of 12/6/1975 at 5:30pm, it should in fact have printed back the exact same string I entered right? Instead I got:

12/6/1975 5:30 AM

I spent awhile trying different things (am I entering the date wrong? is there something wrong with the timezone? etc..) but eventually noticed that ‘h’ is not the same thing as ‘H’ in the date format string. Using an upper case ‘H’ signifies to the SimpleDateFormat parser that you want it to look for a 24 hour time format (ie: instead of 5:30 I should have used 17:30). In hindsight that’s somewhat obvious, but the tricky thing is that I included the PM designation, so in theory, shouldn’t the SimpleDateFormat have picked up the fact that I wanted a time in PM? I think it should have at least have thrown an exception that says you’ve entered a time in the morning and an AM PM designation of evening. True Date class experts would say at this point that I should have set the SimpleDateFormat to be strict in it’s parsing:

formatter.setLenient(true)

which I did, but it still didn’t throw an exception. Should it have?

Delicious + Movable Type + Java

I’ve been keeping a list of interesting links in a text file for the last couple years and only recently thought better of it and started using del.icio.us to store links. And I wanted to show the links as part of this blog, but I wasn’t satisfied with just including their RSS feed of my links in blog (what happens when / if del.icio.us disappears?) so I whipped up a some code using the delicious-java library and the Apache XML-RPC library that extracts my delicious links from the previous day and then posts them directly my Movable Type blog using the XML-RPC API that comes standard with Movable Type. After putting it up on my server, I wrote a simple shell script that invokes the Java class and then popped that into /etc/cron.daily/ so that it will get called a nightly basis, voila!

#!/bin/bash
cd /usr/apps/delicious/
java -cp commons-codec-1.3.jar:commons-httpclient-3.0-rc2.jar:
commons-logging-1.0.4.jar:delicious-1.6.jar:xmlrpc-1.2-b1.jar:bin net.cephas.blog.DeliciousPoster config.properties

If you’d like to run it your own server, feel free to download the binaries (which include the source code), edit config.properties to match your Movable Type and de.licio.us profiles and scheduled it to run on a nightly basis.

Strategy Design Pattern applied to hashCode() and equals()

The latest issue of the JavaSpecialists newsletter (by Dr. Heinz Kabutz) features a lengthy look at possibility of applying the Strategy design pattern to the equals() and hashCode() methods commonly used in Java. In it he concludes that the equals and hashCode methods autogenerated by IntelliJ Idea are better from a performance standpoint.

If your IDE of choice doesn’t include the ability to autogenerate the bodies of the above mentioned methods, you might also check out the EqualsBuilder, HashCodeBuilder and ToStringBuilder classes in the Jakarta Commons Lang library.

Showing Google’s Web Accelerator the door using Java / ServletFilter

The guys over at 37 Signals posted an explanation of why they think the Google Web Accelerator is a bad idea and a link to a page which shows how you can disable the Google Web Accelerator by analyzing HTTP headers using Ruby. I’m don’t really care to discuss why you think the GWA is good or bad, but in case you think it’s bad, here’s the same thing implemented as a ServletFilter (here’s the same thing for ColdFusion):

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
  throws IOException, ServletException {
  HttpServletRequest httpreq = (HttpServletRequest)req;
  HttpServletResponse httpres = (HttpServletResponse)res;
  if (httpreq.getHeader("X-moz") != null &&
    httpreq.getHeader("X-moz").equalsIgnoreCase("prefetch")) {
    httpres.sendError(HttpServletResponse.SC_FORBIDDEN);
  } else {
    chain.doFilter(req, res);
  }
}

Add the following to your web.xml:

<filter>
  <filter-name>gwa</filter-name>
  <filter-class>com.mycompany.web.filters.GWAFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>gwa</filter-name>
  <url-pattern>/</url-pattern>
</filter-mapping>

and you’re good.

Top 15 Ant Best Practices

Good stuff over at OnJava.com, the article “Top 15 Ant Best Practices” gives 15 recommendations on how you should be using Ant to structure and complete your builds. We’re using most of these already at work; I’d be curious to know the author’s take on the deployment system we’ve developed using Ant. I’ve got Subversion handling source control, so on the production machines, I have a build file called build-production.xml that I invoke from the command line using a batch file:

ant -buildfile build-production.xml

which a) checks out the latest build from Subversion / source control, b) executes the default build file (which is in source control) which compiles the project and then wraps up the result in a war file, c) stops the Tomcat Windows service, d) deletes the existing application from the $tomcat/webapps directory, e) unpacks the application from the .war creates in step b, and then finally f) starts the Tomcat Windows service.

It’s worked out pretty well so far in that it decouples the build file for the project from having to know anything about the environment in which it’s executing so developers can write their own build-development.xml which maybe does something similar to the build-production.xml, but deploys to a different location, or even a different application server.

The wrapper build file (be it build-production.xml, build-local.xml, etc..) can also override properties set in the project build.xml. In our projects, I’ve got the build.xml file conditionally setting properties in log4j.properties using the <propertyfile> tag. There are two such targets: one for production that sets the appender to SMTPAPPENDER and the logging level to ERROR and one for development that sets the appender to STDOUT and the logging level to INFO. Said targets use the if and unless attributes of the <target> tag like so:

<target name="build.resources.debug" if="project.debug">
...

and

<target name="build.resources.production" unless="project.debug">
...

This way, unless I set the project.debug property, the system will always be in ERROR / SMTPAPPENDER mode but developers can override that property at compile time using the wrapper build-local.xml to set the project.debug property, ie:

<ant antfile="build.xml">
  <property name="project.debug" value="true"/>
</ant>

Do you do it better? Can you one up me? I’ve love to hear about it.

ASP, Java, Cookies and URLEncode

One of the bugs I tracked down a couple months ago dealt with the different ways in which ASP and Java handle URL encoding in a cookies. ASP automatically encodes and decodes cookie values (without you telling it too even though it the Server object has a method ‘URLEncode’ which does the same job) while Java requires that you explicity use the URLDecoder and URLEncoder, otherwise it sends the cookie values without encoding them first, which in my case lead to an interoperability problem (one assumes URL encoding of cookie values, one doesn’t).

But then it gets weirder. The encoding that ASP automatically applies is different than the encoding that Java applies. For example, in ASP you’d write something like this to set a cookie with my email address:

Response.cookies("encoded") = "ajohnson@cephas.net"

which would then result in this:

ajohnson%40cephas%2Enet

where in Java you’d have something like this:

String email = "ajohnson@cephas.net";
String encoded = URLEncoder.encode(email, "UTF-8");
res.addCookie(new Cookie("encoded", encoded););

which results in this:

ajohnson%40cephas.net

So why does ASP encode the period as %2E and Java leave it alone? The Microsoft documentation for the ASP Server object contains very little documentation about the URLEncode method other than to say that the URLEncode method

… applies URL encoding rules, including escape characters, to a specified string.

(which could be a teensy bit more helpful, must have been a programmer writing that documentation). On the other hand, the Java URLEncoder class documenation says that the special characters “.”, “-“, “*”, and “_” are not to be encoded according to the HTML specification, which itself cites RFC 1738 which says:

…the special characters “$-_.+!*'(),”, and reserved characters used for their reserved purposes may be used unencoded within a URL.

which seems to me to imply that the ASP Cookie object is wrong (ie: it should leave the period alone in the email address). And beyond that, it’s pretty aggressive in assuming that I want to encode the data in my cookies. Am I missing something? How do other languages (PHP, Python, Perl, etc..) implement the same functionality? Aren’t web applications fun?

Tomcat 5.0.x and ClientAbortException

I’ve got an application deployed on Tomcat 5.0.28 that, when in production, uses log4j with the SMTP appender to send relevant debug / error messages via email. Soon after deploying the application I began receiving messages from the application which contained this stack trace:

java.io.IOException: ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error at org.apache.coyote.tomcat5.OutputBuffer.doFlush(OutputBuffer.java:331) at org.apache.coyote.tomcat5.OutputBuffer.flush(OutputBuffer.java:297) at org.apache.coyote.tomcat5.CoyoteOutputStream.flush(CoyoteOutputStream.java:85) at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(Unknown Source) at sun.nio.cs.StreamEncoder.flush(Unknown Source) at java.io.OutputStreamWriter.flush(Unknown Source) at java.io.BufferedWriter.flush(Unknown Source)....

The stack trace isn’t anything special: you’ll get a ClientAbortException whenever the HTTP client on the other end closes the connection prematurely (ie: before Tomcat has a chance to complete the flush of information to the output stream). The problem is that it pollutes your log file, or in my case, my inbox because I was receiving an email every time one of these errors occurred. My log4j configuration file looked something like this:

log4j.rootCategory=ERROR, SMTPAPPENDER
log4j.appender.SMTPAPPENDER.To=me@mydomain.com
log4j.appender.SMTPAPPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.SMTPAPPENDER=org.apache.log4j.net.SMTPAppender
log4j.appender.SMTPAPPENDER.Subject=[my app] ERROR
log4j.appender.SMTPAPPENDER.BufferSize=512
log4j.appender.SMTPAPPENDER.From=errors@mydomain.com
log4j.appender.SMTPAPPENDER.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
log4j.appender.SMTPAPPENDER.SMTPHost=localhost

which, in log4j parlance, means that I want any messages that are of type ERROR or FATAL sent to me via email. Instead I should have started it off with this:

log4j.rootCategory=FATAL, SMTPAPPENDER
log4j.category.com.mycompany=ERROR, SMTPAPPENDER
...

which translated means that I want any FATAL errors in any package sent to me via the SMTPAPPENDER but any messages of type ERROR or FATAL in the package com.mycompany sent to me as well. This effectively cuts out the unnecessary sending of ClientAbortException messages, while still generating the messages that I want to receive.

(Note: if your problem isn’t with log4j, but instead with your Tomcat log files, check out the debug settings in Server, Service, Engine and Host elements of your Tomcat conf\server.xml.)