I am slowly creeping towards the completion of the third WebObjects screencast. In preparation, I’ve created a tweaked version of the Apple Movies database tuned for MySQL and Wonder. You can grab the db dump and EO Model here. The model uses the MySQL protopypes from Project Wonder and the db dump matches it.
Tag: samplecode
Just a few of my favorite things…
Project Wonder is chocked so full of WebObjects goodness that it is hard to envision developing a project without it. Here are three bits that I use all the time.
Autolocking EditingContexts
Step one: Learn WebObjects
Step two: Realize that using the session().defaultEditingContext() exclusively is bad.
Step three: Start using multiple EOEditingContexts.
Step four: Read, re-read, then read again the documentation on EC locking.
Step five: Encounter production deadlocks.
Step six: Cry.
Thankfully Project Wonder provides an amazing solution in the form of autolocking EditingContexts. Enabling them is simple. Set some properties for your project:
er.extensions.ERXApplication.useEditingContextUnlocker=true er.extensions.ERXEC.defaultAutomaticLockUnlock=true er.extensions.ERXEC.useSharedEditingContext=false er.extensions.ERXEC.defaultCoalesceAutoLocks=true
There is an email from Mike Schrag with some juicy details here.
Change your code so that you never call new EOEditingContext();
instead use the ERXEC.newEditingContext()
factory method.
ERXThreadStorage
Problem: You need access to an object in your session from an EO. Maybe you want to set a “createdBy” value to the current user in awakeFromInsertion
Adding a reference to the Session in your EOs would be bad so what are you going to do?
Solution: Use ERXThreadStorage to store a reference to the current user and access that from your EO.
In your Session.java:
public User currentUser; // assume exists public void awake() { super.awake(); ERXThreadStorage.takeValueForKey(currentUser, "currentUser"); }
In your EO.java:
public void awakeFromInsertion(EOEditingContext ec) { super.awakeFromInsertion(ec); User user = ERXThreadStorage.valueForKey("currentUser")); if (user != null) { setCreatedBy(user.userName); } }
ERXGenericRecord
ERXGenericRecord is another Project Wonder class that is full of yumminess. Please read the API docs for the full details, but here are a few of my favorites:
willUpdate(); // called after saveChanges() but before validation // so it is safe to make changes. See the rest of // will* and did* methods for more primaryKey(); // returns the primary key (null if the EO hasn't // been saved yet) primaryKeyInTransaction(); // returns the primary key as above, // but if the EO hasn't beens saved yet, it'll // figure out what the pk should be, return it, // cache it, and use it later when the EO does get // saved. Very cool.
There is much, much more: ERXLocalizer, ERJavaMail, ERExcelLook… Dive into the docs and I’m sure you’ll find something usefull.
Suppressing the wosid in a DirectAction
Two common means of generating DirectAction URLs in WebObjects are by using the directActionName
bindings available in WOHyperLink (and it’s brethren) and by using the WOContext method: directActionURLForActionNamed(String name, NSDictionary)
.
Kol. Panic offered a tip on suppressing the Session ID (wosid) in DirectAction urls generated from a WOHyperLink in the comments of this post.
It turns out that there is a similar method if you are generating the URL in your code from a WOContext:
public String loginUrl() {
NSDictionary dict = new NSDictionary(
new Object[] {Boolean.FALSE},
new String[] {"wosid"});
return context().directActionURLForActionNamed("login", dict);
}