Programatically creating a WODisplayGroup

I like WODisplayGroups. OK, call me crazy – or lazy – but I like them alot. However, I do find that I often need more control over them than the drag and drop creation gives me. So here is how I like to set up WODisplayGroups programatcially:

Just to prevent any potential confusion: This example demonstrates creating a WODisplayGroup from scratch, and will not work if you’ve created one by dragging an Entity from EOModeler into WebObjects Builder. – Thanks Alex!

Using this pattern setup the _displayGroup object

protected WODisplayGroup _displayGroup;
 
public WODisplayGroup displayGroup() {
	if (_displayGroup == null) {
		prepDisplayGroup();
		find();
	}
	return _displayGroup;
}
public void setDisplayGroup(WODisplayGroup dg) {
	_displayGroup = dg;
}

Add the prepDisplayGroup() method:

public void prepDisplayGroup() {
	_displayGroup = new WODisplayGroup();
	_displayGroup.setNumberOfObjectsPerBatch(10); 
	EOSortOrdering asc = EOSortOrdering.sortOrderingWithKey(
			"keyToSortOn", 
			EOSortOrdering.CompareAscending);
	NSArray ordering = new NSArray(new Object[] {asc});
	_displayGroup.setSortOrderings(ordering);
}

The WODisplayGroup API is here

Finally add the find() method:

public void find() {
	NSArray foundObjects = //fetch your objects here
	displayGroup().setObjectArray(foundObjects);
}

In my find() method I usually take advantage of the objectsFor... methods that can be generated by EOGenerator. These wrap your EOModel’s fetchSpecs in static methods in your EO’s, very cool. Take a look at the EOGenerator EOGJavaSource.eotemplate for more details. Update: I’ve blogged more details about my EOGenerator templates here

I often base my search pages on a common super class that includes a displayGroup along with variables for setting objects per batch and a search string amongst other things.

Lazy WOComponent ivar initialization

How do you setup instance variables if they need to be initialized after their WOComponent is fully formed?

Overiding the awake() method happens too early, so you’re usually left overriding later in the request-response loop *. Here is a nice simple alternative pattern that I use all the time.

  1. Create your instance variables (I like to make them protected at least)
    protected NSArray _myThings;
  2. Give your ivars public accessor methods
    public NSArray myThings() {
    	return _myThings;
    }
     
    public void setMyThings(NSArray array) {
    	_myThings = array;
    }
  3. Modify the getter method so it follows this pattern:
    public NSArray myThings() {
    	if (_myThings == null) {
    		//initialize _myThings here
    	}
    	return _myThings;
    }

This pattern works really well for setting up things like display groups or arrays of fetched objects. If you bind to the accessor method in your WOComponent, the first time the method is hit, the values will be initialized. Very clean and easily understood. I like it a lot 🙂

* You do know the stages of the request-response loop don’t you? If you don’t buy Chuck’s book. Do it now. I’ll wait…

Broken comments

If you’ve attempted to leave comments recently, you probably ended up here – I apologize for that. It wasn’t an editorial comment, honest.

I’m using two anti-comment-spam plugins – Kitten’s Spam Words and Three Strikes SPAM. I marked the first piece of spam I received with Kitten’s Spam Words, and it incorrectly identified the local gateway IP as the source of the post and added it to the list of common spam words… Oops!

The two filters are not at fault, it is not easy to identify the source IP of a post (especially when the request comes from the maze of routers that is my upstream provider). It’s my fault for not recognizing the IP for what it was.

Canadian iTunes Music Store

Coming in November!

SAN JOSE, California—October 26, 2004—Apple® today launched a European Union version of its revolutionary iTunes® Music Store, giving music fans in Austria, Belgium, Finland, Greece, Italy, Luxembourg, Netherlands, Portugal and Spain the same innovative features and breakthrough price of €0.99 per song that have made iTunes the number one online music service in the world. With Apple’s legendary ease of use, pioneering features such as iMix playlist sharing, seamless integration with iPod® and groundbreaking personal use rights, the iTunes Music Store is the best way for PC and Mac® users to legally discover, purchase and download music online. Apple today also announced it will launch the iTunes Music Store in Canada in November.

Time to pay down the credit cards…