Madness and the TableModel

What fol­lows is a lengthy rant about a par­tic­u­larly annoy­ing sit­u­a­tion in some of my code. Pro­gram­mers, please let me know — is it the toolkit that is mad, or is it me? Every­one else, feel free to skip it! :)

For one of my cur­rent Java projects, I am using a toolkit that comes with its own com­plete set of GUI wid­gets based on Swing. Swing… and horror.

I was under the impres­sion that man­ag­ing a table in any sane OO lan­guage goes a bit like this:

  1. Cre­ate a class that roughly rep­re­sents, or at least holds the data for, a row of the table.
  2. Cre­ate a “Table Model” or some other kind of back­ing array to hold objects of that class.
  3. Cre­ate a Table wid­get that uses the table model as its data source.
  4. Hap­pily fil­ter and sort away, know­ing that the model and the view are com­pletely sep­a­rate entities.

And if you should want to seri­alise the data behind the table to disk, and load it again, you can just save and reload the model, then call some update method on the table itself to let it know that the model has changed.

Bring on the horror!

What this toolkit does, allegedly in the name of MVC, is this:

  1. Cre­ate a class that roughly rep­re­sents, or at least holds the data for, a row of the table.
  2. Cre­ate a “Table Model”, but com­pletely ignore it.
  3. Name the columns of the table after the inter­nal mem­ber vari­ables of the class you have created.
  4. Add each object to the table in turn, watch­ing in agony as it extracts the val­ues of those mem­ber vari­ables, and puts them into the table as Strings, dis­card­ing the orig­i­nal object in the process.

But wait, what if those mem­ber vari­ables are (sen­si­bly) pri­vate? Oh, no wor­ries. It uses reflec­tion, each and every time you add an object to the table, to fig­ure out what the get­ter method for that vari­able is called.

And then we come to want­ing to seri­alise the data to disk. Well, that could be a prob­lem — the table doesn’t con­tain the objects we want, only Strings. Oh, no wor­ries. You can give the table a new instance of your object, have it fig­ure out (again, at run­time) which the appro­pri­ate set­ter meth­ods are, and run those to make your object again!

Oh, hey, I hope that object didn’t con­tain any vari­ables that weren’t in the table. ‘Cos if so, you’re not get­ting them back.

Luck­ily in my case, every­thing I care about is shown in the table, which only leaves the attempt to seri­alise it.

Now I want to have a sin­gle class that nicely encap­su­lates this seri­al­is­ing busi­ness for all tables, regard­less of what the objects expressed in that table are. Nor­mally, one could just seri­alise the TableModel and be done with it, but now we need to dynam­i­cally re-make the objects based on what’s in the table.

For a fully encap­su­lated solu­tion, I really want to be able to just pass in the table and have the seri­aliser take care of the dif­fi­cult stuff. i.e. I want to call:

if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
    SerialisedTableFile f = new SerialisedTableFile(fc.getSelectedFile());
    f.save(table);
}

But I can’t, because f.save() now has no idea what kind of object it is sup­posed to be build­ing. So we need to pass f.save() a tem­plate object of the class that it is sup­posed to be build­ing, the only require­ment of which is that it can be cloned to pro­duce the real object that we want to store data from the table in. So we imple­ment the Cloneable inter­face — except that Cloneable doesn’t actu­ally include clone() for some no-doubt genius rea­son. (Not sar­casm, I really do sus­pect that lan­guage design­ers are an order of mag­ni­tude more intel­li­gent than I.)

The end result of all this is that I now have an inter­face that delights in the name ReallyCloneable, which all classes that I wran­gle into tables have to imple­ment. And poor old f.save() looks like this:

public boolean save(Table table, ReallyCloneable itemTemplate) {
    boolean success = false;
    try {
        if (file.exists()) {
            file.delete();
        }
        if (file.createNewFile()) {
            ArrayList<Object> items = new ArrayList<Object>();
            for (int i = 0; i < table.getRowCount(); i++) {
                try {
                    Object o = itemTemplate.clone();
                    table.getItemFromRow(o, i);
                    items.add(o);
                } catch (NoSuchMethodException ex) {
                    Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvocationTargetException ex) {
                    Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeObject(items);
            out.close();
            success = true;
        }
    } catch (Exception ex) {
        Logger.getLogger(SerialisedTableFile.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        return success;
    }
}

I think it’s about time I started buy­ing Bad Code Off­sets by Direct Debit.

De-Li’s Little Mistake

Oh boy. Yet again, a children’s tele­vi­sion pro­gramme has dri­ven me to the brink of insan­ity. I return bear­ing this. The worst thing of all is that I’m sober, though I have the sud­den desire not to be.

If you haven’t watched Way­bu­loo before, you should prob­a­bly expe­ri­ence the sac­cha­rine hor­ror on iPlayer before read­ing this travesty.

Crack-crack-crack, came the noise from the sky.

“Look! Whizz-cracker!” said Lau-Lau, and the other Piplings joined her to watch.

“That not whizz-cracker,” said De-Li.

“Not whizz-cracker?”

“Not whizz-cracker. 90-millimetre anti-aircraft gun.”

“Oh. Pretty 90-millimetre anti-aircraft gun.”

Just then, the Piplings heard the famil­iar chimes of the mys­ti­cal device that some­how con­trolled their lives, and like every other day, they were com­pelled to obey its call.

“Yogo?” asked Yojojo.

“Yogo!”

“Debate finer points of anti-aircraft war­fare after Yogo,” said De-Li.

And off they went.

Lined up in front of the name­less device, each Pipling took their allot­ted turn in the rit­ual, announc­ing a shape into which they would have to con­tort themselves.

“Tree!” said Nok-Tok. And they tried to look like trees.

“Shell!” said De-Li. And they tried to look like shells.

“Mon­key!” said Yojojo, which all the oth­ers thought was prob­a­bly cheat­ing. But the machine was watch­ing, so they did it anyway.

“Fish!” said Lau-Lau. They tried to look like fish.

Then, at long last, the device began to chime its song again. It had been appeased for now, and the Piplings tip­toed qui­etly out of the clear­ing in case it heard them and sum­moned them back to dance once more for its enter­tain­ment.

Back near their houses, the Piplings were look­ing out again at what lay beyond their tiny ver­dant world.

“Why rest of Nara so brown?” asked Nok-Tok.

“Chee­bie last week say End Times com­ing,” said Yojojo. “Chee­bie par­ents say some­thing about ‘Jee-sus’.”

“Lau-Lau won­der why Chee­bies leave, go back to brown place,” said Lau-Lau.

“Chee­bies say some­thing about ‘Soma’ wear­ing off,” said Yojojo. “Chee­bies go back to get more.”

“Oh,” said Nok-Tok. “Make sense.”

Another noise entered the Piplings’ world from across the hori­zon — this time, a more human noise.

“Chee­bies?” asked Yojojo.

“Chee­bies!” exclaimed Lau-Lau. But they turned and looked, and didn’t see quite what they were expect­ing to see.

“Why Chee­bies so old?” asked Nok-Tok.

“Why Chee­bies carry assault rifles?” asked De-Li.

“Play Peeka?” asked Lau-Lau, who was always a lit­tle slow on the up-take.

“Yes, Lau-Lau,” said De-Li. “Play Peeka right now. Play Peeka really, really well.”

So the Piplings hid them­selves in logs and pots and up trees, not sure what to make of the new kind of Chee­bies they had seen.

It soon became clear that, not being five-year-olds asked to look for CGI crea­tures they couldn’t see, the new Chee­bies had some­what of an unfair advan­tage when play­ing Peeka. The Piplings were soon rounded up and made to sit back-to-back in the Yogo clearing.

“What new Chee­bies names?” said Lau-Lau, still not fully grasp­ing the sit­u­a­tion at hand.

One of the Chee­bies stepped forward.

“Sergeant Arrow­smith, US Marine Corp,” he said. “Are you the inhab­i­tants of this place?”

“Lau-Lau not know word in-habbit-uns.”

The sergeant sighed. “Do you live here?”

“Yes!” said Lau-Lau hap­pily. “Piplings live here!”

“And do I under­stand cor­rectly that you are in pos­ses­sion of a machine known as the ‘Any­thing Machine’, which is capa­ble of gen­er­at­ing any object known to the user?”

“Yes! Any­thing machine!”

De-Li kicked Lau-Lau’s ankle sharply, and got a gun pointed at her for her trouble.

“Play nice,” said the Marine on the other end of the gun. He sneered down the barrel.

“You will take us to this machine,” said the sergeant.

The Piplings were marched at gun­point to another clear­ing, where the Any­thing Machine sat.

“Good,” said Arrow­smith. “You will now use this machine to pro­duce for me an LGM-30 Min­ute­man bal­lis­tic mis­sile with a sin­gle war­head, tar­geted at Moscow.”

“No!” gasped De-Li, and wished she hadn’t.

“Nok-Tok not know what that is,” Nok-Tok said. “Machine not work when not know what making.”

“The pink one knows, sir,” said the Marine who’d pointed the gun earlier.

“Pink crea­ture,” said the sergeant, point­ing his own rifle at Lau-Lau. “Make the fuck­ing mis­sile, or I shoot the stu­pid one. No tricks.”

De-Li took one look into Lau-Lau’s wide star­ing eyes, and turned her atten­tion to the machine. A few sec­onds of think­ing, a few sec­onds of trem­bling ground and burn­ing air, and off the mis­sile flew into the sky.

They waited, and waited. Min­utes passed.

Then, over the hori­zon, a bril­liant flash lit up Nara’s sky.

“Good,” said the sergeant, heft­ing the Any­thing Machine onto his shoul­der. “Tie the crea­tures up and make them walk. We’re head­ing back to base.“

Years later, the once-green patch of Nara was as scorched and black­ened as the rest of the land. A gust of wind sep­a­rated the last of the four glit­ter­ing crys­tals from the Yogo device, and it splin­tered into a thou­sand tiny pieces on the ground. Never again would it call the Piplings to per­form for it — the Piplings were free at last. But the Piplings had not been seen since that day they and the Any­thing Machine were taken. If they still some­how lived, they were the last things to live on Nara.

An Ode to Sharepoint

At a loss for other, more pleas­ant sub­jects to blog about, I will instead write about my neme­sis, that being that has brought naught but pain to my life. I speak, of course, of Microsoft Sharepoint.

To upgrade one’s ver­sion of Win­dows — Vista to 7, say — is by and large a pretty pain­less expe­ri­ence for the home user. Office, like­wise — there’s no dread that your Office 2003 files will be com­pletely unopen­able in Office 2007. So why is the poor sysad­min not afforded the same easy upgrade path?

In order to move an exist­ing Share­Point Ser­vices 2 web­site to a new net­work with Microsoft Office Share­point Ser­vices 2007, one must:

  1. Learn more than is healthy about the work­ings of Share­point and IIS (2 days, d10 SAN)
  2. Back up the orig­i­nal site to disk (using stsadm.exe not smigrate.exe, as the lat­ter is bro­ken) (5 hours, 13 GB)
  3. Install Win­dows Server, IIS, SQL Server and Share­point Ser­vices 2 on a new machine (1 hour)
  4. Con­fig­ure said IIS, SQL and Share­point (1 hour)
  5. Restore the Share­point site from disk onto the new machine (>8 hours, >120 GB, d10 SAN, fails unre­cov­er­ably when out of disk space)
  6. Per­form an in-place upgrade to Share­point Ser­vices 3 (Sev­eral hours, 40 GB, may fail unrecoverably)
  7. Back up this site to disk (5 hours, 15 GB)
  8. Con­fig­ure MOSS 2007 on the des­ti­na­tion server (2 hours, 24 Google searches, d10 SAN)
  9. Restore the disk backup to the MOSS 2007 server (5 hours, 40 GB, may fail right at the end if pre­vi­ous step per­formed incor­rectly, d100 SAN if this occurs).
  10. Man­u­ally recre­ate per­mis­sions on every Share­point site since all the users are now part of a new domain (8 hours, d10 SAN)
  11. Per­form a rit­ual to offer Great Cthulhu the souls of Microsoft’s Share­point devel­op­ment team (d30 SAN, remark­ably quick by comparison)

I began this task on Tues­day after­noon as a mildly knowl­edge­able Share­point user with vir­tu­ally no admin expe­ri­ence. By Thurs­day after­noon, I may have been our company’s most expe­ri­enced Sharepoint-wrangler. On Fri­day morn­ing, I started the above pro­ce­dure. We are now on Step 5. 200 peo­ple are expect­ing to have Share­point access tomor­row. They have not a snowball’s chance in R’yleh.