Wiki source code of Your First Stateful Project

Version 8.1 by Pascal Robert on 2012/08/09 03:52

Show last authors
1 {{info}}
2 Work in progress
3 {{/info}}
4
5 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.
6
7 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.
8
9 In this tutorial, we are also going to use the Ajax framework, who is stateful too. We will replicate the functionalities of the two other tutorials, but by creating pages ourselves. The application will have the following pages:
10
11 * The main page will display a list of blog entries, with a link to see the blog entry.
12 * The main page will have a link to an "admin" page that will show a login form.
13 * After login, a list of blog entries with links to edit, delete and create blog entries will be show.
14 * We need a form to edit/create blog entries.
15
16 Let's start by creating a new project in Eclipse. You need to create a **Wonder Application** project type, and name it **StatefulBlog**.
17
18 [[image:Capture d’écran 2012-08-06 à 04.56.13.png||border="1"]]
19
20 Just like the D2W tutorial, you need to link the application with the **BlogCommon**, **Ajax** and **H2PlugIn** frameworks. To do so, right-click on **StatefulBlog** and select **Build Path** > **Configure Build Path**. 
21
22 [[image:Capture d’écran 2012-07-29 à 14.25.46.png||border="1"]]
23
24 In the **Libraries** tab, click on **Add Library**. Select **WebObjects Frameworks** and click **Next**. Check **Ajax**, **BlogCommon** and **H2PlugIn** from the list and click **Finish**. The **Libraries** tab should look like this:
25
26 [[image:Capture d’écran 2012-08-06 à 05.15.32.png||border="1"]]
27
28 We are ready to code Open the **Components** folder of the project, and open **Main WO**. In the **Related** view (bottom-right), you see that all related files of the component are listed, and we need to open the Java code associated with the component. To do so, in the **Related** view, double-click on **Main.java** to open the Java class into an editor.
29
30 In **Main.java**, we need some Java code to get the list of blog entries so that we can show that list into the component. The following code will do what we need:
31
32 {{code}}
33
34 import your.app.model.BlogEntry;
35
36 import com.webobjects.appserver.WOContext;
37 import com.webobjects.eoaccess.EODatabaseDataSource;
38 import com.webobjects.eocontrol.EOEditingContext;
39
40 import er.extensions.batching.ERXBatchingDisplayGroup;
41 import er.extensions.components.ERXComponent;
42 import er.extensions.eof.ERXEC;
43
44 public class Main extends ERXComponent {
45
46 private EOEditingContext _ec;
47 private BlogEntry _blogEntryItem;
48
49 public Main(WOContext context) {
50 super(context);
51 EODatabaseDataSource dataSource = new EODatabaseDataSource(editingContext(), BlogEntry.ENTITY_NAME);
52 ERXBatchingDisplayGroup<BlogEntry> dg = new ERXBatchingDisplayGroup<BlogEntry>();
53 dg.setNumberOfObjectsPerBatch(20);
54 dg.setDataSource(dataSource);
55 dg.setObjectArray(BlogEntry.fetchAllBlogEntries(editingContext(), BlogEntry.LAST_MODIFIED.descs()));
56 }
57
58 private EOEditingContext editingContext() {
59 if (_ec == null) {
60 _ec = ERXEC.newEditingContext();
61 }
62 return _ec;
63 }
64
65 public void setBlogEntryItem(BlogEntry blogEntryItem) {
66 this._blogEntryItem = blogEntryItem;
67 }
68
69 public BlogEntry blogEntryItem() {
70 return this._blogEntryItem;
71 }
72
73 }
74
75 {{/code}}
76
77 [[ERXBatchingDisplayGroup>>http://jenkins.wocommunity.org/job/Wonder/lastSuccessfulBuild/javadoc/er/extensions/appserver/ERXDisplayGroup.html]] is a subclass of WODisplayGroup, a utility that adds multiple actions and logic to a list of objects. One of the best features of ERXBatchingDisplayGroup is that it does real batching (if the RDBMS that you use supports it), so that means that if we specify a batch of 20 objects (//dg.setNumberOfObjectsPerBatch(20)//), it will fetch only the first 20 objects from the database, and if you switch to the next batch, the display group will go to the database to get the next 20 objects. ERXBatchingDisplayGroup is useful if you known that your list will contains hundred of objects.
78
79 Let's edit the component. Open **Main.wo** and edit the content in the top panel to be:
80
81 {{code}}
82
83 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
84 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
85 <head>
86 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
87 <title>untitled</title>
88 </head>
89 <body>
90 <h1>Our super blog</h1>
91 <wo:if condition="$displayGroup.hasMultipleBatches">
92 <div>
93 <wo:link action="$displayGroup.displayPreviousBatch">Previous</wo:link>
94 | Batch
95 <wo:str value="$displayGroup.currentBatchIndex" />
96 of
97 <wo:str value="$displayGroup.batchCount" />
98 |
99 <wo:link action="$displayGroup.displayNextBatch">Next</wo:link>
100 </div>
101 </wo:if>
102 <wo:loop list="$displayGroup.displayedObjects" item="$blogEntryItem">
103 <p><wo:str value="$blogEntryItem.title" /></p>
104 <p><wo:str value="$blogEntryItem.content" escapeHTML="false" /></p>
105 <p>Created by
106 <wo:str value="$blogEntryItem.author.fullName" />
107 on
108 <wo:str value="$blogEntryItem.creationDate" />
109 </p>
110 <hr />
111 </wo:loop>
112 </body>
113 </html>
114
115 {{/code}}
116
117 The condition //displayGroup.hasMultipleBatches// checks if we have more than 20 objects. If that's true, we will show a HTML div with links to navigate between batches. After that condition, we loop over the displayedObjects (the current batch of objects) and we use WOString elements to display details about each blog entry.
118
119 You can run the application to check if everything is working. If everything is ok, terminate the app.
120
121 The next steps is to build the administration part of the application. The first thing we need to do is to add a variable and two methods in **Session.java** that will store the logged user. Open **Session.java** and add the following code:
122
123 {{code}}
124
125 private Author _loggedAuthor;
126
127 public Session() {
128 this._loggedAuthor = null;
129 }
130
131 public Author loggedAuthor() {
132 return this._loggedAuthor;
133 }
134
135 public void setAuthor(Author loggedAuthor) {
136 this._loggedAuthor = loggedAuthor;
137 }
138
139
140 {{/code}}
141
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**.
143
144 After the component have been created, open **AdminMainPage.java** and add the following code:
145
146 {{code}}
147
148 import your.app.Session;
149
150 private String _emailAddress;
151
152 public String emailAddress() {
153 return this._emailAddress;
154 }
155
156 public void setEmailAddress(String emailAddress) {
157 this._emailAddress = emailAddress;
158 }
159
160 @Override
161 public WOSession session() {
162 return ((Session)session());
163 }
164
165 public boolean isLogged() {
166 return ((session()).loggedAuthor() == null) ? false: true;
167 }
168
169 {{/code}}