Changes for page Your First Stateful Project
Last modified by Bastian Triller on 2021/08/07 03:59
From version 13.1
edited by Pascal Robert
on 2012/08/09 05:11
on 2012/08/09 05:11
Change comment:
There is no comment for this version
To version 8.1
edited by Pascal Robert
on 2012/08/09 03:52
on 2012/08/09 03:52
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -1,3 +1,7 @@ 1 +{{info}} 2 +Work in progress 3 +{{/info}} 4 + 1 1 So far, we have seen two of the technologies, D2W and ERRest, that Project Wonder offers for viewing and managing the data. In this tutorial, we will show how to do it with the "stateful" way of doing things. Stateful have been around since the beginning of WebObjects in 1996, so it's the oldest way of presenting data and constructing pages. 2 2 3 3 Stateful means that you don't have to worry about creating sessions and keeping track of data coming from HTML input fields and controls. In fact, D2W is also stateful. ... ... @@ -87,11 +87,11 @@ 87 87 <wo:if condition="$displayGroup.hasMultipleBatches"> 88 88 <div> 89 89 <wo:link action="$displayGroup.displayPreviousBatch">Previous</wo:link> 90 - | Batch 94 + | Batch 91 91 <wo:str value="$displayGroup.currentBatchIndex" /> 92 - of 96 + of 93 93 <wo:str value="$displayGroup.batchCount" /> 94 - | 98 + | 95 95 <wo:link action="$displayGroup.displayNextBatch">Next</wo:link> 96 96 </div> 97 97 </wo:if> ... ... @@ -98,9 +98,9 @@ 98 98 <wo:loop list="$displayGroup.displayedObjects" item="$blogEntryItem"> 99 99 <p><wo:str value="$blogEntryItem.title" /></p> 100 100 <p><wo:str value="$blogEntryItem.content" escapeHTML="false" /></p> 101 - <p>Created by 105 + <p>Created by 102 102 <wo:str value="$blogEntryItem.author.fullName" /> 103 - on 107 + on 104 104 <wo:str value="$blogEntryItem.creationDate" /> 105 105 </p> 106 106 <hr /> ... ... @@ -118,83 +118,44 @@ 118 118 119 119 {{code}} 120 120 121 -private Author _loggedAuthor; 125 + private Author _loggedAuthor; 122 122 123 123 public Session() { 124 124 this._loggedAuthor = null; 125 125 } 126 - 130 + 127 127 public Author loggedAuthor() { 128 128 return this._loggedAuthor; 129 129 } 130 - 134 + 131 131 public void setAuthor(Author loggedAuthor) { 132 132 this._loggedAuthor = loggedAuthor; 133 133 } 134 134 139 + 135 135 {{/code}} 136 136 137 -Save the file. Next: we need to add a component to present the login form to the user. Right-click on the **Components** folder in the project, and select **New** > **WOComponent**. Change the name of the component to be **AdminMainPage** and change the superclass to **er.extensions.components.ERXComponent**. 142 +Save the file. Next: we need to add a component to present the login form to the user. Right-click on the **Components** folder in the project, and select **New** -> **WOComponent**. Change the name of the component to be **AdminMainPage** and change the superclass to **er.extensions.components.ERXComponent**. 138 138 139 -After the component have been created, open **AdminMainPage.java** and overridethecontent ofthe class with the following code:144 +After the component have been created, open **AdminMainPage.java** and add the following code: 140 140 141 141 {{code}} 142 142 143 -package your.app.components; 144 - 145 145 import your.app.Session; 146 -import your.app.model.Author; 147 -import your.app.model.BlogEntry; 148 148 149 -import com.webobjects.appserver.WOActionResults; 150 -import com.webobjects.appserver.WOContext; 151 -import com.webobjects.eoaccess.EODatabaseDataSource; 152 -import com.webobjects.eocontrol.EOEditingContext; 153 - 154 -import er.extensions.batching.ERXBatchingDisplayGroup; 155 -import er.extensions.components.ERXComponent; 156 -import er.extensions.eof.ERXEC; 157 - 158 -public class AdminMainPage extends ERXComponent { 159 - 160 - private ERXBatchingDisplayGroup<BlogEntry> _dg; 161 - 162 - public AdminMainPage(WOContext context) { 163 - super(context); 164 - EODatabaseDataSource dataSource = new EODatabaseDataSource(editingContext(), BlogEntry.ENTITY_NAME); 165 - _dg = new ERXBatchingDisplayGroup<BlogEntry>(); 166 - _dg.setNumberOfObjectsPerBatch(20); 167 - _dg.setDataSource(dataSource); 168 - _dg.setObjectArray(BlogEntry.fetchBlogEntries(editingContext(), BlogEntry.AUTHOR.eq(session().loggedAuthor()), BlogEntry.LAST_MODIFIED.descs())); 169 - } 170 - 171 - public ERXBatchingDisplayGroup<BlogEntry> displayGroup() { 172 - return this._dg; 173 - } 174 - 175 175 private String _emailAddress; 176 - 151 + 177 177 public String emailAddress() { 178 178 return this._emailAddress; 179 179 } 180 - 155 + 181 181 public void setEmailAddress(String emailAddress) { 182 182 this._emailAddress = emailAddress; 183 183 } 184 184 185 - private BlogEntry _blogEntryItem; 186 - 187 - public void setBlogEntryItem(BlogEntry blogEntryItem) { 188 - this._blogEntryItem = blogEntryItem; 189 - } 190 - 191 - public BlogEntry blogEntryItem() { 192 - return this._blogEntryItem; 193 - } 194 - 195 195 @Override 196 - public Session session() { 197 - return ((Session)s uper.session());161 + public WOSession session() { 162 + return ((Session)session()); 198 198 } 199 199 200 200 public boolean isLogged() { ... ... @@ -201,221 +201,4 @@ 201 201 return ((session()).loggedAuthor() == null) ? false: true; 202 202 } 203 203 204 - private EOEditingContext _ec; 205 - 206 - public EOEditingContext editingContext() { 207 - if (_ec == null) { 208 - _ec = ERXEC.newEditingContext(); 209 - } 210 - return _ec; 211 - } 212 - 213 - private String _errorMessage = null; 214 - 215 - public String errorMessage() { 216 - return this._errorMessage; 217 - } 218 - 219 - public WOActionResults login() { 220 - Author loggedAuthor = Author.validateLogin(editingContext(), _emailAddress); 221 - if (loggedAuthor != null) { 222 - session().setAuthor(loggedAuthor); 223 - } else { 224 - _errorMessage = "Invalid email address"; 225 - } 226 - return null; 227 - } 228 -} 229 - 230 230 {{/code}} 231 - 232 -You will notice that we are using a ERXBatchingDisplayGroup again. But this time, when we call dg.setObjectArray//, we set the array of objects so that only the blog entries created by the logged author are displayed.// 233 - 234 -Open **AdminMainPage.wo** and override all the content between the <body> tag to be: 235 - 236 -{{code}} 237 - 238 -<wo:AjaxUpdateContainer id="main"> 239 - <wo:if condition="$isLogged"> 240 - <wo:if condition="$displayGroup.hasMultipleBatches"> 241 - <div> 242 - <wo:link action="$displayGroup.displayPreviousBatch">Previous</wo:link> 243 - | Batch 244 - <wo:str value="$displayGroup.currentBatchIndex" /> 245 - of 246 - <wo:str value="$displayGroup.batchCount" /> 247 - | 248 - <wo:link action="$displayGroup.displayNextBatch">Next</wo:link> 249 - </div> 250 - </wo:if> 251 - <table> 252 - <tr> 253 - <th><wo:WOSortOrder displayGroup="$displayGroup" key="title" /> Title</th> 254 - <th>Author</th> 255 - <th><wo:WOSortOrder displayGroup="$displayGroup" key="creationDate" /> Created on</th> 256 - <th><wo:WOSortOrder displayGroup="$displayGroup" key="lastModified" /> Last modified</th> 257 - </tr> 258 - <wo:loop list="$displayGroup.displayedObjects" item="$blogEntryItem"> 259 - <tr> 260 - <td> 261 - <wo:str value="$blogEntryItem.title" /> 262 - </td> 263 - <td> <wo:str value="$blogEntryItem.author.fullName" /> </td> 264 - <td> <wo:str value="$blogEntryItem.creationDate" dateformat="%Y/%m/%d" /> </td> 265 - <td> <wo:str value="$blogEntryItem.lastModified" dateformat="%Y/%m/%d" /> </td> 266 - </tr> 267 - </wo:loop> 268 - </table> 269 - </wo:if> 270 - <wo:else> 271 - <wo:if condition="$errorMessage"> 272 - <span style="text-color: red;">Error: <wo:str value="$errorMessage" /></span> 273 - </wo:if> 274 - <wo:form> 275 - <div> 276 - <label>Email address:</label> 277 - <wo:textField value="$emailAddress" /> 278 - </div> 279 - <div><wo:AjaxSubmitButton updateContainerID="main" action="$login" value="Login" /></div> 280 - </wo:form> 281 - </wo:else> 282 - </wo:AjaxUpdateContainer> 283 - 284 -{{/code}} 285 - 286 -Last step: we need a link to the admin page. Open **Main.wo** and just before the </body> tag, add the following: 287 - 288 -{{code}} 289 - 290 -<wo:link pageName="AdminMainPage">Admin</wo:link> 291 - 292 -{{/code}} 293 - 294 -Save everything, run the app and try to login. If login is not successful, you will get an error message. If login is valid, you will see the blog entries that you created. 295 - 296 -For the last part of this tutorial, we are going to add a link on each blog entry in the list that will bring us to a edit page where we can modify a blog entry. We are also going to add a link to create a new blog entry. 297 - 298 -Create a new component, and name it **EditBlogEntry**. Open **EditBlogEntry.java** and override the code with: 299 - 300 -{{code}} 301 - 302 -package your.app.components; 303 - 304 -import your.app.Session; 305 -import your.app.model.Author; 306 -import your.app.model.BlogEntry; 307 - 308 -import com.webobjects.appserver.WOActionResults; 309 -import com.webobjects.appserver.WOContext; 310 -import com.webobjects.eocontrol.EOEditingContext; 311 - 312 -import er.extensions.components.ERXComponent; 313 -import er.extensions.eof.ERXEC; 314 -import er.extensions.eof.ERXEOControlUtilities; 315 - 316 -public class EditBlogEntry extends ERXComponent { 317 - 318 - public EditBlogEntry(WOContext context) { 319 - super(context); 320 - } 321 - 322 - private BlogEntry _blogEntry; 323 - 324 - public BlogEntry blogEntry() { 325 - return this._blogEntry; 326 - } 327 - 328 - public void setBlogEntry(BlogEntry blogEntry) { 329 - if (blogEntry == null) { 330 - this._blogEntry = ERXEOControlUtilities.createAndInsertObject(editingContext(), BlogEntry.class); 331 - Author localUser = ERXEOControlUtilities.localInstanceOfObject(editingContext(), session().loggedAuthor()); 332 - this._blogEntry.setAuthorRelationship(localUser); 333 - } else { 334 - this._blogEntry = ERXEOControlUtilities.localInstanceOfObject(editingContext(), blogEntry); 335 - } 336 - } 337 - 338 - private EOEditingContext _ec; 339 - 340 - public EOEditingContext editingContext() { 341 - if (_ec == null) { 342 - _ec = ERXEC.newEditingContext(); 343 - } 344 - return _ec; 345 - } 346 - 347 - @Override 348 - public Session session() { 349 - return ((Session)super.session()); 350 - } 351 - 352 - public WOActionResults save() { 353 - editingContext().saveChanges(); 354 - return pageWithName(AdminMainPage.class); 355 - } 356 -} 357 - 358 -{{/code}} 359 - 360 -Open **EditBlogEntry.wo** and between the <body> tag, add the following: 361 - 362 -{{code}} 363 - 364 -<wo:form> 365 - <div> 366 - <label>Title:</label> 367 - <wo:textfield value="$blogEntry.title" /> 368 - </div> 369 - <div> 370 - <label>Content:</label> 371 - <wo:text value="$blogEntry.content" rows="20" cols="80" /> 372 - </div> 373 - <div>Author: <wo:str value="$session.loggedAuthor.fullName" /></div> 374 - <div><wo:submitButton action="$save" value="Save changes" /></div> 375 - </wo:form> 376 - 377 -{{/code}} 378 - 379 -We now have a form to edit or create a blog entry. Save the component and the Java class, and open **AdminMainPage.java** to add the following code: 380 - 381 -{{code}} 382 - 383 -public WOActionResults editBlogEntry() { 384 - EditBlogEntry nextPage = pageWithName(EditBlogEntry.class); 385 - nextPage.setBlogEntry(_blogEntryItem); 386 - return nextPage; 387 - } 388 - 389 - public WOActionResults createBlogEntry() { 390 - EditBlogEntry nextPage = pageWithName(EditBlogEntry.class); 391 - nextPage.setBlogEntry(null); 392 - return nextPage; 393 - } 394 - 395 -{{/code}} 396 - 397 -Open **AdminMainPage.wo** and just after <wo:if condition="$isLogged">, add the following line: 398 - 399 -{{code}} 400 - 401 -<div><wo:link action="$createBlogEntry">Create a new blog entry</wo:link></div> 402 - 403 -{{/code}} 404 - 405 -Find this line: 406 - 407 -{{code}} 408 - 409 -<wo:str value="$blogEntryItem.title" /> 410 - 411 -{{/code}} 412 - 413 -and replace it with: 414 - 415 -{{code}} 416 - 417 -<wo:link action="$editBlogEntry"><wo:str value="$blogEntryItem.title" /></wo:link> 418 - 419 -{{/code}} 420 - 421 -Save everything, run the app, click on the "admin" link, login and check if you can create or edit a blog entry. Everything should be working, and just created your first stateful Project Wonder application [[It's time to deploy an application>>Your First Deployment]].