WebObjects Info
2/04 - dBug Cafe
2/06 - FileMaker Pro
2/08 - Genealogy
2/18 - dBug Cafe
2/27 - Digital Video

SIG Page Selector

Subscribe to dBug's Event Calendar with iCal Subscribe to dBug Events with iCal
Join dBug Ladybug
Learn about the benefits and sign up as a dBug member here!
Search Search
Every page on the site can be accessed directly through our Site Map.
Support dBug
What computer products are recommended by dBug Members? Check them out right here. Products purchased from our recommended page help support dBug!
Member Music Picks iTMS
WebObjects Books Books
Building a Direct Actions WebObjects Application

By Mike Grueter
Posted February 9, 2005

This article is a step-by-step guide to building a very simple, sessionless, bookmarkable WebObjects application using Direct Actions. These steps were used during a demonstration given at a WebObjects SIG meeting by SIG Leader Mike Grueter, and based on chapter 4 of Ravi Mendis' book, "WebObjects Developer's Guide", but adds to it by showing one way to do error checking in a form.

1) Create a new project:

  1. Open Xcode, choose "New Project..." from the "File" menu.
  2. Choose "WebObjects Application" in the Assistant window list and click the "Next" button.
  3. Give the project a title like "HelloDA", choose a location if desired, and click the "Next" button five times.
  4. Click the "Finish" button.

2) Click once on "Web Components" in the "Groups & Files" list, choose "New File..." from the "File" menu, choose "Component" in the Assistant window list, click the "Next" button, name the component "Greeting", check only the "Application Server" target, and click the "Finish" button.

3) Edit DirectAction.java so that defaultAction looks like this:

public WOActionResults defaultAction() {
     String userName = request().stringFormValueForKey("userName");
     WOComponent nextPage = pageWithName("Main");
     nextPage.takeValueForKey(userName, "userName");
     return nextPage;
}

4) Add another direct-action method to DirectAction.java like this:

public WOActionResults greetingAction() {
     String userName = request().stringFormValueForKey("userName");
     WOComponent nextPage;

     if ((userName != null) && (userName.length() > 0))
          nextPage = pageWithName("Greeting");
     else {
          nextPage = pageWithName("Main");
          nextPage.takeValueForKey("true", "nameValidStr");
     }

     nextPage.takeValueForKey(userName, "userName");
     return nextPage;
}

5) Open Main.wo in WebObjects Builder and add two keys of type String. Name them "userName" and "nameValidStr".

6) Add a key of type boolean. Name the key "nameValid", and make sure only the "A method returning the value" checkbox is checked.

7) Add a WOForm to the Main component, type "Name:", add a WOTextField, type a return, add a WOSubmitButton, type a return, add a WOConditional, and type "Please enter something in the Name field and click the Submit button.".

8) Bind userName to the value attribute of the WOTextField and nameValid to the WOConditional.

9) Select the WOForm, show the Inspector window, and choose "greeting" from the directActionName attribute pop-up menu.

10) Double-click the WOSubmitButton to view the Inspector window and click the "Make Static" button.

11) Double-click the WOTextField to view the Inspector window and set the name attribute to "userName" (including the quotes). Save and close Main.wo.

12) Edit Main.java so that the nameValid method looks like this:

public boolean nameValid() {
     if ((nameValidStr != null) && (nameValidStr.equalsIgnoreCase("true")))
          return true;
     else
          return false;
}

13) Open Greeting.wo in WebObjects Builder and add one key of type String named "userName".

14) Add a WOHyperLink to the Greeting component, type "Back", click to the right of the WOHyperLink, type a return, type "Hello ", add a WOString, and type "!".

15) Bind userName to the value attribute of the WOString.

16) Double-click the WOHyperLink to view the Inspector window and set the directActionName attribute to "default" (including the quotes). Add a binding attribute named "?userName" and bind it to "userName" (both without the quotes). Save and close Greeting.wo.

17) Edit Application.java to include the following two lines of code to the Application method:

WORequestHandler directActionRequestHandler = requestHandlerForKey("wa");
setDefaultRequestHandler(directActionRequestHandler);

18) Edit Session.java to include the following line of code to the Session method:

System.out.println("Warning: A session was created!");

19) Build and run HelloDA.

Notes:

1) A session should not be created while HelloDA is running. You can verify this by looking at the log in Xcode's Run Log window. Because we added the println code to Session, "Warning: A session was created!" would show up in the log if the Session constructor was called.

2) Since a session is not created, the URL of each component should have no session info.

3) You could create a new browser window and type:

"http://www.yourdomain.com/cgi-bin/WebObjects/HelloDA.woa/wa/greeting?userName=Mike"

and the URL would take you right to the Greeting component without first having to view the Main component.

4) You can keep a web page open in a browser for any length of time and then continue without getting an expired session error.

5) Try leaving the Name field empty when running HelloDA, and see how the error checking works.

6) Note that the browser back button works and that entering a new name still accepts the correct userName data. Safari does not seem to have a back button problem with session-based applications in this regard, but other browsers may.

Advantages:

1) Pages are bookmarkable
2) Sessionless applications do not cache pages at the WebObjects level, so they use less memory
3) Avoid the backtracking problem seen in some web browsers

Disadvantages:

1) More work for the developer synchronizing variables from component to component manually
2) Very little documentation on Direct Actions, and no sample code that I could find
3) Less code encapsulation

It is possible to use both Direct Actions and normal actions (Session-based variable synchronization, etc.) in a single WebObjects application, and thus have the best of both worlds, but that is a discussion for another time.