Here is an approach I've been using for a long while. I'll describe a concept with the use of entities that could be used with a forum application, but it really is more of a
pattern than a forum specific thing.
Let's say we define an interface PostProvider with a method getPost() that returns Post.
Then we create a tag without a body called PostDisplayer that needs a required parameter field, and some optional parameters.
This tag doesn't care where the Post data actually comes from. All it needs is a parent tag that implemets PostProvider.
Then we create a tag like PostListForTopicRetriever that implements PostProvider interface. The job of the tag is to get the data from wherever based on, say, a topic_id request parameter. This tag doesn't care what happens with that data later on. It just iterates and provides a Post to the child tags.
Then we create an interface UserProvider and a tag UserDisplayer and a tag UserForPostRetriever.
UserForPostRetriever needs a parent tag that implements PostProvider and itself implements UserProvider. So it doesn't care where the Post came from and it doesn't care what the User is used for by its children. It just gets the User coresponding to the provided Post.
Those should be self-explanatory.
And then we have a template with something like:
<mylib:PostListForTopicRetriever>
html...here...
<mylib:UserForPostRetriever><mylib:UserDisplayer field="username"/></mylib:UserForPostRetriever>
html...here...
<mylib:PostDisplayer field="subject"/>
html...here...
<mylib:PostDisplayer field="contents"/>
html...here...
</mylib:PostListForTopicRetriever>
That would list the posts for a topic with the user names.
If you don't want the tags to access the model, the view itself would have a tag like PostListFromRequestRetriever instead of PostListForTopicRetriever.
It would basically look up an attribute of the request with a pre-defined name that would hold a list. Basically similar to what the put's do now for the template engine. That would help with access control.
And if we want to make a link to the user's profile instead of just a name, we would have something like:
<mylib:UserForPostRetriever>
<a href="/userpage?usernum=<mylib:UserDisplayer field="usernum"/>">
<mylib:UserDisplayer field="username"/>
</mylib:UserForPostRetriever>
Then if you want a page with a user list, we would create a tag UserListRetriever that would provide the data for the UserDisplayer.
UserDisplayer doesn't care where the data comes from, just like any other displayer.
And then we would have PostListForUserRetriever that needs a UserProvider parent and itself implements PostProvider for the children.
And then all the other required tags, and keep adding them as we go.
For example, UserFromSessionRetriever would be able to get the User after an established login. The login controller would set an attribute.
UserInSessionMarker would iterate depeding if the user is logged in or not.
For example,
<mylib:UserInSessionMarker marker="true">
Profile link
</mylib:UserInSessionMarker>
<mylib:UserInSessionMarker marker="false">
Login link
</mylib:UserInSessionMarker>
That would display either a profile link or a login link depending on the state.
And AnonymousUserMarker would be used where the if id==1 is used now.
The tag itself wouldn't need to know where the User comes from, just provided by the parent. So that we could also use it under UserForPostRetriever or any other UserProvider for that matter.
Once you build up the code base, the development really speeds up. That way, you get all the flexibility you want without having the designers know anything other than a list of tags they can use to design templates.
And the templates themselves are JSP, so if you need something added that is not in the forum app codebase, you can just do it without having to modify that code, only the template.
[originally posted on jforum.net by bcc]