Viking Hammer

Hibernate: Skipping Criteria’s abstractions for HQL’s flexibility and speed

I was writing a task that would run periodically and clear out old records from a database table, so the database doesn’t grow unbounded; it’s fortunate that we don’t need to keep a perfect historical record in this table, and it sees a lot of inserts.

We’re using Java/MySQL/Hibernate here.

My first pass used the standard “get them and delete them” pattern that seems so common when using Hibernate’s Criteria API.

public List<Record> getByNameBeforeDate(String name, Date before) {
    return getHibernateTemplate().getSessionFactory().getCurrentSession()
        .createCriteria(Record.class)
        .add(Restrictions.eq("name", name))
        .add(Restrictions.lt("recordedAt", before))
        .list();
}

...

List<Record> recordsToDelete = recordDao.getByNameBeforeDate(name, date);
for (Record record : recordsToDelete) {
    recordDao.delete(record);
}

But I quickly became afraid of the way that would perform. I don’t have enough data in my development environment to see what would happen when it runs, but it didn’t take a whole lot of imagination to see it using a ton of memory, being too slow, and executing quite a few queries.

I wanted something better. I couldn’t figure a way around Criteria’s limitations, so I went with HQL instead.

public int deleteByNameBeforeDate(String name, Date before) {
    String hql = "delete from Record where name = :name and recordedAt < :before";
    Query query = getHibernateTemplate().getSessionFactory().getCurrentSession().createQuery(hql);
    query.setString("name", name);
    query.setDate("before", before);
    int rowCount = query.executeUpdate();
    return rowCount;
}

...

int count = recordDao.deleteByNameBeforeDate(name, date);

With the first method, memory use and queries executed were both O(N). With the second method, memory use should be close to constant (depending on what the database does), and queries executed will always be 1.

So don’t be afraid to ditch Criteria where it makes sense; HQL can be much more flexible in certain cases. It gets us much closer to what we’d do if we weren’t using Java, which is just executing a single SQL query: all the fancy abstractions that Hibernate’s Criteria API provides don’t help with that.

And remember to pay attention to the memory/speed characteristics of what you write. It can make a big difference.


Switching between different views in a Playbook app

In my Playbook apps, I often need to switch from one view to another. A common example is that I’m on my base screen that you see when you first launch the app, and you want to add or edit something in the list of items I’m showing you. I’ll try to explain how I’ve done that.

My add/edit screen is a subclass of View; in this case, I call it FamilyEditor.

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        title="Family Editor"
        xmlns:mx="library://ns.adobe.com/flex/mx">

To switch from the base view to FamilyEditor, I need to call navigator.pushView(). Sometimes I want to add a new Family, and other times I want to edit an existing one. So I want to pass a Family to FamilyEditor. I do that by connecting these event handlers to my add/edit buttons:

private function addButtonClickHandler(event:Event):void {
    navigator.pushView(FamilyEditor, new Family());
}

private function editButtonClickHandler(event:Event):void {
    navigator.pushView(FamilyEditor, familiesList.selectedItem);
}

When you use MXML to extend a class, you don’t get to define a constructor. So when you pass your argument into FamilyEditor, you need to override the data setter (just like you would when creating an item renderer).

public override function set data(value:Object):void {
    super.data = value;
    family = Family(value);
    ...
}

I can do my thing in the FamilyEditor view, and when I’m done I just call navigator.popView(). I do that when the user cancels, and when they click save I do it after performing the necessary saving operations. Here’s the cancel button’s event handler:

private function cancelButtonClickHandler(event:Event):void {
    navigator.popView();
}

That goes back to the view the user was on before they got here.

So that’s simple enough, I think. And you can do a whole lot with it.


Playbook/Flex: Delete button inside a List ItemRenderer

I’m doing a bit more Playbook development, and I wanted to be able to delete items out of a List with a button inside each item. The way to do that is by defining your own ItemRenderer.

Here’s what it looks like:

Item renderer with a delete button

I’m using a ModelLocator just like the one I described in my last post about Playbook development, and I’ve defined a new MXML component that displays the name of the object and has a delete button in it.

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                xmlns:s="library://ns.adobe.com/flex/spark" 
                autoDrawBackground="true" xmlns:mx="library://ns.adobe.com/flex/mx">

    <fx:Script>
        <![CDATA[
            import model.ModelLocator;
            import model.Family;

            [Bindable]
            private var modelLocator:ModelLocator = ModelLocator.getInstance();

            [Bindable]
            private var family:Family;

            public override function set data(value:Object):void {
                super.data = value;

                family = Family(value);
            }

            private function deleteClickHandler(event:Event):void {
                modelLocator.removeFamily(family);
            }

        ]]>
    </fx:Script>

    <fx:Binding source="family.selected" destination="selectedCheckBox.selected" twoWay="true" />

    <s:HGroup width="100%" verticalAlign="middle" paddingRight="10">
        <s:CheckBox
            id="selectedCheckBox" />
        <s:Label width="100%" text="{family.name}" />
        <s:Button
            click="deleteClickHandler(event)"
            height="50" width="50"
            icon="@Embed(source='images/delete.png')" />
    </s:HGroup>

</s:ItemRenderer>

And using the ItemRenderer (which I’ve named FamilyRenderer in this case, and placed in the views.renderer package where I’ve been putting all my renderers) is very simple.

<s:List
    id="familiesList"
    itemRenderer="views.renderer.FamilyRenderer"
    width="100%" height="100%" />

The ModelLocator.removeFamily method is about what you’d expect:

public function removeFamily(family:Family):void {
    var index:int = families.getItemIndex(family);
    families.removeItemAt(index);
    flush();
}

What happens here is that when you click that delete button, we call out to the ModelLocator and tell it to remove the item that’s currently being rendered. Since the entire ModelLocator is [Bindable], the change to ModelLocator.persons will update what’s displayed in the familiesList, and the ItemRenderer on which you just clicked the delete button disappears.


Snippets and patterns from my first Playbook app

This week I heard about RIM’s plan to build a developer base for the upcoming Playbook tablet — give a free one to everyone who builds an app and gets it accepted into their App World. Now, I don’t know how stringent their review policy is, but the promise of a free tablet is enough to get me to write an app. I decided to port one of my iPhone apps, Actioneer, which has seemed constrained by the size of the phone’s screen; hopefully an app that’s good enough for Apple’s App Store is good enough for RIM’s App World.

The app is done now. The basic concept of the app is that you can define a set of “Actions” that you’ll perform from time to time; when you click “Perform” on one of them, it records the time the action was performed, and it will display a history of all the times each action was performed. Darlene uses it to help her remember how often Rusty craps, which apparently is valuable information for a mother.

There are a few interesting things in the implementation of the app, that I want to highlight here. Playbook apps are written in Flex, and I’ve used the Cairngorm library pretty extensively in the past — I had thought it was a little heavy, and I took this as an opportunity to take some ideas from it but make it a little bit lighter and easier to deal with.

I start with the ModelLocator, which is a concept stolen from Cairngorm. It’s a singleton that stores data that’ll be shared between different views — but I’ve added the concepts of persisting that data to local storage, as well as dispatching events. As I get around to larger apps, I’ll probably find it necessary to split the persistence code out into another class, but I think the event dispatching works better here than in Cairngorm’s FrontController.

Here’s my ActionModelLocator:

package model
{
    import events.ActionAddedEvent;

    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.net.SharedObject;

    import mx.collections.ArrayCollection;

    [Bindable]
    public class ActionModelLocator extends EventDispatcher
    {
        private static var instance:ActionModelLocator;

        private var sharedObject:SharedObject;

        public var actions:ArrayCollection;

        public function addAction(action:Action):void {
            actions.addItem(action);
            dispatchEvent(new ActionAddedEvent(action));
            flush();
        }

        public function removeAction(action:Action):void {
            var index:int = actions.getItemIndex(action);
            if (index >= 0) {
                actions.removeItemAt(index);
                flush();
            }
        }

        private function flush():void {
            var serializedActions:ArrayCollection = new ArrayCollection();
            for each (var action:Action in actions) {
                serializedActions.addItem(action.serialize());
            }
            sharedObject.data.actions = serializedActions;
            sharedObject.flush();
        }

        private function load():void {
            actions = new ArrayCollection();
            if (sharedObject.size > 0) {
                for each (var obj:Object in sharedObject.data.actions) {
                    actions.addItem(Action.deserialize(obj));
                }
            }
        }

        public function ActionModelLocator()
        {
            if (instance != null) {
                throw new Error("Can only be one ActionModelLocator");
            }

            sharedObject = SharedObject.getLocal("Actioneer_Actions");
            load();

        }

        public static function getInstance():ActionModelLocator {
            if (instance == null) {
                instance = new ActionModelLocator();
            }
            return instance;
        }
    }
}

The constructor, which can only be executed once, initializes the sharedObject variable by grabbing a local persistence object and calling load(), which will pull any data out of the local datastore and deserialize it for use. I’ll get to the serialization/deserialization in a second, but first I want to finish explaining the ModelLocator.

The converse of load() is flush(), which serializes all of our model objects and saves them to the SharedObject, and takes the extra step of flushing the SharedObject to disk. This last step probably isn’t necessary — the SharedObject is supposed to flush to disk when it needs to, like when the app is quit or event pushed from memory in the background. I don’t trust that at the moment, though, so maybe once I actually have a Playbook I can investigate whether that works, and adjust this later.

I have addAction/removeAction methods that handle adding and removing Action objects from the list and calling the aforementioned flush() method. The addAction method also has the added benefit of dispatching an ActionAddedEvent, because we’ll want to be able to add an Action in one view and respond to an Action being added in another view.

The events themselves are very simple; they extend the basic flash.events.Event class, and all they need to do is define a name (which needs to be public/static and unique per VM) and encapsulate any objects that you want to pass along in the event. Here’s the ActionAddedEvent:

package events
{
    import flash.events.Event;

    import model.Action;

    public class ActionAddedEvent extends Event
    {
        public static const NAME:String = "AddActionEvent";

        public var action:Action;

        public function ActionAddedEvent(action:Action, type:String=NAME, bubbles:Boolean=false, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
            this.action = action;
        }
    }
}

To respond to an event, you just need to add an event listener to the model locator that will dispatch the events. I did mine in the creationComplete handler of my views:

private function onCreationComplete(event:Event):void {
    actionModelLocator.addEventListener(ActionAddedEvent.NAME, function(e:ActionAddedEvent):void {
        ...
    });
}

Finally, I’ll show you the Action model object, which holds the data for each action and handles serialization/deserialization of each action.

package model
{
    import mx.collections.ArrayCollection;

    [Bindable]
    public class Action
    {
        public var name:String;
        public var history:ArrayCollection;

        public function Action(name:String=null, history:ArrayCollection=null)
        {
            this.name = name;
            if (history == null) {
                history = new ArrayCollection();
            }
            this.history = history;
        }

        public function perform():void {
            history.addItemAt(new Date(), 0);
        }

        public function deleteHistory(date:Date):void {
            var index:int = history.getItemIndex(date);
            if (index >= 0) {
                history.removeItemAt(index);
            }
        }

        public function serialize():Object {
            var obj:Object = {
                name: this.name,
                history: this.history
            };
            return obj;
        }

        public static function deserialize(obj:Object):Action {
            return new Action(obj.name, obj.history);
        }
    }
}

I’d heard a rumor that when you save something to SharedObject, it would serialize ActionScript objects for you, so you’d be able to put them in and pull them out easily. No such luck, however. When I tried to save an Action directly into the SharedObject, it came back out as a generic Object that couldn’t be cast or coerced into an Action — it was stuck. So my serialize/deserialize methods convert the Action into and out of an Object that the SharedObject persistence can use. (Note: the serialize() method may not be totally necessary in this case, but I’m using it to demonstrate a pattern I expect to have to use in general.)

Hopefully that gives you some ideas as you build your own Playbook apps. I’m not thrilled with the level of documentation, and the FlashBuilder IDE keeps steering me away from components I would normally use that aren’t “mobile optimized,” so I have a lot more to learn when it comes to working with MXML in my Playbook apps.

And I’m curious to see how much of this stuff I can pull out into libraries as I build my next Playbook apps.


Random Gift Assignment

This year, my family is thinking about changing the way they exchange gifts between each other. The basic idea is that rather than having every single person give a gift to every other person, each person would only give a gift to one other person. Saves money, makes things easier, seems like a positive all around. But how to choose who gives something to whom?

Enter the Gifter program. It takes a list of names, assigns each one as giving a gift to one other, and outputs the assignments. Each name only appears once as a gift-receiver, and it doesn’t allow any name to be assigned to itself — it kind of defeats the purpose if you get to give a gift to yourself, doesn’t it?

class Gifter
    def initialize(names)
        @names = names
    end

    def unused_names(all_names, used_names)
        all_names - used_names
    end

    def random_name(names)
        names[rand(names.size)]
    end

    def random_name_excluding(names, exclude)
        if names.size == 1 and names[0] == exclude
            raise "Cannot assign #{exclude} to self"
        end
        name = self.random_name(names)
        while name == exclude
            name = self.random_name(names)
        end
        name
    end

    def try_to_give
        gifts = {}
        @names.each do |name|
            gifts[name] = self.random_name_excluding(self.unused_names(@names, gifts.values), name)
        end
        gifts
    end

    def give
        if @names.size == 1
            raise "You can't exchange gifts if you're all by yourself, you poor lonely fool!"
        end
        loop do
            begin
                return try_to_give
            rescue
            end
        end
    end
end

names = File.read("names").split("\n")

gifter = Gifter.new(names)
gifts = gifter.give

gifts.keys.each do |giver|
    puts "#{giver}: #{gifts[giver]}"
end

It reads the names out of a file, expecting that each name is on its own line. Then it attempts to assign each name to one other name, and if it gets to the end and finds that its only option is to assign a name to itself, it throws away all the assignments and tries again. That can happen a few times, but the likelihood of it happening repeatedly, to the point where you’d notice the program running slowly, is pretty astronomical. So I’m not worried about it.

We’ll see if we end up doing it this way. But if you want to try it with your family (or group of friends), I guarantee this program is easier than trying to come up with a fair and random assignment by hand.


Killing Tomcat, the fun and easy way!

For the longest time, I’ve gone through an annoying manual step of killing Tomcat when it needs to die.

ps aux | grep tomcat

Search for the right one (ie, not the grep), and manually enter the process id into:

kill -9 <process id>

Normally, Tedium is a good enough motivator for me to script something like this. But this time, I waited until Ridicule threw its hat into the ring. After a coworker asked why I didn’t script it, it was really only a matter of time.

#!/usr/bin/env ruby

ps = `ps aux | grep catalina.startup.Bootstrap | grep -v grep`
chunks = ps.split(" ")
if not chunks.empty?
    pid = chunks[1]
    puts "Killing pid: #{pid}"
    `kill -9 #{pid}`
end

And now all I have to do is:

~/code/killer/kill_tomcat.rb

There you go. Tomcat is dead.


Increasing screen brightness with the /proc filesystem

I installed Fedora/LXDE on an old laptop this weekend, and it went well — but when I told it to hibernate and then booted it back up, the screen was painfully dim. I wonder why that happened … but since I’m not planning to go fixing any bugs in the hibernate code of either Fedora or LXDE, the why it happened wasn’t nearly as pressing a question as what do you do about it?

So I started digging around in the /proc filesystem, after not finding anything obviously related to screen brightness in 5 seconds of looking through the GUI tools. The /proc/acpi/video/VGA/LCDD/brightness file looked promising.

[root@flower sirsean]# cat /proc/acpi/video/VGA/LCDD/brightness 
levels:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
current: 0

Ah ha, no wonder the screen was so dim! I just had to tell it to increase the brightness.

[root@flower sirsean]# echo 5 > /proc/acpi/video/VGA/LCDD/brightness

The screen immediately got much brighter, more usable. I was kind of surprised by that, to be honest, but I liked it.

[root@flower sirsean]# cat /proc/acpi/video/VGA/LCDD/brightness 
levels:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
current: 5

Yup. I have a feeling I’ll be needing to do this again at some point.


3D Ultrasound of Rusty

So we went to have some 3D ultrasound images taken this weekend, which I’d never heard of before. The idea of it, though, is pretty cool. I don’t know if you’ve ever seen an ultrasound happen, but the basic concept is that they take a slice image that you can see; sure, it lets you see more than you would without the ultrasound at all, but it also leaves quite a bit to the imagination. Some people can’t tell what’s going on at all.

But if you take those slices and let a computer reconstruct them into a 3D image, it looks much better. You’ll probably be able to tell what you’re looking at. Watch this:

(This is an HTML video in H.264 format. Use Safari or Chrome.)


Chrome OS: Remapping the Caps Lock key, plus some initial thoughts

This morning I installed Chromium OS on my old Acer Aspire One, which happens to be on its last legs and has been collecting dust in the bottom of a box in the back of my closet for the last several months. (The biggest two problems are 1: the AC adapter doesn’t work consistently and sometimes won’t charge the device, and 2: the OS options are slim, and slow, and Jolicloud was a huge disappointment.)

I used the Chromium Flow build by Hexxeh, which is just a 300MB or so download and gives you a bootable USB drive you can use to check out Chromium OS — or install to the computer’s hard drive so you can use it without having a USB drive sticking out the side of your computer.

So far the main problem I’ve seen is that this thing supports Flash; that makes web pages load painfully slow on a device with merely a 1.6 GHz Atom and 512 MB RAM. If Google wants Chrome OS to be a success, they’re going to have to really increase the minimum hardware requirements, or implement a very high quality version of “click to Flash” or something which blocks Flash from loading until the user explicitly asks for it. But this isn’t about Flash, so I’ll just leave it at that. Other than Flash, the Chromium OS experience is quite good.

With the tiny keyboard on the netbook, I was having quite a bit of trouble hitting the control keys; they’re really small and tucked away down in the corner of the keyboard where my oversized, gnarled up fingers can’t reach. So I hit Ctrl-Alt-T to open up a terminal window, which includes a cool window-sliding animation, and entered the following commands:

xmodmap -e "remove lock = Caps_Lock"
xmodmap -e "add control = Caps_Lock"

Then I switched back to the main browser window by hitting Alt-Tab, though hitting F12 would give me an Expose-like panel view of all my open windows.

Note: The only way I’ve figured out to close terminal windows once they’re open is to go back into them and issue the “exit” command. Chromium OS doesn’t seem to have very robust window-management functionality, which isn’t surprising given the way they’d expect you to use it.

So now the Caps Lock key is a Control button, and using the keyboard just got a whole lot more pleasant.

With some sexier hardware, a more comfortable keyboard, and a 3G connection, I can totally see myself using a Chrome OS device; that said, I can’t see how they can ever make it as nice to use as an iPad.


Simple Javascript event/model framework

Last weekend I wrote my first iPhone app, Tabata Sprinter, and Apple let it into their App Store late in the week. I took that as validation that using Appcelerator Titanium to write iPhone apps is still acceptable, because that’s what I’d used. So this weekend, I wrote a second app, Choose4me, which is currently awaiting review.

While making the first app I started a model/event binding library, and I have improved upon it for the second app.

The concept is that you want to store your values in a central location, and listen for any changes in their values so you can update the UI or fire any other events that you want. Without further ado, here’s the code:

var VH = {
    Model: function () {
        this._listeners = {};
        this._fields = {};
        this._boundListeners = {};

        this.listen = function(key, listener) {
            if (this._listeners[key] == null) {
                this._listeners[key] = [];
            }
            this._listeners[key].push(listener);
        };

        this.set = function(key, value) {
            var oldValue = this._fields[key];
            this._fields[key] = value;
            if (oldValue !== value) {
                this.poke(key);
            }
        };

        this.poke = function(key) {
            if (this._listeners[key] != null) {
                for (var i=0; i < this._listeners[key].length; i++) {
                    var listener = this._listeners[key][i];
                    listener(this._fields[key]);
                }
            }
        };

        this.get = function(key) {
            return this._fields[key];
        };
    }
};

To listen for a changing variable, you call listen() and pass it a callback that takes a single argument — the newly changed value.

When you set() a variable, it checks to see if the new value is different from the old value, and if so, notifies all listeners using poke(). Note that you can call poke() yourself, if you want to notify listeners without setting a value (for events, perhaps).

Example

You instantiate your model at the beginning; it should be among the first things you do.

var model = new VH.Model();
var delegate = new VH.Model();

I’m using two of them; the “model” is for storing values, and the “delegate” is just for firing events (ie, you use the key/value pairs but you don’t care about the values). This is just a convention I came up with, you may not find it useful.

Then you set default values, which your components may need during their setup.

model.set(C4.fields.numOptions, 2);

(Note that C4.fields.numOptions is just a string constant. You’ll want each key to be a unique value, and using constants helps keep track.)

While you’re setting up your components, you’ll want to listen for changing values.

delegate.listen(C4.events.choose, function(v) {
    model.set(C4.fields.currentChoice, VH.random(1, model.get(C4.fields.numOptions)));
});

Here, we’re listening for any time someone calls delegate.poke(C4.events.choose), which indicates that the “choose” event has been fired. So when does that happen?

chooseButton.addEventListener("click", function(e) {
    delegate.poke(C4.events.choose);
});

I have a button, and I attached an event listener to it, so that any time they click the button we’ll poke the delegate to fire the choose event. I could have done this differently — either by doing the random calculation right in the click event handler and setting the model field directly, or by using a function rather than listening for the choose event. But this works better because we get the benefit of writing our logic only once just like a function, while avoiding any “function is called before it’s defined” warnings that crop up during cross-compilation.

Using this model has worked out great for me in my first two apps, and what’s nice is that I expect it’ll also work nicely in a regular webapp the next time I write one.

So hopefully Appcelerator Titanium remains kosher on the App Store, because this is a pretty fun way to program.