Archive

Archive for March, 2005

Greasemonkey

March 31st, 2005

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.

nick Uncategorized

Hibernate 3.0 Final

March 31st, 2005

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.

nick Uncategorized

Redirecting with parameters

March 29th, 2005
Comments Off

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.

<forward name=”success”
path=”success.jsp?firstName=${firstName}&${lastName}/>

Next, you need a special ActionMapping class. I’ve partially implemented a VelocityActionMapping class below.

import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

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.

nick Uncategorized

Sun Micro President on CNBC

March 28th, 2005

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:

  • Solaris 10 has been downloaded over 1 million times. Mr. Schwartz tried to sell this as an indicator that Sun is gaining traction with the business community, but I have to disagree. How many of those downloads were simply hobbyists trying out the new version of the OS because it was free? It’s doubtful that companies are installing Solaris on their HP or IBM machines because they’re already running HPUX, AIX or Linux.
  • Sun is currently sitting on $7.5bn in cash. As Mr. Schwartz stated, Sun isn’t a bank, so they may be looking to make some acquisitions in the near future. Unfortunately, no specifics were given about the types of acquisitions or the timeframe. (However, our event planning software is for sale. :)

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.

nick Uncategorized

Comments are fixed

March 25th, 2005

Thanks to Steve for telling me the comments were down. Oops.

nick Uncategorized

Migration to eApps

March 23rd, 2005

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.

nick Uncategorized

IDEA Problems on OSX

March 21st, 2005

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:

<key>apple.laf.useScreenMenuBar</key>
<string>false</string>

This seems to have resolved the issue. As an aside, the turnaround time from the people at Intellij was very fast.

nick Uncategorized

Formatting Timestamps in DBUnit

March 19th, 2005
Comments Off

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.

The DataType

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 class CustomTimestampDataType extends AbstractDataType {

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

The DataTypeFactory is pretty simple since I just needed to override a small portion of the base class’s functionality.

public class CustomDataTypeFactory extends DefaultDataTypeFactory {

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.)

Registering the DataTypeFactory

This was the easiest part to figure out:

IDatabaseConnection conn = new DatabaseConnection(c);
conn.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
new CustomDataTypeFactory());

Hopefully this saves someone a good deal of aggravation.

nick Uncategorized

Upgrade to WP 1.5

March 12th, 2005

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.

nick Uncategorized

Coder Needed

March 9th, 2005
Comments Off

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.

nick Uncategorized

Workaround for DBUnit

March 8th, 2005
Comments Off

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:

public class MyColumnFilter implements IColumnFilter {
public boolean accept(String tableName, Column column) {
// since my seating_links table doesn’t have a primary key,
// just return true;
if (tableName != null && tableName.equals(”seating_links”)) {
return true;
}
else {
if (column.getName().equals(”id”)) {
return true;
}
else {
return false;
}
}
}
}

With the implementation done, we just need to tell DBUnit to use it:

IDatabaseConnection conn = new DatabaseConnection(jdbcConn);
conn.getConfig().setProperty(
“http://www.dbunit.org/properties/primaryKeyFilter”,
new MyColumnFilter());

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.

nick Uncategorized

Closing Your Hibernate Session

March 6th, 2005
Comments Off

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:

public Connection close() throws HibernateException {
log.trace(”closing session”);
try {
if (connection==null) {
connect = false;
return null;
}
else {
return disconnect();
}
}
finally {
cleanup();
}
}

Simple enough. The JDBC connection is close if necessary and cleanup() is called. Let’s look at that SessionImpl.cleanup() method.

private void cleanup() {
closed = true;
entitiesByKey.clear();
proxiesByKey.clear();
entityEntries.clear();
arrayHolders.clear();
collectionEntries.clear();
nullifiables.clear();
batchLoadableEntityKeys.clear();
collectionsByKey.clear();
nonExists.clear();
// commented code omitted.
}

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.

nick Uncategorized