A Blog Application with Wideplay's Warp Framework(1)
A Blog Application with Wideplay's Warp Framework
First check out the Hello World example to get yourself going. In this article, I'll show you how to knock together a simple Blog application where you can browse and read blog entries. You will learn the following Warp concepts:
- Page Injection
- RESTful behavior and the HyperLink component
- The Table and Column components
- Simple Internationalization (i18n)
First let's create ourselves a data model object representing a blog. This will be a simple POJO with 2 fields: subject and text.
public class Blog {
private String subject;
private String text;
//don't forget your getters/setters here...
}
OK, now we make a list page where you can see a list of all
the blogs currently in the system. For simplicity, we will store blogs
in a HashMap. The Page object class for this list should look something
like this:
@URIMapping("/blogs")
public class ListBlogs {
private final Map<String, Blog> blogs = new HashMap<String, Blog>();
public ListBlogs() {
//setup a blog as dummy data
blog = new Blog("MyBlog", "Warp is so great...");
blogs.put(blog.getSubject(), blog);
}
public Collection<Blog> getBlogList() {
return blogs.values();
}
}
Note the @URIMapping annotation which tells warp to map this page object to the URI "/blogs". The getter for property blogList, simply returns a list of all the values contained in our HashMap of blogs. For the interesting part, let's make a template to layout our blogs:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<title>Warp :: Blogs</title>
</head>
<body w:component="frame">
<h1>A list of blog entries</h1>
<table w:component="table" w:items="${blogList}"/>
</body>
</html>
This is a very simple template. Inside our body we have only one real component (Table) and we pass it our list of blogs in the w:items property that we declared above. Go ahead and run the app now and point your browser to: http://localhost:8080/blogs, you should see a table with 2 columns (subject and text) corresponding to the Blog data model object we declared above. Table is smart enough to inspect the items given it and construct an appropriate set of display columns. The rows of the table reflect the data in each instance of the Blog object in our HashMap. Nice!
OK, having the
property names as the title of each column is not ideal--let's
customize this. Customizing is as simple as adding a properties file in
the same package as our Blog class, with the same name:
Blog.properties:
subject=Subject of Blog
text=Content
Now, run the app again and you should see the column names changed. In this way, you can also achieve internationalization (i18n). If you want to hide a property (i.e. not render a column for it), specify an empty key (so to hide subject, you would have just "subject=").
OK, let's create a view blog page now. This page will display one blog entry. Let's start with the view portion (called ViewBlog.html):
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head w:component="meta">
<title>Reading :: ${blog.subject}</title>
</head>
<body w:component="frame">
<h1>Read...</h1>
<h3>${blog.subject}</h3>
${blog.text}
<a href="../home">back to list</a>
</body>
And its Page object:
@URIMapping("/blog")
public class ViewBlog {
private Blog blog;
//getters/setters...
}
Ok, this is fairly simple, but how does it know what blog to display? Let us use a RESTful idiom to achieve this. First, change your ViewBlog page object so that it takes a parameter indicating what blog to show:
@URIMapping("/blog/{subject}")
public class ViewBlog {
private Blog blog;
@OnEvent @PreRender
public void init(String subject) { .. }
}
Ok, this tells warp that when the URL http://localhost:8080/blog/myblog is requested, to inject anything matching the {subject} portion of the @URIMapping (in this case "myblog") to the @PreRender event handler method. Hold on, we're not done yet--we still need to obtain the appropriate blog from our HashMap which is stored in the ListBlogs page. This is done via page-injection:
@URIMapping("/blog/{subject}")
public class ViewBlog {
private Blog blog;
@Inject @Page private ListBlogs listBlogs;
@OnEvent @PreRender
public void init(String subject) {
this.blog = listBlogs.getBlog(subject);
}
}
Finally, we need to modify ListBlogs and give it a getBlog() method to fetch a Blog by subject:
@URIMapping("/blogs")
public class ListBlogs {
private Map<String, Blog> blogs = new HashMap<String, Blog>();
public ListBlogs() { .. }
public Collection<Blog> getBlogList() {
return blogs.values();
}
public Blog getBlog(String subject) {
return blogs.get(subject);
}
}
Ok,
now let's wire the pages together so clicking on a blog in the list
will take us to the view page for that blog. I want to make the subject
of the blog clickable, so let's use the Column component to override
the default behavior of table (which just prints out the subject as
text):
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head w:component="meta">
<title>Warp :: Blogs</title>
</head>
<body w:component="frame">
<h1>A list of blog entries</h1>
<table w:component="table" w:items="${blogList}" class="mytableCss">
<td w:component="column" w:property="subject">
<a w:component="hyperlink" w:target="/blog"
w:topic="${subject}">${subject}</a>
</td>
</table>
</body>
</html>
Notice that we nest the hyperlink component inside the column override. This tells the Table component not to draw the column, instead to use our overridden layout instead. The attribute w:target simply tells the hyperlink the URI that we're linking (in this case /blog, which is the ViewBlog's mapping) and w:topic tells hyperlink to append the subject of the blog to the URI. So for a blog entitled "MyBlog," Warp will generate a URI as follows: /blog/MyBlog. And "MyBlog" gets stripped out and injected into the ViewBlog page's @PreRender handler so it can set it up.
Also notice the addition of a non-Warp attribute class to the <table> tag, which refers to the CSS class I want to style my table with. This is a useful tool for both for previewability as well as the end result HTML--generally whatever HTML attributes you write on a component will be passed through the final rendered page.
Done!posted on 2009-02-17 16:29 草原上的駱駝 閱讀(269) 評論(0) 編輯 收藏 所屬分類: JAVA框架