Enterprise Objects in WebObjects

This appendix discusses how to access WebObjects in enterprise object classes and how to access enterprise objects in WebObjects Builder.

Accessing WebObjects in Enterprise Objects

In a well-designed WebObjects application, Enterprise Object classes don’t have direct knowledge of WebObjects classes. In practical terms, this means that Enterprise Objects classes don’t reference any classes in the WebObjects framework (com.webobjects.appserver). Enterprise Object classes designed this way are more portable and help you achieve the promise of reusable, highly maintainable business objects.

However, there are occasions in which you need to reference a WebObjects object such as WOSession or WOApplication. There is no direct API to do this. However, there are a few tricks that are commonly used to accomplish this.

The easiest way to access a WOSession object in an Enterprise Object class is to set the delegate of an editing context to be the session object. When you invoke the method editingContext on an enterprise object instance, it returns the Session’s default editing context (this is the default behavior; your configuration may differ, depending on customizations you make).

Assuming your enterprise object classes use the default editing context configuration, to set the delegate for the editing context of any enterprise object class in your application, you invoke defaultEditingContext().setDelegate(this) in your Session class’s constructor. Then, to get a reference to the Session object in an enterprise object class, you invoke the method shown in Listing A-1 on an enterprise object instance.

Listing A-1  Accessing a Session object from an enterprise object

Session aSession = (Session)editingContext().delegate();

The code in Listing A-1 assumes that an enterprise object’s editing context is not null and that the enterprise object is in the editing context. In an enterprise object’s constructor, this is not necessarily the case: The enterprise object may not yet be inserted into the editing context. So, the safe place to invoke the code is in awakeFromInsertion or awakeFromFetch.

While this is the easiet way to obtain references to WebObjects objects from enterprise objects, it compromises the purity and portability of the enterprise objects. A better approach would be to use notifications to access WebObjects objects from within enterprise objects. This approach maintains the decoupling between the two frameworks.

Enterprise Objects in WebObjects Builder

One of the most useful features of WebObjects Builder is its ability to access an application’s EOModels and to extract from those models information about entities and an entity’s class properties. It displays the entities and class properties in the lower pane of the split view while in layout view. This allows you to quickly and easily bind dynamic element bindings to properties of an enterprise object. Figure A-1 shows the Listing entity and its class properties from the Real Estate model.

Figure A-1  Entity and attributes in WebObjects Builder
Entity and attributes in WebObjects BuilderEntity and attributes in WebObjects Builder

So how does WebObjects Builder know what entities to display? It does not display all of the entities in an application’s models. Rather, it displays an entity and its attributes only if aWOComponent includes a key (a field or accessor methods) of a type that corresponds to an entity in the application’s models.

For example, in Figure A-1, the listing key corresponds to the Listing entity in the Real Estate model. The HomePage.wo component (from the iShacks example in /Developer/Examples/JavaWebObjects/) includes a field and accessors for the listing key. WebObjects Builder knows that the listing field and its accessors correspond to an enterprise object of type Listing because the listing field is declared to be of type Listing, which is an Enterprise Object class declared in the Real Estate framework that the iShacks example includes. The declarations of listing in the HomePage.wo component are shown in Listing A-2.

Listing A-2  Declarations of the listing key

public Listing listing;
public Listing listing() {
    return listing;
}
public void setListing(Listing newListing) {
    listing = newListing;
}

But what if you add a key to a WOComponent that corresponds to an entity that doesn’t use a customer enterprise object class (that is, the entity maps directly to EOGenericRecord)? To add a key to a WOComponent, you usually do it within WebObjects Builder. A window appears when you add a key, as shown in Figure A-2.

Figure A-2  Add key window in WebObjects Builder
Add key window in WebObjects Builder

The combo box in the Type section lets you enter the name of an entity in the application’s models. It includes an auto-complete feature, so if you want a new key to correspond to the Listing entity, typing “Li” displays the whole word “Listing.” When you click Add, declarations for the new key are added to the current WOComponent. Each of the declarations includes a @TypeInfo comment above it, which WebObjects Builder uses to determine the entity of a key that is declared as an EOEnterpriseObject. Declarations for the listing key that maps to an EOGenericRecord rather than to an EOGenericRecord subclass called Listing are shown in Listing A-3.

Listing A-3  listing key declarations with @TypeInfo

/** @TypeInfo Listing */
protected EOEnterpriseObject listing;
 
/** @TypeInfo Listing */
public EOEnterpriseObject listing() {
    return listing;
}
 
public void setListing(EOEnterpriseObject newListing) {
    listing = newListing;
}