apache apachecon app apple asf atom atomprotocol atompub barcamprdu blogapps blogging businessblogging conferences family feeds foss general glassfish google humor ibm java javaone links linux mac microsoft movies music netbeans opensocial opensource photos politics rest roller rome rss socialnetworking socialsite socialsoftware sun triangle trianglebloggers vacation webdev webservices wiki
Roller has changed quite a bit since the Roller article was published on the O'Reilly site. Roller has moved from a two layer architecture with a Presentation Layer and a Business Layer to a three layer architecture with Presentation, Business, and Persistence Layers. This article covers the transition and will bring you up to date with the current Roller persistence architecture.
Then, as now, the Roller Business layer was a small collection of interfaces. The Roller interface was the entry point and provided access to the various Roller manager interfaces. Back then, the Business Layer interfaces were implemented in the org.roller.business package and used the Castor O/R mapping framework APIs directly. The diagram below illustrates this point. The org.roller.business package implements the Business Layer intefaces defined in org.roller.model and depends on org.exolab.castor.
Earlier this year, during Roller 0.9.7 development, we decided to create an implementation of the Roller Business Layer using the Hibernate O/R framework. We moved the Castor implementation into the org.roller.business.castor package and added the new Hibernate implementation in org.roller.business.hibernate. In the process we noticed a lot of code duplication and we tried to move common code back up into org.roller.business, but we had limited success. The diagram below illustrates this situation: separate Castor and Hibernate implementations of the Roller Business Layer with some shared code.
Since Roller 0.9.7, the Roller Business Layer implementation has been evolving and moving towards that three layer architecture mentioned at the start of this article. We introduced a
PersistenceStrategy interface and a persistence package in
org.roller.persistence. Over time we have slowly moved almost all Castor and Hibernate specific code behind the PersistenceStrategy interface. I say almost because, there are a couple of cases where the Persistence Layer abstraction is not powerful enough to handle the queries needed by the Business Layer. Specifically, the RefererManager.getHits() and RefererManager.getDaysPopularWebsites() methods need to drop down to raw SQL because, apparently, neither Castor nor Hibernate can handle the queries we need to do.
The diagram below illustrates the current situation. The Business Layer calls upon the Persistence Layer for object storage, retrieval, and queries. The org.roller.business.castor and org.roller.business.hibernate packages are shown in grey because they still exist but are on the way out.
Thus far, we've been looking at things at the package level. Let's zoom in on the
org.roller.persistence package and take a close look at the key interfaces in that package:
PersistenceStrategy,
QueryFactory, and
Query.
PersistenceStrategy supports storage, retrieval, and removal of objects. To execute a query, you create a Query object using the QueryFactory, create a where clause by adding Conditions together, set a limit if desired, set an order-by if desired, and call the Query.execute() method. At that point, the Query implementation will generate an HQL query for Hibernate or an OQL query string for Castor and will call the appropriate method to execute the query. Below is some example code to illustrate typical usage of the Query API.
public List getTodaysReferers(WebsiteData website) throws RollerException {
if (website==null ) throw new RollerException("Website is null");
QueryFactory factory = mStrategy.getQueryFactory();
Query query = factory.createQuery(RefererData.class.getName());
Condition specifiedUser = factory.createCondition(
"website", Query.EQ, website);
Condition hasDayHits = factory.createCondition(
"dayHits", Query.GT, new Integer(0));
Condition userEnabled = factory.createCondition(
"website.user.userEnabled", Query.EQ, new Boolean(true));
List conditions = new LinkedList();
conditions.add(specifiedUser);
conditions.add(hasDayHits);
conditions.add(userEnabled);
query.setWhere(factory.createCondition(Query.AND, conditions));
query.setOrderBy(Query.DESC, "dayHits");
return query.execute();
}
The PersistenceStrategy interface is a fairly simple abstraction, sort of a least common denominator approach, but it is expressive enough to handle all of the requirements of Roller. This approach allows the Roller Business Layer to be completely independent of the underlying persistence mechanism. This is really nothing new. PersistenceStrategy is essentially a generic Data Access Object (DAO). I use the word "generic" because most DAOs I've seen are specific to one type of object, a CustomerDAO or EmployeeDAO for example, but PersistenceStrategy handles any persistent object in the system. I'm interested to see how this approach holds up. Will we eventually find the simple API to be too limiting? Will it be possible to implement PersistentStrategy with other persistence technologies such as JDO?
As part of Roller 0.9.9's new boomkark management features, I have also added the ability to export the bookmark folder hierarchy as OPML. I implemented this by changing Roller's RSSServlet into a FlavorServlet that serves "flavors" defined by Velocity templates found in the classpath at under /flavors and by adding a new flavor called opml.vm.
For example, the following URL will retrieve all of my folders in OPML format:
The following URL will retrieve only the contents of the my "/Subscriptions/Blogs - blogroll" folder:
And finally, the following URL will return my RSS2 feed:
Note that the FlavorServlet defaults to RSS and is mapped to /rss as well as /flavor so all existing Roller RSS URLs will continue to work.
/rss/roller <-- still worksThere is also a new macro #showOpmlLink that renders an OPML icon which links to the bookmark folder of your choice. For example, near the bottom of my Bookmarks page there are OPML links, one for my bookmarks and one for my subsriptions. These OPML links are displayed by the following template code:
<p>You can download my entire bookmark collection in OPML format
using the links below:</p>
#showOpmlLink("/Bookmarks")Bookmarks (shown above)<br />
#showOpmlLink("/Subscriptions")RSS Subscriptions (not shown)
Over the past month or so, I've been re-working Roller's bookmark management features. As part of this work I added a new Query API so that we no longer have to hard-code Castor or Hibernate query language statements into the Roller Business Layer, I modified BookmarkManager to handle folder hierarchies of arbitrary depth, and I modified the bookmark POJOs to use Castor and Hibernate's lazy-loading facilities. I also rewrote the bookmark management JSP pages and used the JSTL <fmt:message> tag to externalize all strings on the page (for I18N).
Below is the new bookmark manager interface. It works fine now, but it still needs a little fit and finish.

The new bookmark management features will be included in Roller 0.9.9. If you want a preview, check out the new Bookmark Management docs I'm working on.
Now that I've got the hierarchy thing down, I'm turning my attention to the WeblogManager where I will add support for multiple categories per weblog entry and for hierarchical categories.Get a turkey. Get it out of the wrapper. Then get some spicy sauce. Then you get some peas and put them around the turkey on a plate. Take the turkey and put it on a pan and put it in the oven (a big fat one) at 4000 degrees. Cook the turkey for 5-7 minutes then take it out of the oven. Put it back on the plate that has the peas on it. Eat.
Charles Miller: Despite what the name suggests, a stand-up meeting can be held sitting down.
Lenny and the Squigtones: Come on everybody, sit down and dance!I love the idea of stand-up meetings, because I like short meetings. If your team's legs are aching because of stand-up meetings, then your team needs to work some more exercise time into the schedule.
"architecture is the set of significant decisions about the organization of a software system." Here are some of the more significant decisions that have been made in the development of Roller. Some are questionable, some are bad and have been reversed, and some, as longtime followers of Roller internals will note, are new.
Presentation Layer
Business Layer
Persistence Layer
pattern will be used to ensure maximum of one persistence session per request.
).
I think this is a very interesting topic and I've been exploring it further. Here is my current reading list.
Papers and talks on continuations and web programming:
A couple of weblog posting on the topic:
Java web application frameworks that support continuations:
Often in web applications, a user will be filling in an HTML form on one page and will realize the need to go to a second or even a third page to enter information needed by the first page.
For example, you are writing a weblog entry by typing text into an HTML form on the Edit Weblog Entry page. You type in about half of your entry and then you realize that you need to create a new category for your post. You click the Add Weblog Category button, arrive at the Add Weblog Category page, create your new Category, and click OK. At this point, you are returned to the Edit Weblog Entry page to find that your half-edited weblog entry is still there. You are ready to continue right where you left off.
How do you achieve this type of behavior in your web application? How do you allow users to continue working where they left off? Do you treat each case as a special case or do you have a general solution like a breadcrumb stack or a web continuation to this problem? It can get pretty messy. Do you cache half-completed forms in your HTTP session or in your database? Or, do you avoid the whole issue by carefully designing around it.
I didn't get a good response on the Weblogic forums for this question, so now, dear reader, I bothering you.
If you deploy a simple Servlet/JSP application with an error page on Weblogic 8.1 and your application throws an error, the Servlet Container will save and then restore the contents of your ServletContext. So, if you have any non-serializable ServletContext attributes, you will lose them. (Strange thing is, and this part is definitely a bug, if you deploy the very same application, but without an error page specified in web.xml, then the save and restore will not occur and all of your ServletContext attributes will be preserved.)
This doesn't seem quite right. I realize that the best practice is to only store serializable attributes in your context and in your session, but it is not a requirement of the Servlet specification. If it was a requirement, then setAttribute would take a Serializable rather than just a plain old Object.
Seems to me, non-serializable attributes should only break your application if you try to run in distributed mode. Also, the behavior of ServletContext attributes should be the same regardless of the presence or absence of an error page.
Is this save-and-restore-on-error behavior a bug in Weblogic?
Must context attributes be serializable?
Is there a way to turn off the save-and-restore-on-error behavior on Weblogic?
Mike Levin This month we'll learn about Roller, the open-source weblog. Written entirely in Java, Roller uses many design patterns and java components and has a fascinating architecture. Pizza and refreshments will be served. ...Welcome to the Gator JUG in sunny Gainesville, Florida.I've been working on my own Roller presentation, now Mike has beat me to the punch.
James Robertson: How hard was it in the past to get ahold of the product manager for something at an outfit as big as MS? Now look at it - straightforward access, including contact information. That's huge. It used to be that you had to go to a trade show (and swim through huge crowds) or be an important customer and get ad hoc access. Now anyone with a browser or news aggregator can get far more details.
Joe Gregorio on Longhorn: That basically covers it. Three major components, all useless in their own right, now stacked together on a shaky foundation to make an even more useless heap.
Joe Gregorio makes lots of valid points in response to Marc Cantor's gushing fanboy Longhorn post, but I'm not sure Joe has all of his facts straight. Is Dot-Net really built on top of COM? I thought Dot-Net was a whole new component model and required bridging technology to hook it up to COM. Is user-supplied meta-data the whole idea of WinFS? I thought the whole idea was to suck SQLServer into the operating system so that DBMS vendors Oracle and IBM can be microsofted as Netscape, Stac, and others were. Is it be true that Microsoft has never shipped a pure Dot-Net application? I hope this one is true, is it?
NY Times : Cornell University physicists reported they had used a laser beam to pluck the strings of a tiny silicon guitar just 10 millionths of a meter long.
Is that really necessary? Bunch of showoffs!
365gay.com: If Charles succeeds to the throne, and the allegations are proved true, it would make him the first known bisexual monarch since William III. The only openly gay British monarch was Edward II, who was put to death in 1327 by having a red hot poker brutally shoved into his anus by rebellious barons.
Is that really necessary? Take it easy on poor Charles.
This work is licensed under a Creative Commons License.
Copyright 2002-2007, David M Johnson (dave.johnson at rollerweblogger.org)
This is a personal weblog, I do not speak for my employer.

Buy now from Amazon.com
Or direct from Manning
| « November 2003 » | ||||||
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|---|---|---|---|---|---|
1 | ||||||
2 | 4 | 5 | 6 | |||
10 | 14 | 15 | ||||
21 | ||||||
23 | 24 | 25 | 28 | 29 | ||
| Today | ||||||
Allen Gilliland
Anil Gangolli
Dan Axon
Danese Cooper
Film Babble Blog
Geertjan's Weblog
Henri Yandell
James Robertson
Jim Grisanzio
Josh Staiger
Linda Skrocki
Pat Chanezon
Rama
Ruby Sinreich
Simon Phipps
Tim Bray
Will Snow
Janne Jalkanen
Joe Gregorio
Matt Raible
Mike Cannon Brookes
Rafe Colburn
Sam Ruby
Simon Brown
My other sites