Version 23.1 by Andy Tripp on 2020/06/10

Hide last authors
Andy Tripp 4.1 1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
Andy Tripp 1.1 4
Andy Tripp 9.1 5 This tutorial will show you how to build a Contact Manager application.  It's very similar to the [[Documentation.DevGuide.Tutorials.FAQTutorial.FAQTutorialManual]] tutorial. The only difference (so far) is that the FAQ tutorial involves a very trivial object: a FAQ object contains just two things: a "question" and an "answer", while this example uses a Person object that has more properties ("name", "age", "sex", etc.) .This is a very simple application that makes use of XWiki's [[classes, properties, and objects>>platform:DevGuide.DataModel||anchor="HXWikiClasses2CObjects2CandProperties"]]. It also uses a technique that you may frequently use as the basis for several different kinds of applications.
Andy Tripp 1.1 6
7 Also, this tutorial explains things a little differently than the FAQ tutorial. If something here doesn't make sense to you, try going through the FAQ tutorial and maybe it will make more sense.
8
Andy Tripp 4.1 9 = Prerequisites for following the tutorial =
Andy Tripp 1.1 10
Andy Tripp 4.1 11 You should have [[installed XWiki>>platform:AdminGuide.Installation]] and have a [[basic understanding of how to use it>>platform:Features.WebHome]].
Andy Tripp 1.1 12
Andy Tripp 4.1 13 All through this tutorial you should refer to the [[XWiki Data Model>>platform:DevGuide.DataModel]] for information on XWiki's data model. You might also use the [[XWiki Scripting Guide>>platform:DevGuide.Scripting]] to get you started with scripting in XWiki and manipulating XWiki objects. In addition, this tutorial will introduce the concepts of Authoring Templates and Page Design Sheets, patterns that you will find particularly useful in creating XWiki applications. Completing this tutorial is a recommended prerequisite for anyone who wants to build custom applications on the XWiki engine. And by "custom application", we mean a huge variety of web applications.
Andy Tripp 1.1 14
Andy Tripp 4.1 15 {{warning}}
16 Make sure that your user is an [[Advanced user>>platform:Features.PageEditing||anchor="HAdvancedMode"]] before following this tutorial since you'll need for example to use the wiki editor (##Wiki > Edit## menu).
17 {{/warning}}
Andy Tripp 1.1 18
Andy Tripp 4.1 19 = Application Overview =
Andy Tripp 1.1 20
Andy Tripp 9.1 21 The Person Manager application will allow users to create a "Person object" by entering data (name, age, sex, etc) into a simple form and then submitting the form. Let's sketch out what roughly what those two pages should look like on a "napkin", using [[Balsamiq>>https://balsamiq.com/]]:
Andy Tripp 1.1 22
Andy Tripp 4.1 23 image:personDialog.PNG
Andy Tripp 1.1 24
Andy Tripp 4.1 25 Our page won't look exactly like that, but the point is that a website user can create a Person by filling out a "form" page like this.
Andy Tripp 1.1 26
Andy Tripp 14.1 27 Note all the various types of "widgets" shown here:
28
29 * "name" is a single-line text field
30 * "email" is also a single-line text field, but we'd like it to be validated (e.g. give an error if it doesn't have a "@" in it)
31 * "address" is a multi-line text field
32 * "phone" is a single-line text field (perhaps some validation here, too)
33 * "sex" is a drop-down list
34 * "married" is a checkbox: the only allowed values are "true" and "false"
35 * "image" is actually the name of some image file, but we actually display the image itself. Nice!
36 * "age" is Number field, which looks like a single-line text field, but has validation.
37 * "related people" is one more more links to other web pages. Very nice!
38
Andy Tripp 4.1 39 The Person then appears in a table with all other Person objects that have been previously created. Users can click on the Person in the table to see all the information about the Person. He may also edit that information or delete the Person. The table might look something like this:
Andy Tripp 1.1 40
Andy Tripp 4.1 41 image:personTable.PNG
Andy Tripp 1.1 42
Andy Tripp 4.1 43 When the user clicks on a row in the table, he will get a page that shows the information about the Person, which will look similar to the "Create Person" page, but without the ability to change anything.
Andy Tripp 1.1 44
Andy Tripp 4.1 45 == Objects Overview And Terminology ==
Andy Tripp 1.1 46
Andy Tripp 7.1 47 Next, let's summarize the terminology for "Objects". For full details, see [[Data Model>>https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/DataModel/#HXWikiClasses2CObjects2CandProperties]]. There is nothing fancy happening here, but it's important to get our terminology straight.
Andy Tripp 1.1 48
Andy Tripp 9.1 49 A Person is an example of some "Object" or "class". We will use XWiki to define what "properties" are in a "Person" object. For example, we will say that there's a property called "name" of type "String". There's also a property called "age" of type "Number", and an "address" property that's type "TextArea" (a string that can be multiple lines).
Andy Tripp 7.1 50
Andy Tripp 4.1 51 When a user creates a new Person, we call that an "instance" of the "class". So we might say something like "I've created an instance of the Person class, with name 'Joe Smith'". And we would say that our table shows all the instances of the Person class. And instances can not only be created, but also edited or deleted.
Andy Tripp 1.1 52
Andy Tripp 7.1 53 We, the creators of the website, define the "Person" class. We define that once, and we're done. Our users use our website to create, edit, and delete instances of our Person class.
54
Andy Tripp 4.1 55 == Overview Of What We Will Do ==
Andy Tripp 7.1 56
Andy Tripp 4.1 57 In this tutorial, we'll do the following steps:
Andy Tripp 1.1 58
Andy Tripp 9.1 59 * Define our Person class, using the XWiki "Data Types" page.
60 * Specify the properties of our Person class, using the XWiki "Class Editor" page.
Andy Tripp 4.1 61 * Define how a Person instance should be displayed, by creating a "Person Sheet" page.
62 * Create a Template and a Template Provider (whatever they are) for our Person class.
Andy Tripp 7.1 63 * Create a web page that displays a table of people.
Andy Tripp 22.1 64 * For each Person that you want to create, create a page and add an instance of our Person class to the page.
Andy Tripp 1.1 65
Andy Tripp 7.1 66 Note that we don't need to define a page for creating or editing a Person, just a page for *displaying* a Person. XWiki will automatically do that for us!
Andy Tripp 1.1 67
Andy Tripp 7.1 68 Once we are done with these steps, our application will be finished. A user of our website can see a page containing the table of Person objects, view the page for an existing person, add a new Person, edit an existing Person, or delete a Person.
Andy Tripp 1.1 69
Andy Tripp 7.1 70 = Go to the Special "Data Types" Page =
Andy Tripp 1.1 71
Andy Tripp 7.1 72 The "Data Types" page is a special XWiki page that lets us define classes like "Person". It'sactually hidden by default. To be "unhide" it, go to your profile page, select the Preferences tab, edit the page and choose to view Hidden Documents.
Andy Tripp 4.1 73
Andy Tripp 9.1 74 To find the "Data Types" page, enter a search query for the keyword "D". This should return a document titled "Data Types".
Andy Tripp 7.1 75
Andy Tripp 4.1 76 = Create the Person Class =
77
Andy Tripp 7.1 78 * On the "Data Types" page, under the heading "Create a new data type", in the "Title" field, enter ##Person## as the name of the page to create:(((
79 {{image reference="personClass.PNG"/}}
Andy Tripp 4.1 80 )))
Andy Tripp 7.1 81 * As you can see in the Breadcrumb below the new page will be created at location ##XWiki > Person##. In practice the "Data Types" page will automatically prefix the page name with ##Class## (you could also enter ##PersonClass## as the page name directly).
82 * Now it would be nice to have it created in a new location such as ##PersonSpace > Person Class##. Since the ##PersonSpace## parent doesn't exist we cannot use the Tree picker button. Thus click the Pencil button as shown in the following image and replace ##XWiki## by ##PersonSpace##.(((
83 {{image reference="personLocation.PNG"/}}
Andy Tripp 4.1 84 )))
Andy Tripp 7.1 85 * In technical terms you're creating a page named ##PersonClass## (with a title of "Person Class") located in a space also called ##PersonSpace## and thus the technical reference is ##PersonSpace.PersonClass##.
Andy Tripp 4.1 86 * Click the "Create this Class" button. You should then see a page with the following content:(((
87 {{code language="none"}}
88 {{velocity}}
89 ## Replace the default space with the space where you want your documents to be created.
90 ## Replace the default parent with the one of your choice and save the document.
91 ##
Andy Tripp 1.1 92 #set($defaultSpace = $doc.space)
93 #set($defaultParent = $doc.fullName)
Andy Tripp 4.1 94 {{/velocity}}
95 {{/code}}
96 )))
Andy Tripp 1.1 97
Andy Tripp 7.1 98 In the code, change the word "$doc.space" with the name of the space where you want your pages to be created: "PersonSpace".
Andy Tripp 1.1 99 The line of code should look like this:
100
Andy Tripp 4.1 101 {{code language="none"}}
Andy Tripp 7.1 102 #set($defaultSpace = 'PersonSpace')
Andy Tripp 4.1 103 {{/code}}
Andy Tripp 1.1 104
105 You can also change the default parent of the new FAQ documents that are going to be created. To do so, replace the "$defaultParent" variable with the name of your document.
106 The line of code should look like this:
107
Andy Tripp 4.1 108 {{code language="none"}}
Andy Tripp 7.1 109 #set($defaultParent = 'PersonSpace.WebHome')
Andy Tripp 4.1 110 {{/code}}
Andy Tripp 1.1 111
Andy Tripp 7.1 112 Click the "Save & View" button. The class is now created and you should be looking at a page titled "Class: Person" that looks like this:
Andy Tripp 1.1 113
Andy Tripp 9.1 114 {{image reference="newPersonClass.PNG"/}}
Andy Tripp 1.1 115
Andy Tripp 4.1 116 = Add Properties to the Class =
Andy Tripp 1.1 117
Andy Tripp 4.1 118 Under the page title, you should see the words "The class does not have any properties yet. You can use the //__class editor__// to define them." Let's just follow those instructions!
Andy Tripp 1.1 119
Andy Tripp 4.1 120 * Click on the 'class editor' link
Andy Tripp 9.1 121 * Note that the link trail in the header is something like "Wiki Home / PersonSpace / Person Class". This shows you that you are indeed on the Person class page in Class edit mode.
Andy Tripp 1.1 122
Andy Tripp 9.1 123 Now, we need to specify all the properties of a Person. Let's have the following properties:
Andy Tripp 12.1 124
Andy Tripp 14.1 125 |=Property Name|=Property Type
Andy Tripp 9.1 126 |name|String
127 |email|EMail
128 |address|TextArea
129 |phone|String
130 |sex|static list
131 |married|Boolean
132 |image|Image
133 |age|Number
Andy Tripp 14.1 134 |relatedPeople|Page (Multiple)
Andy Tripp 1.1 135
Andy Tripp 9.1 136 * Enter the text //name// in the "name" field
Andy Tripp 14.1 137 * Choose "String" for the type of the property and then click on "Add". By using a String type, when a user goes to enter the //name// of a new Person, he will be prompted with a single-line text field.(((
Andy Tripp 9.1 138 {{image reference="name.PNG"/}}
Andy Tripp 4.1 139 )))
140 * Click on the "+" icon to expand the options for the newly created property
Andy Tripp 14.1 141 * Change the value of the "Pretty Name" field to "Name"(capital N). With this done, the user sees the label "Name" rather than "name" when prompted for the name of a Person. This doesn't make a huge difference for this property, but when it comes to the property with the name "relatedPeople", it's nice to show the user something a little more friendy like "Related People". Also, you could later decide to change that label to "Similar People" without actually renaming the property (and thereby probably breaking something).
Andy Tripp 9.1 142 * Now repeat this to add each of the properties shown in the table above.
Andy Tripp 12.1 143 ** Note that the "EMail" type is like a String, except that it has a "Validation Expression" (e.g. to make sure it has an "@" character).
144 ** If we wanted to, we could add a "Validation Expression" to the "phone" property to make sure it's in a particular format.
Andy Tripp 14.1 145 ** For the "sex" property, in the "Display Type" field, enter "Select". This will give the user a drop-down menu.
146 ** As we define the "sex" property as type "static list", we specify the values for the field like this:(((
Andy Tripp 12.1 147 {{image reference="staticList.PNG"/}}
148 )))
Andy Tripp 14.1 149 ** Note that there is no "Image" type. That's unfortunate. Let's just define it as a String here, and deal with that later.
150 ** Note that the "size" of our "age" field is 30 digits. Three digits should be plenty, so feel free to change that.
151 ** For our "relatedPeople" property, we want to allow multiple values, not just one. So find the "Multi Select" checkbox and check it.
152 * When you are done, you should see all your properties like this:(((
Andy Tripp 12.1 153 {{image reference="properties.PNG"/}}
154 )))
Andy Tripp 4.1 155 * When you are done adding and configuring the properties, click the "Save & View" button
Andy Tripp 1.1 156
Andy Tripp 4.1 157 = Create the Page Design Sheet =
Andy Tripp 1.1 158
Andy Tripp 4.1 159 * After the previous step you are now on the FAQClass page which should look like this:(((
Andy Tripp 14.1 160 {{image reference="personClass2.PNG"/}}
Andy Tripp 4.1 161 )))
162 * Click the first button ("Create the document sheet") to create the document sheet (the Page Design Sheet). This sheet determines how your page's objects will be rendered to the user. The document is automatically created.
Andy Tripp 18.1 163 * You should see a warning message with the text "The sheet is not bound to the class so it won't be applied automatically when a page that has an object of this class is displayed". Click the "Bind the sheet to the class" link that appears after the text. Basically, this ties the Person Class to the Person Sheet.
Andy Tripp 16.1 164 * Now click on "View the sheet document". This takes you to the ##PersonSpace.PersonSheet## page which you can edit in wiki mode and see its default content. This content is Velocity code which simply goes through all the properties and displays each one. For example, it will see that our Person class has a "married" property of type "Boolean", and will show a checkbox with a label of "married" (or perhaps "Married" if we specified that as our "pretty name" for the property). See [[Documentation.DevGuide.Tutorials.FAQTutorial.FAQTutorialManual]] for more details about this code. This code is actually very close to working as-is. The only thing that would be ugly is that our "image" property would display as just a String, whereas we probably want to display the image itself, not some URL.
Andy Tripp 1.1 165
Andy Tripp 4.1 166 * Click "Save & View"
Andy Tripp 1.1 167
Andy Tripp 4.1 168 = Create the Authoring Template =
Andy Tripp 1.1 169
Andy Tripp 16.1 170 * Navigate back to the ##PersonSpace.PersonClass## document (you can use the arrows in the breadcrumb to do so).
Andy Tripp 4.1 171 * Click on the "Create the document template" button. The Authoring Template will be automatically created.
Andy Tripp 1.1 172
Andy Tripp 16.1 173 Note that earlier, we changed the space name preceding the page name because we wanted all of our Person pages to reside in a space named PersonSpace. Remember that all our documents will be copies of the Authoring Template used as a prototype so the content will be copied in all our Person documents and will execute the Design Sheet code in the context of the current document. See the [[dedicated page>>platform:DevGuide.IncludeInVelocity]] for more information regarding this technique.
Andy Tripp 1.1 174
175 Now we need to associate the prototype object with this document to turn it into a true authoring template:
176
Andy Tripp 16.1 177 * If you're on the template page, navigate back to the ##PersonSpace.PersonClass## document.
178 * At the bottom of the page, look for the following warning message: "The template does not contain an object of type PersonClass. Add a Person object to the template »."
179 * Click on "Add a Person object to the template »":(((
Andy Tripp 18.1 180 {{image reference="personClass3.PNG"/}}
Andy Tripp 4.1 181 )))
Andy Tripp 1.1 182
183 Next, we want to remove the title for the newly created template:
184
Andy Tripp 18.1 185 * Navigate to the ##PersonSpace.PersonTemplate## document (you can click on the "View the template page (PersonSpace / Person Template)" link for doing that for example.
Andy Tripp 4.1 186 * Edit this document in Wiki mode
Andy Tripp 18.1 187 * Inside the Title field you have "Person Template" written -> delete this text
Andy Tripp 4.1 188 * Save & View
Andy Tripp 1.1 189
Andy Tripp 18.1 190 This step is needed so that all of our future entries don't have "Person Template" as their title.
Andy Tripp 1.1 191
192 Congratulations: you just created an Authoring Template! You're almost done now.
193
Andy Tripp 4.1 194 = Create the Template Provider =
Andy Tripp 1.1 195
Andy Tripp 20.1 196 After the template was created and the object was added, a new section appears with a button to create a template provider to use the existing template. Click that button.
Andy Tripp 1.1 197
Andy Tripp 20.1 198 (((
199 {{image reference="personClass4.PNG"/}}
200 )))
Andy Tripp 1.1 201
Andy Tripp 20.1 202 = Create a home page for the Person Manager application =
Andy Tripp 1.1 203
Andy Tripp 20.1 204 Now we are finished defining our Person class, and it's time to create our web pages. Recall that we only have two pages to create:
Andy Tripp 1.1 205
Andy Tripp 20.1 206 * A "main" page that contains a table of Person objects.
207 * A "Person" page that displays a single Person
208 * (We don't need to create a "form" page for creating a new Person or edit an existing person - XWiki does that for us)
Andy Tripp 4.1 209
Andy Tripp 22.1 210 Our "main" page will be the ##PersonSpace.WebHome## page.
Andy Tripp 1.1 211
Andy Tripp 20.1 212 * Click on "PersonSpace" in the breadcrumb to navigate to ##PersonSpace.WebHome## and notice that the page doesn't exist yet.
Andy Tripp 4.1 213 * Edit it in wiki mode
Andy Tripp 20.1 214 * Type in the title "People"
Andy Tripp 1.1 215
Andy Tripp 20.1 216 == Displaying existing Person entries ==
Andy Tripp 1.1 217
Andy Tripp 20.1 218 You have 2 options when it comes to displaying existing Person entries:
Andy Tripp 1.1 219
Andy Tripp 4.1 220 1. Use the livetable component
Andy Tripp 20.1 221 1. Write custom code in order to display them in a table
Andy Tripp 1.1 222
Andy Tripp 20.1 223 We will only cover the "custom code" option here, because it's actually very easy to write a little code to display the table the way we want to. See the "Using the Livetable component" section of the [[Documentation.DevGuide.Tutorials.FAQTutorial.FAQTutorialManual]] page for instructions to use a "livetable" instead.
Andy Tripp 1.1 224
Andy Tripp 20.1 225 To create our table, we need to think about Objects, not web pages. As people use our application, they create new instances of our Person class - they create Objects. Let's say there have been three "Person" objects created so far. That means there will be three rows in our table. But how do we write code for this table? We will need to "query the XWiki database" - essentially tell XWiki "get me all the instances of the PersonClass that exist". XWiki provides [[several different ways>>https://extensions.xwiki.org/xwiki/bin/view/Extension/Query%20Module]] to do this query:
Andy Tripp 1.1 226
Andy Tripp 20.1 227 * XWiki Query Language (XWQL)
228 * Hibernate Query Language (HQL)
229 * Solr Query Language (SOLR)
Andy Tripp 1.1 230
Andy Tripp 20.1 231 The [[Documentation.DevGuide.Tutorials.FAQTutorial.FAQTutorialManual]] page tells you how to use XWQL, but I will show you how to use SOLR. Why is SOLR "better"? It's a bit of a standard, it's very well documented, very flexible and fast. It's also pretty simple.
Andy Tripp 1.1 232
Andy Tripp 20.1 233 Regardless of which of these techniques we use to query, we will be writing code in the [[Velocity Template Language>>https://velocity.apache.org/engine/1.7/user-guide.html]].
Andy Tripp 1.1 234
Andy Tripp 4.1 235 === Using custom code ===
Andy Tripp 1.1 236
237 You will need to write the following code:
238
Andy Tripp 20.1 239 * Display a header above the table that says "People"
240 * Do SOLR query to get all documents (i.e. pages) containing an instance of PersonClass, with a "name" property of any value.
241 * Let's limit the number of results to 1000 because the default for SOLR is 10 and that's too low.
242 * Let's use XWiki syntax to create a table with three columns: Name, Email, and Phone (note that we don't bother to show all properties of a Person as columns in our table, but we could if we wanted).
243 * Loop through each document, doing the following:
244 ** find the PersonClass instance on the page. Set a variable called $object to that.
245 ** get the "name" property from the instance and display that in the first column of the table.
246 ** get the "email" property from the instance and display that in the second column of the table.
247 ** get the "phone" property from the instance and display that in the third column of the table.
Andy Tripp 1.1 248
249 Here is the resulting code:
250
Andy Tripp 4.1 251 {{code language="none"}}
252 {{velocity}}
Andy Tripp 20.1 253 = People =
254 #set ($className = 'PersonSpace.PersonClass')
255 #set ($attr = 'name')
256 #set ($queryStatement = "property.$className.$attr:*")
257 #set ($query = $services.query.createQuery($queryStatement, 'solr'))
258 #set ($discard = $query.bindValue('rows', '1000'))
259 #set ($searchResponse = $query.execute()[0])
260 |=Name|=Email|=Phone
261 #foreach ($searchResult in $searchResponse.results)
262 #set ($documentReference = $services.solr.resolveDocument($searchResult))
263 #set ($d = $xwiki.getDocument($documentReference))
264 #set ($object = $d.getObject("$className"))
265 #if ($object.getProperty('name').getValue() != '')
266 |$object.getProperty('name').getValue()##
267 |$object.getProperty('email').getValue()##
268 |$object.getProperty('phone').getValue()
269 #end
Andy Tripp 1.1 270 #end
Andy Tripp 4.1 271 {{/velocity}}
272 {{/code}}
Andy Tripp 1.1 273
Andy Tripp 20.1 274 Notes:
Andy Tripp 22.1 275
Andy Tripp 20.1 276 * (TODO: explain why the check for empty name is needed - is the query returning the Template or class definition?)
Andy Tripp 22.1 277 * The "##" characters at the end of the lines showing rows in the table are required because XWiki wants all table data for a row to be on a single line.##
Andy Tripp 20.1 278 * TODO: explain Document, DocumentReference, and link to the javadoc.
279
280 * Copy this code and paste it as Wiki content inside ##PersonSpace.WebHome##
Andy Tripp 4.1 281 * Click "Save and View"
Andy Tripp 20.1 282 * New Person entries will now be displayed on the page once you create them.
Andy Tripp 1.1 283
Andy Tripp 20.1 284 At this point, your ##PersonSpace.WebHome## page will just display as an empty table because no instances of PersonClass have been created yet.
Andy Tripp 1.1 285
Andy Tripp 20.1 286 == Creating new Person instances ==
Andy Tripp 1.1 287
Andy Tripp 20.1 288 There are 2 ways for you to let your users create new instances of our PersonClass:
Andy Tripp 1.1 289
Andy Tripp 20.1 290 1. Declare the Person as a template
Andy Tripp 4.1 291 1. Add a custom creation form
Andy Tripp 1.1 292
Andy Tripp 22.1 293 The [[Documentation.DevGuide.Tutorials.FAQTutorial.FAQTutorialManual]] page describes how to create a custom form if you want to do that. But the simpler way is for you to use a template. Remember earlier, on the Person Class page, we clicked on a button to create a template, and clicked on another button to create a "Template Provider"? That's all we needed to do! 
Andy Tripp 1.1 294
Andy Tripp 20.1 295 With that done, let's go ahead and create an instance of PersonClass. Go to your PersonSpace.WebHome page (the one with the table), and click the "Create" button to create a child page. You will be prompted for a page title and page type. In the list of Types, under "Template" you should see "Person":
296 image:createPerson.PNG
Andy Tripp 1.1 297
Andy Tripp 22.1 298 Fill in the person's name as the page title, choose the "Person" type, and click "Create."
299 You will then be prompted for all the information about your the Person instance that you want to create:
300 image:createPerson2.PNG
Andy Tripp 1.1 301
302 If you previously chose to use a "Custom creation form" for creating new FAQ entries, follow these steps:
303
Andy Tripp 4.1 304 * Go to ##FAQ.WebHome##
305 * Below the "Add a new question" header, enter a question (which will also be used as the document title) in the //Document// field
306 * Click //Create this FAQ//
307 * You can then enter your question in longer form using the //Question// field on the template, like this:(((
308 {{image reference="FAQSheetEdit.PNG"/}}
309 )))
310 * Click //Save & View// and then you will see the newly created document, like this:(((
311 {{image reference="FAQSheetView.PNG"/}}
312 )))
313 * Go back to the ##FAQ.WebHome## page (you can use the breadcrumbs) to see the list of existing questions(((
314 {{image reference="FAQsWithEntry.png"/}}
315 )))
Andy Tripp 1.1 316
Andy Tripp 4.1 317 = Conclusion =
Andy Tripp 1.1 318
319 This tutorial has taught you how to use the Class Wizard app and it has detailed the concepts of classes, objects and properties and introduced the authoring templates and page design sheets.
320
321 You may also have learned a little bit about Velocity scripting in documents. You can use these basic concepts to build custom applications at the document or presentation layer of XWiki without having to compile or deploy code.
322
323 As always, please take the time to make this document better for other users if you find ways that it can be improved as you read it for the first time.

Get Connected