Using WebObjects: More Practical Tips and Tricks
Pages: 1, 2
Put It to Use
Login
You should now be able to build and run your application. When you receive the Login form, try:
- Leaving the
UsernameorPasswordfields empty. - Logging in using incorrect credentials.
When you decide to log in correctly, make sure you select the Assistant checkbox. Once you have received the Home Page, click on the Customize button. The D2WAssistant should launch in a new window. You then want to customize a List page for a User; a simple way to do so is to simply query for Users.

Display the Full Name
The D2WAssistant will then update to allow you to edit the current Rule(s). You should be able to select nameFull from the list of Properties. If you decide to Show nameFull, either click the Update or Save buttons to see your change reflected on the current page.
You'll notice D2W is displaying the property nameFull without prettifying it. You can change the display by simply selecting nameFull under the Show list and entering Full Name in the Display field:

But there's a more "global" way to accomplish it. For now, enter Full Name and save the changes.
A Helpful Rule
Although you can run the D2WAssistant while editing your .d2wmodel file, I choose not to in order to avoid overwriting or corrupting the file. So, to be safe, log out of your application. Locate and open the user.d2wmodel file in your project. You should now be editing your file using the Rule Editor application.
Since you'll probably want to display something other than a label like nameFull throughout your application, you can create a more generic Rule. To do so, simply select your new Rule, which has the Left-Hand Side argument of:
((task = 'list') and (entity.name = 'User') and (propertyKey = 'nameFull'))
Remove the first argument: (task = 'list').
By simply removing the task argument, you've just enabled D2W to always display the Full Name label any time it needs to display a User's nameFull. In other words, any time a web page is created and that web page is going to display information obtained using a User's nameFull method, it will be labeled as Full Name. That's it ... I tried ... I don't know how else to explain it ... because I feel like I'm going in circles ... (Paragraph courtesy of Red Bull.)
Your Rule should now look something like this:

If you wanted to have a really generic Rule, you could even remove the entity.name = 'User' argument. You would then enable D2W to always display the label Full Name for every nameFull property. So, in the future, if you had a City class that had a nameFull property, D2W would implement this Rule just as it does for a User.
Run Through the Gap
Obviously, your User is pretty light on details. What if you wanted to contact a User? How would you do so? I'm partial to email.
Return to EOModeler and select your User Entity. You're not going to do anything too fancy here, just add another attribute and name it email. I took the lazy person's route and did a copy/paste using the username attribute, and simply renamed both the name and column.
Since you've now changed the schema of your User, you'll need to synchronize your EOModel and your database. As I discussed in the last article, how you synchronize your EOModel and your database is up to you. Please be aware you've now implemented a Login panel, so if you drop your table, you'll need to add a User to your database somehow.
Once you've made the change, go ahead and generate the Java file for your User again.
- Select the
User Entity. - Click the Java button
. - Click the Save As button (Do Not Overwrite or Merge).
- Rename the User.java file to _User.java.
- Replace the previous file.
- "Remove the wrench."
I realize these steps are fairly tedious for an application of this size, but you shouldn't have to change the schema of you model(s) too often.
Your nameFull method should have survived this minor onslaught. As your application grows, and the logic for each of your EOEnterpriseObjects becomes more complex, the Generation Gap pattern should prove quite beneficial. At the very least, you'll have a clean separation between code "owned" by EOModeler and code "owned" by you (or your employer).
Show
Build and Run your application again. When logging in, select the Assistant checkbox. Choose to Customize, wait for the D2WAssistant to launch and then query for a User. You should ultimately receive a List page for a User.
In the D2WAssistant window, notice the email property is now available. Go ahead and select it and add it to the Show list. Directly to the right of the Show list is a popup button. This popup button will allow you to create a Rule to assign a reusable component, given these criteria (i.e., a List page, a User, and the email property). When you click on the popup button, you should be able to select a component named D2WDisplayMailTo.

By selecting this component, whenever a List page for a User needs to display the email property, it will be presented as a mailto: link. Therefore, clients will be able to simply click on a User's email address in order to compose and send email.
Edit
While still viewing the List page, you will be able to edit a User by clicking the Edit button
. The D2WAssistant should update to reflect the fact you are now viewing an Edit page. Again, select the email property and add it to the Show list.

When you click on the Save button, in the D2WAssistant, you should notice your web page update. You can now edit a User's email address. Enter an appropriate address and click the Save button on the web page. You should then receive a List page.
Use
Now, when viewing a List of Users you'll be able to send them an email with a simple mouse click.

When the address is clicked, your Mail application should launch and create an email addressed to the selected User.
For Fun
If you'd like, you can refactor your Login code (using Move Method) from Main.java to User.java. When doing so, you might wind up with a static method in your User class. In fact, your User class might look something like:
public static EOEnterpriseObject userForCredentials
(EOEditingContext ec, String uid, String pwd)
throws EOObjectNotAvailableException {
EOEnterpriseObject aUser;
// use with EOUtilities to query the database
NSDictionary bindings;
// used to determine which columns to query
Object[] keys = {"username", "password"};
// used to query the database rows
Object[] values = {uid, pwd};
if ((uid == null) || (uid.length() == 0) ||
(pwd == null) || (pwd.length() == 0)) {
throw new EOObjectNotAvailableException
("Username and Password required.");
}
aUser = null;
bindings = new NSDictionary(values, keys);
try {
aUser = EOUtilities.objectMatchingValues(ec, "User", bindings);
}
catch (EOUtilities.MoreThanOneException e1) {
System.err.println("ERROR: More than one User with username '" + uid +
"' and password '" + pwd + "'.");
throw new EOObjectNotAvailableException
("Please contact a System Administrator.");
}
catch (EOObjectNotAvailableException e2) {
throw new EOObjectNotAvailableException
("Your Login information was incorrect.");
}
return aUser;
}
}
I will leave the Login implementation in Main.java to you.
Josh Paul is the founder and CEO of Aweli, a startup focused on digital video solutions, and the author of Digital Video Hacks. He has provided software and service solutions to entertainment production companies throughout Los Angeles and New York.
Return to Mac DevCenter
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 6 of 6.
-
Full Name didn't work
2004-03-13 17:24:23 stevechen [Reply | View]
-
Full Name didn't work
2004-03-13 23:11:47 Josh Paul |
[Reply | View]
From the information you've provided, I think the error is coming from your EOModel. You should check your model and make sure there is an Attribute callednameFull. Make sure both theNameandColumnfields are filled in. Also check to see if the Attribute has the diamond-symbol next to it.
HTH. -
Full Name didn't work
2004-03-31 17:35:02 dgregory1 [Reply | View]
I also am having this problem with fullName(). As I understand it, the reason for subclassing _User was so that an attribute for fullname was not needed in the database. What else could we be doing wrong?.....Dale -
Full Name didn't work
2004-03-31 20:09:40 Josh Paul |
[Reply | View]
You are correct. I mistakenly gave bad advice. SORRY!
Hmm..the attribute offullNameshould not be needed in the database nor the EOModel. Since I can't see your code, or project, I can only guess at a solution:
<br/>
<br/>check your EOModel and make sure your Entity'sNameandClass Nameis namedUsernot_User
<br/>
<br/>
If that doesn't solve it, please let me know.
-
Use EOGenerator to generate EOs
2004-01-20 15:14:19 ghopson [Reply | View]
Check out EOGenerator at http://www.rubicode.com/Software/EOGenerator/ - this command line utility uses templates to generate both the _User and the User java files, and subsequently will only overwrite the _User.java file if the schema changes, thus leaving your custom code alone. And because it is a command line utility, it's scriptable, so you canmake it a part of your build scripts.
Unless you are diligent about source code repositories, using the method outlined in the article could result in you deleting some valuable business logic. Be careful!






I am half way through this article, but I'm stucked. When I add the Full Name in the Assitant and save, it would give error: com.webobjects.foundation.NSKeyValueCoding$UnknownKeyException: valueForKey(): lookup of unknown key: 'nameFull'. This class does not have an instance variable of the name nameFull or _nameFull, nor a method of the name nameFull, _nameFull, getNameFull, or _getNameFull
What did I do wrong? Any help would be much appreciated.