ITC382 11255412 A1B
From PeacockWiki
Revision as of 02:07, 26 August 2005 (edit) Trevorp (Talk | contribs) (→The Scenario) ← Previous diff |
Revision as of 02:20, 26 August 2005 (edit) Trevorp (Talk | contribs) (→Sample project) Next diff → |
||
Line 188: | Line 188: | ||
<div id="reference">[http://www.sandcastsoftware.com/downloads/brownbag/tapestry/tapestry-crud-a4.pdf Sandcast Software <i>Creating a CRUD application (pt. 1)</i>]</div> | <div id="reference">[http://www.sandcastsoftware.com/downloads/brownbag/tapestry/tapestry-crud-a4.pdf Sandcast Software <i>Creating a CRUD application (pt. 1)</i>]</div> | ||
+ | ====View List==== | ||
+ | Create a new Tapestry Page called ViewList, again, creating a class for it in the same package as previously. | ||
+ | Enter the following into ViewList.java | ||
+ | <pre> | ||
+ | import java.util.ArrayList; | ||
+ | import org.apache.tapestry.IRequestCycle; | ||
+ | import org.apache.tapestry.html.BasePage; | ||
+ | import com.peacocktech.tapestry.lists.model.List; | ||
+ | import com.peacocktech.tapestry.lists.model.Post; | ||
+ | |||
+ | public class ViewList extends BasePage { | ||
+ | private List list; | ||
+ | public Post post; | ||
+ | |||
+ | public String getListName() { | ||
+ | return list.getName(); | ||
+ | } | ||
+ | |||
+ | public void setList(List list) { | ||
+ | this.list= list; | ||
+ | } | ||
+ | |||
+ | public ArrayList<Post> getPosts() | ||
+ | { | ||
+ | return list.getPosts(); | ||
+ | } | ||
+ | |||
+ | public void viewPost(IRequestCycle r) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </pre> | ||
+ | And the following into ViewList.html | ||
+ | <pre> | ||
+ | <span jwcid="@Page"> | ||
+ | Viewing List: <span jwcid="@InsertText" value="ognl:listName"/><br /> | ||
+ | <table border="1"> | ||
+ | <tr jwcid="@Foreach" source="ognl:posts" value="ognl:post" element="tr"> | ||
+ | <td><span jwcid="@Insert" value="ognl:post.date"/></td> | ||
+ | <td><span jwcid="@Insert" value="ognl:post.from" raw="true"/></td> | ||
+ | <td><span jwcid="@ActionLink" listener="ognl:listeners.viewPost"><span jwcid="@Insert" value="ognl:post.subject"/></span></td> | ||
+ | </tr> | ||
+ | </table> | ||
+ | </span> | ||
+ | </pre> | ||
+ | |||
+ | Relationships in this are similar to the last section. @Page calls our first component to set up the html and body tags. listName calls getListName in the java file, posts calls getPosts, while post refers to the post field. post again is an object from the model, containing methods getDate, getFrom and getSubject. listeners.viewPost refers to viewPost from the java code. | ||
+ | |||
+ | To get this page working, we must flesh out the two methods from the previous component, ListSelector.java | ||
+ | <pre> | ||
+ | public void selectList(IRequestCycle r) { | ||
+ | ViewList viewList = (ViewList) r.getPage("ViewList"); | ||
+ | viewList.setList(lists.getList(listName)); | ||
+ | r.activate(viewList); | ||
+ | } | ||
+ | public void viewList(IRequestCycle r) { | ||
+ | ViewList viewList = (ViewList) r.getPage("ViewList"); | ||
+ | viewList.setList(list); | ||
+ | r.activate(viewList); | ||
+ | } | ||
+ | </pre> | ||
+ | Both methods perform a similar task. They retrieve an instance of ViewList, instruct it which list to present, and call upon it to display. The selectList is called form the form, it searches lists for the correct list, while viewList is used in the for loop. Tapestry automatically sets the link field, which is used to instruct ViewList which list to present. Ideally both method should implement some error checking to ensure the chosen lists actually exist. | ||
+ | |||
+ | Again, run the build script, and you should be able to view a list of posts. | ||
+ | |||
+ | |||
+ | ====View Email==== | ||
+ | |||
+ | ====View Post==== | ||
{{ITC382_11255412_A1}} | {{ITC382_11255412_A1}} |
Revision as of 02:20, 26 August 2005
Contents |
Technical Report
Brief installation overview
- Acquire Java JDK, Apache Ant, Eclipse 3.1.x, Tomcat 4.1.30 (Newer versions should work fine), Tapestry 3.0.3, and optionally the Spindle 3.2.0 update site zip (or download directly using eclipse).
Links- JDK 5.0 Update 4
- Apache-ant-1.6.5-bin.* (multi-platform distribution)
- Eclipse 3.1
- Tomcat 4.1.30
- Tapestry 3.0.3
- Spindle 3.2.0 update site zip
or - "http://spindle.sourceforge.net/updates" site update in eclipse "Find and Install" (after eclipse is installed)
- Install Java, Apache Ant, and Tomcat. Use Ant to deploy Tapestry to the tomcat install.
- Execute the Java download file, and follow wizard.
- Extract the ant archive to a permanent location, and add the bin directory to the your path.
- Extract the tomcat archive. Either add JAVA_HOME to your environment variables, or set the variable in the startup and shutdown scripts in the bin directory. JAVA_HOME points to the installation point of the JDK, the directory above the bin directory containing java.exe and javaw.exe.
- Extract the tapestry archive to a temporary location, and follow the instructions in Readme.html under "Configuring Tomcat"
I found the the install failed on downloading Javassist, if you have this problem, try editing the javassist.loc property in config/common.properties, replacing the server telia.dl.sourceforge.net with your own choice of sourceforge mirror, or simply replace the entire link with a selection from http://prdownloads.sourceforge.net/jboss/javassist-2.5.1.zip?download
- Copy tapestry libs into tomcat lib folder
- Copy all files from webapps/workbench/WEB-INF/lib to shared/lib. Alternatively, ensure these files are copied into webapps/project-name/WEB-INF/lib for every tapestry webapp.
- Install Eclipse and Spindle
- Extract the eclipse archive to a permanent location, and run the executable.
- Select Help → Software Updates → Find and Install, choose Select new features to install.
- Proceed with one of the following
- Choose New Remote Site, and enter the name Spindle, and the UpdateSite URL (http://spindle.sourceforge.net/updates)
- Extract the UdateSite Zip, choose New Local Site, and select the location of the extracted files.
- Click Finish
- Explore the tree and select "Spindle 3, and Eclipse Plugin for Tapestry 3.2.0"
- Proceed through the wizard to install spindle
- Restart the workbench when prompted
Sample project
This section will detail the construction of my sample project, how it works, and problems and solutions encountered in its development.
Creating the project
File → New → Project (or first icon on toolbar)
Name the project ("lists")
Continue Next, and Finish (leave all options default).
Set project compiler options, right click on the project, and choose Properties. Select Java Compiler, and select Enable Project Specific Settings. Choose a Compiler Compliance Level of 5.0. (alternatively this can be done through Window → Preferences → Java → Compiler, to set this property for all projects)
Open web.xml, and add the following lines
<filter> <filter-name>redirect</filter-name> <filter-class>org.apache.tapestry.RedirectFilter</filter-class> </filter> <filter-mapping> <filter-name>redirect</filter-name> <url-pattern>/</url-pattern> </filter-mapping>
The default path of a Tapestry app is /app-name/app . If you visit /app-name/ you will recieve an error. These lines will instruct the servlet container (tomcat) to redirect the client to the application.
Open Home.html and place some text between the body tags. Save the file.
Download tomcat-local-deploy.xml and import it in the root directory of the project (File → Import → File System). Open the file in eclipse, and check the properties match your local configuration, then choose Run → External Tools → Run As → Ant Build. This should install the test app into your tomcat installation, which should be visible by point a browser to http://localhost:8080/lists/ .
Download lists-model.zip and import it to the root directory of the project also (File → Import → Arcihve). It contains the java classes of the data model used in this app.
The Scenario
This app is designed to allow a user to browse mailing list archives. My mail server runs Apache James, and it is set to save mailing list emails in a designated directory. For the purposes of this test i am using a sample arvhive. The arcive may be extracted to C: root (C:\), it will create a TEMP directory with the following structure
C:\ TEMP lists lists 4D61696C313131303238393436363630312D30.Repository.FileStreamStore.txt 4D61696C313131303436313636363131392D3932.Repository.FileStreamStore.txt test 4D61696C313131303238393436363630312D30.Repository.FileStreamStore.txt 4D61696C313131303436313636363131392D3932.Repository.FileStreamStore.txt public
This application has no security built into it, apart from the fact you cant access a private group unless you know its name. Public archives are marked by an empty file named public in that archives directory, and are listed by the app for all to see.
Download the archive, and extract it to C:\ . If you do choose another application, be sure you change the path in the java code later on (for this demo the path is hard-coded in the app).
The app will consist of 3 pages, the first allowing the user to select a public list, or enter a private list to view. The second will show all posts to that list, allowing the user to select one to view. The third page will be a view of that email.
Page Layout
First thing to do is to create a page template that can be used by all pages in the app. To do this create a new component in Eclipse (File → New → other → Tapestry → Tapestry Component). Name the component "Page", and leave all options as default. Page.jwc is fine as default. Page.html should contain the following
<html jwcid="@Shell" title="Mail Lists"> <body jwcid="@Body"> <span jwcid="@PageLink" page="Home">Home</span><br /> <span jwcid="@RenderBody">Page content goes here.</span> </body> </html>
Tapestry components are called by the inclusion of a jwcid attribute in a html tag. The original tag is ignored by tapestry, but is included so normal WYSIWYG editors can sucessfully edit the file, and the tag is normally made to be the same as the tapestry component used will generate. Span tags are typicaly used when the coponent will not return a html tag (for eg. if it just returns a line of text). Additional parameters may be sent to the tapestry component simply by adding them as normal parameters in the HTML tag.
Shell and Body construct the HTML and BODY tags, and are not absolutely necessary, as these tags could be entered manually. Shell and body simply save a bit of time.
PageLink creates a link to the specified page, in this instance "Home". So every page using this template will have a link to the main page of the app.
Now open Home.html, and replace any content with the following.
<span jwcid="@Page"> Select a List to view:<br/> </span>
As you can see, this template calls the Page component defined above.
The RenderBody tag in the Page.html takes the content of the calling template (in this case "Select a List to view:<br/>"), and passes it through the tapestry engine to be processed and outputted to the browser.
The ant build script should be able to be run now, and by refreshing the browser you should see a page with a link and a line of text.
Selector Component
Create a new component called "ListSelector", and this time in the New Tapestry Component wizard, choose Create a new Class. The Class name will be entered automatically. Enter a package name similar to "com.yourname.tapestry.list".
Excluding the package specifier, the file should look similar to:
import java.util.ArrayList; import org.apache.tapestry.BaseComponent; import org.apache.tapestry.IRequestCycle; import com.peacocktech.tapestry.lists.model.*; public class ListSelector extends BaseComponent { //name entered from form private String listName; public List list; private Lists lists; public ListSelector() { super(); lists = new Lists(); } //Form Action public void selectList(IRequestCycle r) { } public String getListName() { return listName; } public void setListName(String listName) { this.listName = listName; } //retrive a list of public lists for display public ArrayList getPublicList() { return lists.getPublicLists(); } //link action for public lists public void viewList(IRequestCycle r) { } }
Update ListSelector.html as:
<form jwcid="@Form" listener="ognl:listeners.selectList"> <input jwcid="@TextField" value="ognl:listName" size="12"/> <input type="submit" value="Login"/> </form> <ul> <li jwcid="@Foreach" source="ognl:publicList" value="ognl:list" element="li"><span jwcid="@ActionLink" listener="ognl:listeners.viewList"><span jwcid="@InsertText" value="ognl:list.name"/></span></li> </ul>
Finally update Home.html with an extra line
<span jwcid="@Page"> Select a List to view:<br/> <span jwcid="@ListSelector"/> </span>
The build script may be run again, and the app will show a form and a "list" of lists (currently containing only one item).
The @ListSelector tag instructs the template to load ListSelector.jwc and associated files, and execute them as a template embedded in Home.html. Note that ListSelector.html has no html or body tags, as a component is generally embedded in a page that already has these tags.
ListSelector.html contains a number of new tags.
@Form generates a html form. The listener property instructs taprstry to call selectList in ListSelector.java when the form is submitted. @TextField adds a html form text field, whose value is saved to listName via getter and setter methods (detected automatically by tapestry using reflection). Tapestry automatically assigns a name to the field, and handles transferring data to the class and calling the listener method. A standard submit button is added to the form.
@ForEach loops items in an Iterator, Collection, Object[], or Object. In this case, the source is publicList (the result of a call to getPublicList(), which returns an ArrayList). In each iteration the current value being iterated is stored in list (public field in ListSelector.java), to be accessed by other components. @InsertText reads this value, and echos the result of getName of the object stored in list (an instance of an object in the data model).
View List
Create a new Tapestry Page called ViewList, again, creating a class for it in the same package as previously. Enter the following into ViewList.java
import java.util.ArrayList; import org.apache.tapestry.IRequestCycle; import org.apache.tapestry.html.BasePage; import com.peacocktech.tapestry.lists.model.List; import com.peacocktech.tapestry.lists.model.Post; public class ViewList extends BasePage { private List list; public Post post; public String getListName() { return list.getName(); } public void setList(List list) { this.list= list; } public ArrayList<Post> getPosts() { return list.getPosts(); } public void viewPost(IRequestCycle r) { } }
And the following into ViewList.html
<span jwcid="@Page"> Viewing List: <span jwcid="@InsertText" value="ognl:listName"/><br /> <table border="1"> <tr jwcid="@Foreach" source="ognl:posts" value="ognl:post" element="tr"> <td><span jwcid="@Insert" value="ognl:post.date"/></td> <td><span jwcid="@Insert" value="ognl:post.from" raw="true"/></td> <td><span jwcid="@ActionLink" listener="ognl:listeners.viewPost"><span jwcid="@Insert" value="ognl:post.subject"/></span></td> </tr> </table> </span>
Relationships in this are similar to the last section. @Page calls our first component to set up the html and body tags. listName calls getListName in the java file, posts calls getPosts, while post refers to the post field. post again is an object from the model, containing methods getDate, getFrom and getSubject. listeners.viewPost refers to viewPost from the java code.
To get this page working, we must flesh out the two methods from the previous component, ListSelector.java
public void selectList(IRequestCycle r) { ViewList viewList = (ViewList) r.getPage("ViewList"); viewList.setList(lists.getList(listName)); r.activate(viewList); } public void viewList(IRequestCycle r) { ViewList viewList = (ViewList) r.getPage("ViewList"); viewList.setList(list); r.activate(viewList); }
Both methods perform a similar task. They retrieve an instance of ViewList, instruct it which list to present, and call upon it to display. The selectList is called form the form, it searches lists for the correct list, while viewList is used in the for loop. Tapestry automatically sets the link field, which is used to instruct ViewList which list to present. Ideally both method should implement some error checking to ensure the chosen lists actually exist.
Again, run the build script, and you should be able to view a list of posts.
View Email
View Post
Assignment 1: | Journal | Non-Technical Article | Technical Article | Technical Report | Demo App |