Greasemonkey
Because of this rock I’ve been living under, I hadn’t heard about the Firefox extension called Greasemonkey. But that’s okay because Simon explains what it’s up to.
Uncategorized
Because of this rock I’ve been living under, I hadn’t heard about the Firefox extension called Greasemonkey. But that’s okay because Simon explains what it’s up to.
Uncategorized
Congrats to the Hibernate team on releasing 3.0 today. You can get it here.
I wish I could tell you that my upgrade from 2.x to 3.0 has been painless, but it’s taken the better part of a day so far.
Uncategorized
A common question on the struts-user mailing list is how to pass request parameters to a redirect page. Since a redirect is issued to the client browser with an HTTP 302, you lose any request-scoped variables. The only method you have is appending properties to a URL, which can be ugly and tedious. One possible way to get around this problem is to create an ActionForward with a Velocity template in the path.
Next, you need a special ActionMapping class. I’ve partially implemented a VelocityActionMapping class below.
import java.io.StringWriter;
import java.util.Map;
public class VelocityActionMapping extends ActionMapping {
public ActionForward findForward(String name, Map params) {
ActionForward fwd = super.findForward(name);
if (fwd == null) {
return null;
}
else {
ActionForward velocityFwd =
new ActionForward(fwd);
String path = evaluateTemplate(fwd.getPath(), params);
velocityFwd.setPath(path);
return velocityFwd;
}
}
public String evaluateTemplate(String vtl, Map params) {
VelocityContext context = new VelocityContext(params);
StringWriter writer = new StringWriter();
try {
Velocity.evaluate(context, writer, “ad hoc”, vtl);
}
catch (Exception e) {
throw new RuntimeException(e);
}
return writer.toString();
}
}
After that, you just need to update your struts-config.xml to use the new VelocityActionMapping class and call the new findForward(…) method.
Let me know if this looks interesting and I’ll make the rest of the code available.
Uncategorized
Sun Microsystems President and COO Jonathan Schwartz was interviewed on CNBC this afternoon. He didn’t have much in the way of concrete statements, and the interviewer failed to push him. (It wasn’t Squawkbox, after all.) Sun has spent $9bn on research and development, and I don’t believe they have much to show for it. Their numbers are still pathetic, including their share price. My ranting aside, Schwartz did give two numbers that are worth talking about:
I’ve never been a fan of Schwartz and I feel that he’s only hurt Sun’s future prospects. His performance during the interview did little to improve my confidence. It will be interesting to see how the market responds in after hours trading.
Uncategorized
Thanks to Steve for telling me the comments were down. Oops.
Uncategorized
In an effort to reduce the number of machines I need to maintain, I’m in the process of moving my sites over to eApps. So far, I’m very happy with the service and the speed at which it’s provided.
I think the only tricky thing is going to be moving the various subversion repos over to the new machine. Once that’s done, however, I’ll be all set.
Uncategorized
Occasionally IDEA will stop responding to menu events, and the application menu is greyed out. I’m told this is a bug in Apple’s JDK, which I’m inclined to believe since I have the same problem with JEdit. I contacted the Intellij folks about it and was told to disable the screen menu bar with the following change to IDEA’s Info.plist file:
This seems to have resolved the issue. As an aside, the turnaround time from the people at Intellij was very fast.
Uncategorized
Another recent problem I’ve had with DBUnit has been the mandated format for TIMESTAMP columns in the test data. You’re forced to define TIMESTAMPs as yyyy-MM-dd HH:mm:ss.fffffffff, which is great if you need that level of granularity. I don’t, and revisiting all of my test data was too cumbersome. So I set about changing the format for my TIMESTAMPs.
Each data type is represented by an implementation of the DataType class. DBUnit’s existing TimestampDataType class is what enforces the verbose format. By creating a new implementation of that class, I was able to define multiple TIMESTAMP formats, using the SimpleDateFormat class.
public CustomTimestampDataType() {
super(”TIMESTAMP”, Types.TIMESTAMP, Timestamp.class, false);
}
public Object typeCast(Object value) throws TypeCastException {
if (value == null || value == ITable.NO_VALUE) {
return null;
}
if (value instanceof java.sql.Timestamp) {
return value;
}
if (value instanceof java.util.Date) {
java.util.Date date = (java.util.Date) value;
return new java.sql.Timestamp(date.getTime());
}
if (value instanceof Long) {
Long date = (Long) value;
return new java.sql.Timestamp(date.longValue());
}
if (value instanceof String) {
String stringValue = (String) value;
// Probably a java.sql.Date, try it just in case!
if (stringValue.length() == 10) {
try {
long time = java.sql.Date.valueOf(stringValue).getTime();
return new java.sql.Timestamp(time);
}
catch (IllegalArgumentException e) {
// Was not a java.sql.Date, let Timestamp handle this value
}
}
try {
String formats[] =
{”yyyy-MM-dd HH:mm”,
“yyyy-MM-dd HH:mm a”,
“yyyy-MM-dd HH:mm:ss.fffffffff”};
Timestamp ts = null;
for (int i = 0; i < formats.length; i++) {
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
Date date = sdf.parse(stringValue);
ts = new Timestamp(date.getTime());
return ts;
}
catch (ParseException e) {
}
}
}
catch (IllegalArgumentException e) {
throw new TypeCastException(value, this, e);
}
}
throw new TypeCastException(value, this);
}
public boolean isDateTime() {
return true;
}
public Object getSqlValue(int column, ResultSet resultSet)
throws SQLException, TypeCastException {
Timestamp value = resultSet.getTimestamp(column);
if (value == null || resultSet.wasNull()) {
return null;
}
return value;
}
public void setSqlValue(Object value, int column, PreparedStatement statement)
throws SQLException, TypeCastException {
statement.setTimestamp(column, (java.sql.Timestamp) typeCast(value));
}
}
Unfortunately, DBUnit doesn’t allow me to simply register this new class. Instead, I have to go about creating a DataTypeFactory.
The DataTypeFactory is pretty simple since I just needed to override a small portion of the base class’s functionality.
public DataType createDataType(int sqlType, String sqlTypeName)
throws DataTypeException {
if (sqlType == Types.TIMESTAMP) {
return new CustomTimestampDataType();
}
else {
return super.createDataType(sqlType, sqlTypeName);
}
}
}
Next, I had to tell DBUnit about the new factory. (You can register new factories but not individual data types.)
This was the easiest part to figure out:
Hopefully this saves someone a good deal of aggravation.
Uncategorized
So I finally made the upgrade to Wordpress 1.5. I’m not happy with the theme, but I’m pressed for time so I doubt I’ll be able to change it in a timely fashion. I’m also trying out the bot-check plugin to see if I can disable comment moderation in the near future.
Uncategorized
Oddly enough, I’m looking for a Java developer for a few months of work. This is in the Phoenix/Tempe area for an existing project. The general technologies I’m looking for are web dev (Struts is a plus) and relational database knowledge (Hibernate is a plus). I don’t care which databases you’ve worked with, as long as you understand good programming practice. WSAD is a plus, as is ClearCase. The rate is $50-$60/hr, depending on competence, not experience. If you’re interested, send me an email at info at systemmobile dot com.
Update: I should also mention that you don’t need to be in the Phoenix area for this gig, but travel will be required.
Uncategorized
DBUnit has an odd requirement for tables used for testing: Each table must have a primary key defined. If you don’t have a primary key for a given table when you’re loading data, you’ll get an exception. To work around this exception, you have to create your own implementation of DBUnits IColumnFilter interface and register it. The following code listing has a trivial implementation of the interface:
With the implementation done, we just need to tell DBUnit to use it:
This is a little long-winded for something that should be trivial. However, I have this code in my base test case class so I don’t need to duplicate it throughout the test code.
Uncategorized
There seems to be some confusion about what exactly happens when you close your Hibernate Session instances. I present the close() method here.
The Session interface is implemented by the SessionImpl class. When you call Session.close(), the following happens:
Simple enough. The JDBC connection is close if necessary and cleanup() is called. Let’s look at that SessionImpl.cleanup() method.
Here, they’re setting the closed boolean to true and clearing out the state maintained by the SessionImpl class. This wipes out the history of what you’ve done with a Session instance. If you just want to close the open JDBC connection and keep the state of the Session intact, just call Session.disconnect(). When you need to reconnect the Session, call Session.reconnect().
Hopefully, that will clear up some confusion.
Uncategorized