Last modified by Pascal Robert on 2012/03/09 16:04

Hide last authors
Pascal Robert 13.1 1 {{toc/}}
Pascal Robert 12.1 2
3 = Thinking About Design with WebObjects =
4
5 == How a WebObjects Developer Thinks ==
6
7 == Relationships not Queries ==
8
9 == Qualifiers ==
10
11 == Fetch Specifications ==
12
13 == Business Logic for Business Objects ==
14
15 == Components are for View Not Process ==
16
17 == Object Design ==
18
19 == The Request - Response Loop ==
20
Pascal Robert 13.1 21 Each action taken by a user is communicated to your application via the web server and the WebObjects adaptor. All the pertinent details of the user’s action~-~-(% style="text-decoration: line-through;" %)the contents of text fields, the state of radio buttons and checkboxes, and the selections in pop-up menus(%%)~-~-as well as information about the session and the button or link activated is encoded in the HTTP request.
22 The request is decoded by the action of the WebObjects adaptor and default application behavior. This decoding process, which culminates in the generation of a response page to be returned to the web browser, constitutes the request-response loop. Figure 2 shows the sequence of messages invoked when processing a request.
Pascal Robert 12.1 23
24 WebObjects has two request-processing models: component actions and direct actions.
Pascal Robert 13.1 25 ■ The component actions model allows you to maintain state in applications; therefore, it requires and uses session objects. By default, web applications use this model.
26 ■ The direct actions model is used by applications that don’t require state management~-~--for example, search engines, product catalogs, document libraries, and dynamic publishing. Applications that use this model don’t have session objects by default.
Pascal Robert 12.1 27
28 When developing an application, you are not restricted to one request-processing model. Applications can use the model most appropriate to implement specific features. Component actions are generally useful in web applications with interconnected components; however, they do not give the user a great deal of control over an application’s flow. For example, a user cannot directly execute a method defined in the Java source file of a web component. Direct actions, on the other hand, are better suited at providing users such access. For example, using the appropriate URL, users can execute specific methods of an application.
29
30 The application object is an instance of Application where Application is a subclass of WOApplication. A session object is an instance of Session where Session is a subclass of WOSession. An instance of Application is created when your application launches, and an instance of Session is created for each initial user. Note that sessions may time out. You can configure the time out duration when deploying an application.
31
32 Awake
Pascal Robert 13.1 33 public void awake()
34 The application, session, and component objects are awakened. Custom initialization logic can be added in this phase.
Pascal Robert 12.1 35
36 Sync
Pascal Robert 13.1 37 public void
38 takeValuesFromRequest
39 (WORequest, WOContext)
40 Form data is read into the instance variables the WebObjects elements are bound to. Key-value coding set methods are invoked.
Pascal Robert 12.1 41
42 Action
Pascal Robert 13.1 43 public WOActionResults
44 invokeAction (WORequest,
45 WOContext)
46 The action the user triggered~-~-(% style="text-decoration: line-through;" %)with a link or a submit button(%%)~-~-is performed. The action could create a new page.
Pascal Robert 12.1 47
48 Response
Pascal Robert 13.1 49 public void
50 appendToResponse
51 (WOResponse, WOContext)
52 The response page is generated. The form elements’ contents are set to the values stored in the instance variables the WebObjects elements are bound to. Key-value coding accessor methods are invoked.
Pascal Robert 12.1 53
54 Sleep
Pascal Robert 13.1 55 public void sleep()
56 The application, session, and component objects are put to sleep. Custom deactivation logic can be added in this phase.
Pascal Robert 12.1 57
Pascal Robert 13.1 58 |=(((
59 Application
60 )))|=(((
61 Session
62 )))|=(((
63 Component
64 )))
65 |(((
66 awake
67 )))|(((
68
69 )))|(((
70
71 )))
72 |(((
73
74 )))|(((
75 awake
76 )))|(((
77
78 )))
79 |(((
80
81 )))|(((
82
83 )))|(((
84 awake
85 )))
86 |(((
87 takeValuesFromRequest
88 )))|(((
89
90 )))|(((
91
92 )))
93 |(((
94
95 )))|(((
96 takeValuesFromRequest
97 )))|(((
98
99 )))
100 |(((
101
102 )))|(((
103
104 )))|(((
105 takeValuesFromRequest
106 )))
107 |(((
108
109 )))|(((
110
111 )))|(((
112 Set methods invoked.
113 )))
114 |(((
115 invokeAction
116 )))|(((
117
118 )))|(((
119
120 )))
121 |(((
122
123 )))|(((
124 invokeAction
125 )))|(((
126
127 )))
128 |(((
129
130 )))|(((
131
132 )))|(((
133 invokeAction
134 )))
135 |(((
136 appendToResponse
137 )))|(((
138
139 )))|(((
140
141 )))
142 |(((
143
144 )))|(((
145 appendToResponse
146 )))|(((
147
148 )))
149 |(((
150
151 )))|(((
152
153 )))|(((
154 appendToResponse
155 )))
156 |(((
157
158 )))|(((
159
160 )))|(((
161 Accessor methods invoked. Response page generated.
162 )))
163 |(((
164
165 )))|(((
166
167 )))|(((
168 sleep
169 )))
170 |(((
171
172 )))|(((
173 sleep
174 )))|(((
175
176 )))
177 |(((
178 sleep
179 )))|(((
180
181 )))|(((
182
183 )))
Pascal Robert 12.1 184
185 === Processing the Request ===
186
187 Request processing takes place in three stages: awake, sync, and action.
188
189 ■ Awake. This stage is carried out when WebObjects sends awake messages to several objects.
190
191 In a multi-user system, limited resources need to be used as efficiently as possible. To this end, applications are active only while they perform a task. A single server can be running several applications or many instances of the same application. Application instances are active only while processing requests. See “Generating the Response” (page 16) for more information.
Pascal Robert 13.1 192 The application object’s awake method is invoked first, then the session object’s awake method, and, for component action~-~-based requests, the web component’s awake method. You can customize the method in each of the corresponding classes to add logic that needs to be performed before processing the request. Even though the default implementations of these awake methods do nothing, you should invoke the superclass implementation before executing custom logic, as here:
Pascal Robert 12.1 193
194 {{code}}
195
196 public void awake() {
197 super.awake();
198 /* Custom logic goes here. */
199 }
200
201 {{/code}}
202
203 Sync. During this stage, the takeValuesFromRequest method is invoked, which causes the values entered in form elements by the user to be copied into the corresponding instance variables. This stage is skipped if the component contains no form elements or if the values of the form elements are not changed.
Pascal Robert 13.1 204 WebObjects invokes the application object’s takeValuesFromRequest method. The application then invokes the session object’s corresponding method, which in turn invokes the web component’s method (for component action-(% style="text-decoration: line-through;" %)based requests). The component invokes each dynamic element’s takeValuesFromRequest method, which causes form elements to copy the values from the request into the appropriate component bindings. WebObjects uses key-value coding(%%)-(% style="text-decoration: line-through;" %)implemented by the NSKeyValueCoding interface in (com.webobjects.foundation(%%)~-~-to determine how to set the value of the binding.
Pascal Robert 12.1 205
206 To set the value of a key named key, key-value coding looks for an available set method or an instance variable in the following order:
Pascal Robert 13.1 207 ~1. public void setKey()
208 2. private_setKey()
209 3. _key
210 4. key
Pascal Robert 12.1 211
212 Action. During this stage, the action the user chose is executed by invoking the invokeAction method.
Pascal Robert 13.1 213 Like the takeValuesFromRequest method, WebObjects invokes the application’s invokeAction method. The application then invokes the session’s method, which in turn invokes the web component’s method (for component action~-~-based requests). The component then sends invokeAction to each of its dynamic elements.
214 When the invokeAction method of the dynamic element that triggered the request is invoked~-~-(% style="text-decoration: line-through;" %)for example, a submit button(%%)~-~-the dynamic element sends the message bound to its action attribute.
Pascal Robert 12.1 215
216 === Generating the response ===
217
218 After the form values are gathered and the action method is invoked, the application creates a response page. This is the web component returned by the action method. The response-generation process has two phases: response and sleep.
219
220 ■ Response. The response page is generated during this phase. Each dynamic element’s appendToResponse method is invoked, so that it can add its content to the rendered webpage.
221
222 WebObjects invokes the application’s appendToResponse method. Then the application invokes the session’s method, which in turn invokes the web component’s method. The component goes through its HTML code creating the page’s content. When it finds a WEBOBJECT element, it invokes its appendToResponse method, so that it can get the values of its bindings and add the resulting content to the page. The process continues recursively until the entire response page is generated.
223
224 Again, WebObjects uses key-value coding when a variable needs to be accessed or set. When the value of a key named key is requested, key-value coding first looks for an accessor method. If one is not found, it accesses the instance variable itself. The order in which key-value coding tries to obtain the value for key is as follows:
Pascal Robert 13.1 225 ~1. public [] getKey()
226 2. public[]key()
227 3. private[]_getKey()
228 4. private[]key()
229 5. []_key
230 6. []key
Pascal Robert 12.1 231
232 ■ Sleep. When the response process is completed, the sleep methods of the web component, session, and application objects are invoked. (The order in which the objects’ sleep method is called is the opposite of the order in which the awake methods are invoked in the awake phase.) When overriding the sleep method, you should incorporate the superclass implementation at the end of the method as shown in Listing 2. After all the objects involved in the request-response process are put to sleep, the new page is sent to the WebObjects adaptor.
233
234 {{code}}
235
236 Listing 2 Overriding the sleep method public void sleep() {
237 /* Custom logic goes here. */
238 super.sleep();
239 }
240
241 {{/code}}
242
243 == Why Defer Optimization Concerns ==
244
245 == Key Value Coding and WOGNL Extensions ==
246
247 In order for models, views, and controllers to be independent of each other, you need to be able to access properties in a way that is independent of a model’s implementation. This is accomplished by using key-value coding.
248
249 === Keys ===
250
251 You specify properties of a model using a simple key, often a string. The corresponding view or controller uses the key to look up the corresponding attribute value. The “value for an attribute” construction enforces the notion that the attribute itself doesn’t necessarily contain the data—the value can be indirectly obtained or derived.
Pascal Robert 13.1 252 Key-value coding is used to perform this lookup—it is a mechanism for accessing an object’s properties indirectly and, in certain contexts, automatically. Key-value coding works by using the names of the object’s properties—typically its instance variables or accessor methods—as keys to access the values of those properties.
Pascal Robert 12.1 253
254 For example, you might obtain the name of a Department object using a name key. If the Department object either has an instance variable or method called name, then a value for the key can be returned. Similarly, you might obtain Employee attributes using the firstName, lastName, and salary keys.
255
256 === Values ===
257
258 All values for a particular attribute of a given entity are of the same data type. The data type of an attribute is specified in the declaration of its corresponding instance variable, the return value of its accessor method, or simply in the object model. For example, the data type of the Department object name attribute may be an String object in Java. Note that key-value coding returns only object values.
259
260 The value of a to-one relationship is simply the destination object of that relationship. For example, the value of the department property of an Employee object is a Department object.
261
262 The value of a to-many relationship is a collection object (an array) that contains the destination objects of that relationship. For example, the value of the employees property of Department object is a collection containing Employee objects.
263
264 === Key Paths ===
265
266 A key path is a string of dot-separated keys that specify a sequence of object properties to traverse. The property of the first key is determined by, and each subsequent key is evaluated relative to, the previous property. Key paths allow you to specify the properties of related objects in a way that is independent of the model implementation. Using key paths you can specify the path through an object graph, of arbitrary depth, to a specific attribute of a related object.
267
268 The key-value coding mechanism implements the lookup of a value given a key path similar to key-value pairs. For example, you might access the name of a department via an Employee object using the department.name key path where department is a relationship of Employee and name is an attribute of Department.
269
270 Not every relationship in a key path necessarily has a value. For example, the manager relationship can be null if the employee is the CEO. In this case, the key-value coding mechanism does not break—it simply stops traversing the path and returns an appropriate value, such as null.
271
272 == Description of the Application to be Built (blog) ==