Java for Mac OS X 10.6 Update 1 on Software Updates

December 4th, 2009

Apple has released JDK 1.6.0_17 for Mac OS X. 'Nuff said. Have to get it.

Converting a Java Properties Config to a Database Schema

December 2nd, 2009

Today I started the work on a conversion in my webapp's codebase from a Java Properties file-based system to a database-based system because the users were asking for an editing page for their alerts. It's understandable, I created the alerts config simply thinking that I'd be the one adding and removing people from the lists, but in the end, the users wanted to be able to control this themselves. While it's possible to have them edit the Properties object data and then write it out to the file system, that makes for a mess in trying to read it. I've run into that before.

So I needed to make the conversion without a huge impact to the codebase. I started out with a pretty standard Java Properties file:

  # list all the alerts by name that we'll be using
  Alerts=One;Two;Three
 
  # this is the config for alert 'One'
  Alert.One.ClassName=com.bobbeaty.alerts.FlipFlop
  Alert.One.VersionID=20091029
  Alert.One.SilenceInMins=10
  Alert.One.AlertExpr=(pnl > 50000)
  Alert.One.Message="The p/l exceeds $50,000: " + pnl
  Alert.One.ChatTo=drbob;liza;joe
 
  # this is the config for alert 'Two'
  Alert.Two.ClassName=com.bobbeaty.alerts.BaseAlert
  Alert.Two.VersionID=20091111
  Alert.Two.HoldTimeInMins=5
  Alert.Two.AlertExpr=(leadFuture == leadFutureLast)
  Alert.Two.Message="The lead future has not moved in 5 mins: " + leadFuture
  Alert.Two.ChatTo=drbob;liza
 
  # this is the config for alert 'Three'
  Alert.Three.ClassName=com.bobbeaty.alerts.BarrierBreach
  Alert.Three.VersionID=20091011
  Alert.Three.States=T;T;T;T;T;F;F;F;F;F
  Alert.Three.n=-5..5
  Alert.Three.AlertExpr=(pnl > n*50000)
  Alert.Three.Message="The p/l exceeds $50,000: " + pnl
  Alert.One.ChatTo=joe;mimi;nina

OK, they're all made up, but the idea is that this system is very flexible, and while a database-system will be nice to have, it's a lot more work to put together than this. There's the fact that this is an a corporate environment, so you can't just make databases ad hoc, and such.

I thought (briefly) about using SQLite3, but it's Java API is JNI, and that's something I'm just not ready to do. I could have used H2, but that system makes multiple files for a single database, and that's just a little too much clutter for me. I wanted something simple, and easy to work with.

In the end, I had to give in and go with the corporate 'standard': MS SQL Server. OK, it's life. But I then needed to try to come up with a way to easily edit the ChatTo arguments of each alert, and there was also a MailTo property that I just didn't include in this example. Meaning: I couldn't just have a single table with two columns and leave it at that. I needed to have something that was a little better designed than that.

So I started looking at the ways in which I was going to need to use this data. First, I needed to have something that was going to hold the basics of the alert:

  CREATE TABLE Alerts (
    alertID        INT IDENTITY,
    name           VARCHAR(132) NOT NULL,
    description    VARCHAR(4096) NOT NULL,
    classname      VARCHAR(256) NOT NULL,
    versionID      INT NOT NULL,
    active         bit NOT NULL DEFAULT 1,
    CONSTRAINT Alerts_PK PRIMARY KEY (alertID)
  )

I toyed a lot with whether or not to include more of the common attributes, like AlertExpr and a few others, but in the end, I didn't want to have these records fiddled with much. I thought it was better to just activate/deactivate them and that's it. The rest should be set once and then left alone.

Clearly, the versionID is going to be updated, but the reason it's in the table, and Java Properties scheme originally, is that I would make changes to the alerts, and the state would be saved so that on restart it didn't re-alert for the same conditions. This meant that I needed to know when the saved state was stale, and that's where the versionID comes in.

If the versionID changes from what's saved for the named alert, we assume that there's something about the alert that fundamentally changed. That means that the state can't be trusted, and so has to start from scratch. It's just like Java's RMI serialVersionUID, in that regard. Which is, of course, where I got the idea.

The bulk of the parameters for the alerts could be held in a very simple table:

  CREATE TABLE AlertParams (
    alertID        INT,
    setName        VARCHAR(80) NOT NULL,
    name           VARCHAR(132) NOT NULL,
    VALUE          VARCHAR(4096),
    CONSTRAINT AlertParamsPK PRIMARY KEY (alertID, setName, name),
    CONSTRAINT AlertParams_ID_FK FOREIGN KEY (alertID) REFERENCES Alerts (alertID)
  )

Here, I'm just going for the basic key/value pairs that comprise the lion share of the configuration parameters for the alerts. Pretty simple stuff. The last table was a little more of a toughie.

We already had a permissioning table in the database, which had the primary key field of username, which the web app would get from the logged-in user - or a login box, whichever was easier to get. I decided to expand this table and add in the email address of this user so that we could use this one table as the 'target locator' for the alerts. The chat id was the username, and with the email address, all I needed to add was a table that cross-referenced the alerts to the users, and how they wanted to be notified:

  CREATE TABLE AlertRecv (
    alertID        INT,
    setName        VARCHAR(80) NOT NULL,
    username       VARCHAR(80) NOT NULL,
    chat           bit NOT NULL DEFAULT 0,
    email          bit NOT NULL DEFAULT 0,
    CONSTRAINT AlertParamsPK PRIMARY KEY (alertID, setName, username),
    CONSTRAINT AlertParams_ID_FK FOREIGN KEY (alertID) REFERENCES Alerts (alertID)
  )

With this, we could easily get the list of active (or inactive) alerts and a description. That was important to me for the web page. Also, I needed to be able to easily edit the alerts the users were getting, and with this simple cross-reference table, I can build a servlet that will quickly check/uncheck the bit fields in the table for the given user/alert combination.

It took me several hours to come to this design. I tried to simplify it to two tables, or one, and each time I ended up with much harder maintenance tasks to do the things I could have easily done with a text editor and the Properties file. I was really trying to make it pretty simple to get this converted as I didn't have a lot of time to make the conversion and be sure it worked.

After playing with it in my head (and adding in all the values from the Properties file), I was convinced that it would work. Now all I had to do was to build the SQL to get the data out of the tables in a way that it's easy to build a Java Properties object, and then test that I actually had something that worked.

Upgraded to WordPress 2.8.6 at HostMonster

December 2nd, 2009

This morning I was playing with the new WordPress 2 iPhone app - putting my blogs into the app, and realized that I didn't have written down the password to my old journal from UBS. This was a mistake, because I remember forgetting it, then changing it and then today I found where I'd written down the coded message that was the password, but forgot the changed one.

Thankfully, the way to change the password is really very simple - assuming that you have access to the databases that drive the system... and I do. So I changed it back to the original value and left it at that. Now I'm ready to play with the new iPhone app, and it works. Nicely, in fact.

While I was at HostMonster, I noticed that WordPress 2.8.6 was out, and so I upgraded my installs to the latest stable release. They had 2.9b1, but I'm not that hyped to use the beta - I can wait.

It's great tools, well put together, and hosted by a great company. Love this set-up.

How Possible is it to Get Honest Opinions at Work?

December 1st, 2009

I've been asked to give a assessment of the current technical state of the Shop I've been at for about nine months now. In general, I'd say that's not enough time to really understand the ins and outs of the place, but they asked, and so I have to give it my best shot.

As I started formulating my answers to their questions, I started to really wonder if they wanted my answers. I mean, really... I was thinking that many of these questions were the equivalent of re-arranging desk chairs on the Titanic. They were questions, yes, and they had answers, yes, but they were all the wrong questions to be asking. I kept trying to think about a way to phrase the answers to give a politically-correct answer while still expressing my opinions, and just couldn't.

This, of course, made me want to not answer the questions, but that really wasn't the answer, either, as they didn't ask everyone the same questions, so they were clearly looking for my take on the issues, and that meant that I really had to answer these questions, like it or not.

So I decided to take another tack - the direct approach: answer their questions stating that it's not about these details they should be asking, but the bigger questions like centralized versus distributed and diverse... groups providing fixed services, or groups assisting other groups in what they want to do... there are a lot bigger issues that need to be answered before you can really get a good idea of what your current state is.

For example, if you are moving towards a distributed development model, then the only measure that matters is: are the users getting the tools they ask for? If the answer is Yes, then it doesn't matter that there are six different types of databases in use, or that there are a dozen different languages on three different operating systems. It's all secondary to getting the product to the end-user.

But if you're going for a more centralized approach with standards for linux workstations and servers, and a Database Team where lots of decisions are made, then you're not just looking at the end result - you're looking at how the systems work, are deployed, supported, updated... all the things that large, centralized IT departments look at.

Two very different ways of working, and two entirely different ways of delivering a product to a customer. But both can work - it's just important to remember which one you're attempting so as not to confuse the two.

When I looked back at what I'd written, I realized that I really didn't know if they were interested in reading this. Maybe so, maybe not. I decided to end it with a simple closing paragraph

Like I said, I'm not sure this is really what you guys, and the guys asking you to compile this list were looking for. I've only been here nine months. That's not long enough to know a lot of people, or really understand the way things are done, and why.

But I've done my best at giving you an honest, clear, direct answer to your questions. I hope it helps. If not, throw it out. It's all just an opinion.

And in the end, I think it's nearly impossible to get a really un-biased, honest opinion of the technological state of things from within. Everyone has their biases, and while we might try to really remove them, they're there, anyway. I guess it's going to have to do for the list they are compiling. It's the best I can do.

Xcode 3.2.1 is Out on Software Updates

December 1st, 2009

I was really surprised this morning to see that Xcode 3.2.1 was out on Software Updates. The notes on the developer web site say:

Xcode 3.2.1 is an update release of the developer tools for Mac OS X. This release provides bug fixes in gdb, Interface Builder, Instruments, llvm-gcc and Clang optimizer, Shark, and Xcode and must be installed on Mac OS X 10.6 Snow Leopard and higher.

so it appears to have updated components of the Xcode suite as opposed to actually updating the Xcode GUI app. Interesting.

Certainly had to get that.

When Unit Tests Do More Harm than Good

November 30th, 2009

Today I've been up to my neck (again) in the code I inherited that I seem to be bound to with rope and Crazy Glue. This time, I was trying to add to the Flex client a little data that was in at least one of the XML data feeds. Turns out, it wasn't in all three of the necessary XML data feeds, and therein lies my sorry tale of woe today.

The original author believed that, when it came to JUnit tests, if a few are good, a lot are really super, and dozens are really far out. While that might be true, the problem today turned out that the data driving the tests wasn't contained 100% within the JUnit tests, but also took data from the database, etc. and when things changed, as they have in the last few weeks, you run into a lot of broken tests, with no real way to easily fix them.

There are a few things that unit tests - even automated unit tests, are really good for. But they are all basically small, utility class functionality that isn't dependent on date, or time of day, or anything not controlled by the test. When you have things like database configurations, or expiring instruments, then you need to be very careful, because when you come back to the tests after a prolonged period of inactivity, you can get into a really bad place... and that's where I found myself today.

There were errors all over the place, and the one line of code change could not have accounted for the failures. There was something else, but what? The problem with JUnit tests is that you typically only get an error and an exception stack. It's up to you to dig in there to see what the problem is. Sure, the unit tests I've made have a lot of sub-tests in them so that it's pretty darn easy to see what caused the problem, but that's not required. Unfortunately, these tests I was working with were very complex, and no real intermediate results, so it took me about an hour to figure out the problem: database changes.

This is where the unit test concept really fails. It took a simple one-line change and drug it out to more than an hour of work. This is not what the proponents of unit testing put forth. In theory, since I just added one thing, they would say I'd only see a different where that caused an output difference. But that's ideal, and this is the real world.

So I got the changes in, and the tests corrected for the new data in the database, and things are OK for now. But in a few months, it might happen again. A 10 min change drags out into an hour-long test-fixing enterprise. Gack!

MarsEdit 2.4 is Out

November 30th, 2009

MarsEdit 2.4 was released today and the Sparkle notes say the changes are:

  • Improved Squarespace support
    • Support for server drafts
    • Support for tags
    • Support for adding new categories
    • Improved error handling
  • Post editor windows now automatically remember size and screen position
  • Avoid accidental post publishing by disabling the send button when document is not frontmost
  • Improved error messages for misconfigured Tumblr blogs
  • Bug fixes
    • Fixed Flickr image links so they produce valid HTML when align-centered.
    • Fix a Snow Leopard problem that prevented the Save button from enabling immediately when document is edited
    • Fix a rare bug that could cause locked up dialogs on the second launch
    • Fix a crash that could occur when configuring a blog with an extremely weird URL
    • Fix a bug that occurred when an invalid URL was specified for a blog home page
    • Fix a bug that caused duplication of tags on a previously published draft
    • Fix a bug that prevented existing open document from being located when opening a local draft.

I'm very interested in the post windows saving their position, but I'm not certain that it'll solve my issue with the size of the post window. Alas, we'll have to see when I install the update.

UPDATE: nope, the minimum size of the post window is exactly the same. So it goes.

VLC 1.0.3 and HandBrake 0.9.4 Issues

November 30th, 2009

When HandBrake 0.9.4 was announced, I immediately downloaded the new 64-bit version for Snow Leopard, and was excited about the possibilities. It's great to see the move to 64-bits, even though I know it's going to take a long time to get the vast majority of the apps there, it's great to see some open source headliners get there sooner than later.

But I hadn't tried to use HandBrake to rip a DVD since the upgrade. Just no need.

Then I read this off Daring Fireball this morning. Very interesting. I have to wonder how on earth the HandBrake guys built the 64-bit version if they didn't have a 64-bit VLC, and if they didn't have it, what did they use?

I have the FairMount (32-bit) installed, and can use that in the interim while VLC gets around to creating a 64-bit binary. Alternatively, I could just go back to a 32-bit HandBrake, and then move to 64-bit when VLC is there, but that isn't necessary with the FairMount work-around.

I just never imagined that they'd ship something that can't work. Very odd. If it turns out that the work-around takes too much time, then I'll fall back to a 32-bit HandBrake. But if I'm lucky, the 64-bit VLC will be out before I need to rip another DVD.

Bean 2.4.2 is Out

November 30th, 2009

While I haven't had need to use it in a long while, Bean 2.4.2 was released today and I decided to pick up a copy. There are quite a few Snow Leopard fixes in this release, which is great news. I like having a fast, lightweight alternative to Pages that's capable of dealing with Microsoft Word files. Nice to have in my pocket.

MacSpice 2.10.22 is Out

November 30th, 2009

Being an Electrical Engineer, I've always had a soft spot for SPICE, and the Mac port: MacSpice is a great little version that can get you some really nice performance and top-notch simulation results on inexpensive hardware. Today I noticed that MacSpice 2.10.22 was out and there were a few nice additions and fixes. While I'd really like to see a graphical client for SPICE, but I don't really have to have it, and the commercial ones are nice, but far too expensive for playing with.