In one of my programs, I needed to calculate the difference between 2 dates in days. Ironically I could not find any method for the same in the core Java API of Calendar and Date.
So, I decided to write a utility method for the same. But then it struck me that I need to take care of DST and leap seconds. Googling around led me to a interesting journey of Atomic clocks, Quartz clocks, leap secs, etc.
Some cool links to get started with the concepts:
http://www.xmission.com/~goodhill/dates/deltaDates.html
http://www.exit109.com/%7Eghealton/y2k/yrexamples.html
Finally the algorithm I used to calculate the days-between 2 dates was:
1. Get the UTC time of both dates (imp if dates are from different locales)
2. Set the time on both dates as 12 noon. (good practice as it avoids DST and leap sec issues)
3. Calculate the milli-sec difference between the dates.
4. Divide the difference with 24*60*60 and take a Math.abs
Tuesday, February 27, 2007
Thursday, February 22, 2007
Programming to interfaces
We all know that as a good programming practice we should always program against interfaces and not actual subclasses. That's the reason when libraris are designed, they return an interface to an collection and not the actual implementation class.
Recently the developers in my team were facing a problem regarding ClassCast exceptions using Spring JDBC when they upgraded the commons-collection package. After analysis of the source code, it was revealed that the developer was type-casting the List interface to a solid class, i.e. the LinkedHashMap class.
Spring JDBC decides at runtime what Map implementation should be returned. If the latest version of jakarta-commons is available in the classpath, an implementation of org.apache.commons.collections.map.ListOrderedMap is returned, else java.util.LinkedHashMap is used.
Hence the program would start throwing ClassCastExceptions ...See log below comparing what happens depending on the classpath jars:
-- When the latest version of jakarta-commons is not there in the classpath
16-Feb-2007 14:29:47 DEBUG (CollectionFactory.java:142)
org.springframework.core.CollectionFactory -
Falling back to [java.util.LinkedHashMap] for linked case-insensitive map
-- When the latest version of jakarata commons is present
16-Feb-2007 14:31:36 DEBUG (CollectionFactory.java:138) org.springframework.core.CollectionFactory -
Creating [org.apache.commons.collections.
map.ListOrderedMap/CaseInsensitiveMap]
Moral of the story: Always program to interfaces.
Recently the developers in my team were facing a problem regarding ClassCast exceptions using Spring JDBC when they upgraded the commons-collection package. After analysis of the source code, it was revealed that the developer was type-casting the List interface to a solid class, i.e. the LinkedHashMap class.
Spring JDBC decides at runtime what Map implementation should be returned. If the latest version of jakarta-commons is available in the classpath, an implementation of org.apache.commons.collections.map.ListOrderedMap is returned, else java.util.LinkedHashMap is used.
Hence the program would start throwing ClassCastExceptions ...See log below comparing what happens depending on the classpath jars:
-- When the latest version of jakarta-commons is not there in the classpath
16-Feb-2007 14:29:47 DEBUG (CollectionFactory.java:142)
org.springframework.core.CollectionFactory -
Falling back to [java.util.LinkedHashMap] for linked case-insensitive map
-- When the latest version of jakarata commons is present
16-Feb-2007 14:31:36 DEBUG (CollectionFactory.java:138) org.springframework.core.CollectionFactory -
Creating [org.apache.commons.collections.
map.ListOrderedMap/CaseInsensitiveMap]
Moral of the story: Always program to interfaces.
Starting a java daemon on Solaris
We were using Quartz as a scheduler to run our cron-like java programs on Solaris. Quartz gives us much more flexibility than the cron-tab, as we can add listeners and plug-ins.
Normally, when we exit a shell, all the programs that were started in the shell are terminated.
To avoid this, we made use of the 'nohup' command that keeps running the program even if the shell is closed. nohup = no-hang-up.
Also important thing to remember is that if the Std. input is kept open, then the shell does not exit. In the Java program, the main method automatically opens the Std input stream. Hence we need to close it. Here is the complete syntax.
nohup java com.domain.main_class <&- &
The ampersand at the end, starts the program in the background. nohup creates a file called nohup.log that contains the output to the standard stream.
Normally, when we exit a shell, all the programs that were started in the shell are terminated.
To avoid this, we made use of the 'nohup' command that keeps running the program even if the shell is closed. nohup = no-hang-up.
Also important thing to remember is that if the Std. input is kept open, then the shell does not exit. In the Java program, the main method automatically opens the Std input stream. Hence we need to close it. Here is the complete syntax.
nohup java com.domain.main_class <&- &
The ampersand at the end, starts the program in the background. nohup creates a file called nohup.log that contains the output to the standard stream.
Thursday, February 15, 2007
Daylight saving time
Being brought up in India, we never have to worry about Daylight saving chores. But its very interesting and also important for any system designer to know all about DST.
More info at this link : http://webexhibits.org/daylightsaving/
DST also comes into play when we schedule jobs using cron or Quartz.
For e.g. In the US, many states implement DST at 2 a.m.
If we have a job scheduled at 2.15 am, then it won't be fired on the day when the cock is shifted ahead from 2.00 to 3.00 am :)
More info at this link : http://webexhibits.org/daylightsaving/
DST also comes into play when we schedule jobs using cron or Quartz.
For e.g. In the US, many states implement DST at 2 a.m.
If we have a job scheduled at 2.15 am, then it won't be fired on the day when the cock is shifted ahead from 2.00 to 3.00 am :)
Monday, February 12, 2007
Spring JDBC quirks
Spring JDBC's JdbcTemplate provides us with utility methods that return scalar values. For e.g. methods such as queryForObject, queryForInt, queryForLong etc. These methods are useful when we need to obtain a single row or single column from the database.
But there is a caveat here. Each of these 'scalar' methods throw an IncorrectResultSizeDataAccessException if the there are no results or more than one row in the resultset.
For e.g. if there is a valid business condition that no rows may be returned for a particular query, then we need to handle this exception and return null. The other option is to use the generic query methods that return a list. For empty resultsets we can return an empty list.
But there is a caveat here. Each of these 'scalar' methods throw an IncorrectResultSizeDataAccessException if the there are no results or more than one row in the resultset.
For e.g. if there is a valid business condition that no rows may be returned for a particular query, then we need to handle this exception and return null. The other option is to use the generic query methods that return a list. For empty resultsets we can return an empty list.
Printing Stack Trace in Java
Quite often, developers use the statement exception.printStackTrace() to print the stack trace on to the console. It is important to remember that printStackTrace method prints the stack trace to the System.Err stream and not the System.Out stream.
Due to this, there are a lot of exception stacks getting printed in the System.Err files on the application server, but we do not see any trace of it in the Log4J files or System.out files !!!!
As a best practice, I strongly recommend not using e.printStackTrace() in production code. If the project is using Log4J, then the method 'Logger.error(message, exception)' would print the stack trace to all the registered appenders.
Alternatively, I have written a utility method that would return the stack trace as String. Please use this method if you want to get a stacktrace as a string for more flexibility in printing.
---------------------------------------------------------
/**
* Gets the exception stack trace as a string.
* @param exception
* @return
*/
public String getStackTraceAsString(Exception exception)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.print(" [ ");
pw.print(exception.getClass().getName());
pw.print(" ] ");
pw.print(exception.getMessage());
exception.printStackTrace(pw);
return sw.toString();
}
---------------------------------------------------
But what if there is already production code that uses e.printStackTrace() and System.out and you want to redirect them to the Log Files. In that case, we can make use of the System.setOut() and System.setErr() methods. Also try the LoggingOutputStream class in the contribs/JimMoore folder of the log4j release.
Due to this, there are a lot of exception stacks getting printed in the System.Err files on the application server, but we do not see any trace of it in the Log4J files or System.out files !!!!
As a best practice, I strongly recommend not using e.printStackTrace() in production code. If the project is using Log4J, then the method 'Logger.error(message, exception)' would print the stack trace to all the registered appenders.
Alternatively, I have written a utility method that would return the stack trace as String. Please use this method if you want to get a stacktrace as a string for more flexibility in printing.
---------------------------------------------------------
/**
* Gets the exception stack trace as a string.
* @param exception
* @return
*/
public String getStackTraceAsString(Exception exception)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.print(" [ ");
pw.print(exception.getClass().getName());
pw.print(" ] ");
pw.print(exception.getMessage());
exception.printStackTrace(pw);
return sw.toString();
}
---------------------------------------------------
But what if there is already production code that uses e.printStackTrace() and System.out and you want to redirect them to the Log Files. In that case, we can make use of the System.setOut() and System.setErr() methods. Also try the LoggingOutputStream class in the contribs/JimMoore folder of the log4j release.
Monday, February 05, 2007
Redirecting system.out, system.err to a file on Unix/Solaris boxes
It is simple to redirect a process output to a standard file using the '>' operator.
But if you also want the std error to go to a file, then you need to type:
java className>file 2>&1
To understand what the above command means, it is imp to note that the shell reads arguments from left to right. The shell sees >file first and redirects stdout to file. Next 2>&1 sends fd2 (stderr) to the same place fd1 is going - that's to the file.
But if you also want the std error to go to a file, then you need to type:
java className>file 2>&1
To understand what the above command means, it is imp to note that the shell reads arguments from left to right. The shell sees >file first and redirects stdout to file. Next 2>&1 sends fd2 (stderr) to the same place fd1 is going - that's to the file.
Epoch - The start of time for computing
Recently working on a XML data feed program, I had to handle empty date XML elements. I wondered as to what date I can put into the database - the start of time?. What is the start of time used by computer systems?
As Java programmers we all know that the Date, Calendar classes in Java use January 1, 1970 as the start of 'time'. This is known as Epoch. Wikipedia defines epoch as follows:
"The epoch serves as a reference point from which time is measured. Days, hours and other time units are counted from the epoch, so that the date and time of events can be specified. Events that took place earlier can be dated by counting negatively from the epoch."
There are different epocs used by different systems:
- Unix and Java use Jan 1, 1970
- MS DOS uses Jan 1, 1980
- Excel and Lotus = Dec 31, 1899
More info can be found here.
As for me, I decided to use the Java Epoc for my program :)
As Java programmers we all know that the Date, Calendar classes in Java use January 1, 1970 as the start of 'time'. This is known as Epoch. Wikipedia defines epoch as follows:
"The epoch serves as a reference point from which time is measured. Days, hours and other time units are counted from the epoch, so that the date and time of events can be specified. Events that took place earlier can be dated by counting negatively from the epoch."
There are different epocs used by different systems:
- Unix and Java use Jan 1, 1970
- MS DOS uses Jan 1, 1980
- Excel and Lotus = Dec 31, 1899
More info can be found here.
As for me, I decided to use the Java Epoc for my program :)
Subscribe to:
Posts (Atom)