Extending EOGenerator templates

The default EOGenerator templates (JavaSourceEOF52.eotemplate and JavaSubclassSourceEOF5.eotemplate) only implement the basic logic in the generated _EO.java and EO.java classes.

I’m assuming you know what eogenerator does, and you understand how the _EO.java and EO.java classes relate to one another. If you don’t, ask, and I’ll try to explain.

For instance, for an entity named Person with the attributes firstName and lastName and a to many relationship to PhoneNumbers named phoneNumbers you’d end up with this:

  • Getter and setter accessor methods for firstName
  • Getter and setter accessor methods for lastName
  • Getter and setter methods for phoneNumbers
  • addTo and removeFrom methods for phoneNumbers

This is about the same amount of java that you’d get from EOModeler if it generated your java for you. Acceptable, but we can do much better.

My Template

My templates (which you can download here) are derived from the advanced sample template that ships with eogenerator (EOGJavaSource.eotemplate) and create the following additional methods in your _EO.java class:

For each to-many relationships

  • addToRelationshipNameRelationship(Object obj) – calls addObjectToBothSidesOfRelationshipWithKey on the relationship with obj
  • removeFromRelationshipNameRelationship(Object obj) – calls removeObjectFromBothSidesOfRelationshipWithKey on the relationship with obj
  • createRelationshipNameRelationship() – creates a new object matching the destination type of the relationship, inserts it into this EO’s EOEditingContexts and adds it to the relationship.
  • deleteRelationshipNameRelationship(Object obj) – removes obj from the relationship and then calls editingContext().deleteObject(obj)
  • deleteAllRelationshipNameRelationships – iterates through all of the objects in the relationship, calling deleteRelationshipNameRelationship.

For each model defined fetch specifications

  • objectsForFetchSpecificationName(EOEditingContext ec, AObject aObjectBinding, BObject bObjectBinding, …) – a static method that returns any objects matching the fetch spec FetchSpecificationName. It takes typed objects for any bindings defined in the fetchSpec.

Using the templates

Using my templates is straight forward, simply specify them when you call EOGenerator (see this post for more details). Before you use my templates however, you will need to specify the name of the class that your EO’s should inherit from (EOGenericRecord is the default). Replace the reference to CBEOBaseClass in the constructor section of CBJavaSourceEOF5.eotemplate (it should be around line 29).

Extending the templates

EOGenerator uses a tool called MiscMerge to create the java class from the EOModel. There is a MiscMerge.rtf included in the eogenerator distribution, but you can figure out what is going on pretty easily just by looking at the templates (the template that does most of the work is CBJavaSourceEOF5.eotemplate).

One of the downsides to using Key Value Coding is that you lose compile time checking on valueForKey methods. For instance, calling:

valueForKey("anAtribute")

will compile fine, but fail at runtime if the attribute is actually called anAttribute.

So, one extension you may wish to make to my templates is to have static strings created to that map to each of your attributes. This means that you can call:

valueForKey(MyEO.AN_ATTRIBUTE)

and the compiler will catch your typos.

The EOGJavaSource.eotemplate included with eogenerator includes an example of how to do this. The template code between line 34 and 39 will create a static string variable for each of your attributes and relationships. Simply copy these lines of code (in between the <$comment … $> and <$comment) and paste them below the constructor in CBJavaSourceEOF5.eotemplate.

EOGenerator is a very powerful tool, it will get you a lot of machine generated (and more importantly machine maintained) code that will make your applications simpler and easier to build. I highly recommend exploring its capabilities a little.

Mac OS X 10.3.7 is now out

The Mac OS X 10.3.7 update is now available.

A few choice resolved issues:

  • Resolves an issue in which Safari, Mail, and other networking applications that use DNS lookups could experience intermittent connectivity issues with Security Update 2004-09-30 and Mac OS X 10.3.5 or later installed.
  • Filenames longer than 31 characters are no longer shortened when the file is saved on a server via Apple File Sharing.
  • Resolves an issue with Mac OS X 10.3.6 in which some FireWire hard drives would not appear (“mount”) on the desktop.

Using WebObjects DirectActions – pt. 5

Calling a DirectAction with values from a WORedirect

WORedirect is useful when you need a regular Component action (i.e. non DA) to lead somewhere other than another WOComponent (i.e. If you need to perform some cleanup and return a company homepage when a logout link is clicked).

Luckily for us, a WORedirect can also easily allows us to redirect to a DirectAction, as the following code demonstrates:

String searchString; 		//assume exists
String category;		//assume exists
String pageOfResults = "0"
 
public WORedirect performSearch() {
    NSMutableDictionary dict = new NSMutableDictionary();
    dict.takeValueForKey(searchString, "searchString");
    dict.takeValueForKey(category, "category");
    dict.takeValueForKey(pageOfResults, "page");
    String url = context().directActionURLForActionNamed(
                 "search", dict ); 
    WORedirect redirect = new WORedirect(context());
    redirect.setUrl(url);
    return redirect;
}

This hypothetical action is bound to a WOSubmitButton in a WOForm on a WOComponant. It is important to note that its return type is WORedirect instead of the usual WOComponent.

It function is pretty clear, it creates a new NSMutableDictionary and populates it with the values and keys that we need to append to our DirectAction URL. The single line of code does most of the heavy lifting:

String url = context().directActionURLForActionNamed( 
                  "search", dict );

It creates the DirectAction url (in this case for the searchAction) for us and append the values from our NSMutableDictionary. Finally we set the url for the WORedirect and return it.

The directActionURLForActionNamed comes from WOContext and it’s API can be found here.

Well, I think this will be the last DirecAction specific post. I’ve covered pretty much everything I set out to, so I think I’ll take a break an look for a different topic to examine. If anyone has any suggestions, let me know.

First post with MarsEdit

This is my first blog entry composed in MarsEdit.

Up to now I’ve been using HyperEdit to compose the entries and the WordPress web interface to post.

I miss the html Code Snippet pallet in HyperEdit but I don’t miss the WordPress web interface at all. 🙂

I did have a problem getting MarsEdit to access my blog archives. I discovered (thanks to Brent Simmons) that there is a problem with OS X Server that truncates the XML-RPC methodResponse to 32k if the web Performance Cache is enabled for any site on the box. This particular server is running Jaguar, I don’t know if this problem afflicts Panther as well. When I have a chance I’ll investigate that.