Docstoc

Maverick

Document Sample
Maverick Powered By Docstoc
					Lighter than Struts – Maverick
Cut the fat on all the web presentation frameworks out there and what do you have left
over? Maverick! I originally got into Maverick because as I was researching other web
frameworks for my user group, www.frameworks-boulder.org. What caught my attention
was what I thought a crazy statement by them how Maverick claimed that it is “Lighter
then Struts”. Having a strong Expresso background I had always considered Struts to be
the Duplo blocks of frameworks...that is until I started building the Wafer example with
Maverick. Maverick is a lightweight, simple to use web presentation framework based
on the MVC design principle but offers a few variations of that design as well. It is
agnostic about view technologies and can support JSP (JSTL), Velocity, and XSLT and is
operated by a simple XML file. As a member of the Wafer Project, I built the Wafer
example demo weblog application http://cvs.sourceforge.net/cgi-
bin/viewcvs.cgi/wafer/examples/maverick/weblog/. There you can also find a .war file to
see it in action. This article will cover the code and experience in building that
application, enjoy.



Purpose
This article is for those either getting started on Maverick or need a quick understanding
of how it operates or why one would even use this framework. There are a few
comparisons to other frameworks mainly Struts.

The features
So what makes Maverick unique? Below are some of the key features of the framework
   o Light weight both in API and actual footprint.
   o Supports multiple templating options.
   o Controlled by a simple XML file.
   o Supports Internationalization by use of Shunts.
   o Stable development life cycle.
   o Extensibility and Plug ability
   o Performance




Getting Started
For nearly every framework the heart of it is its controlling mechanism, in Mavericks
case it is the maverick.xml file. This file layout is simple and without a DTD to annoy
you.

<maverick version="2.0" default-view-type="document" default-transform-
type="document">
       <views>
             <view id="loginRequired" path="loginRequired.jsp">
                   <transform path="trimOutside.jsp"/>
             </view>

             <view id="loginFailed" path="loginFailed.jsp">
                   <transform path="trimOutside.jsp"/>
             </view>
       </views>

       <commands>
             <command name="welcome">
                   <view name="success" path="weblog/welcome.jsp">
                         <transform path="weblog/trimOutside.jsp"/>
                   </view>
                   <view name="success" mode="en"
             path="weblog/welcome.jsp">
                         <transform path="weblog/trimOutside.jsp"/>
                   </view>

                    <view name="success" mode="de"
                    path="weblog/welcome_de.jsp">
                          <transform path="weblog/trimOutside.jsp"/>
                    </view>
              </command>

              <command name="weblog">
                    <controller class="org.wafer.ctl.WebLog"/>

                      <view name="loginRequired" ref="loginRequired"/>
                      <view name="loginFailed" ref="loginFailed"/>

                   <view name="success" path="weblog.jsp">
                         <transform path="trimInside.jsp"/>
                   </view>
             </command>
       </commands>

Part of a maverick.xml file.

As you can see from the snip above there are two basic nodes to the XML file,
<commands> and <views>, these aren’t the only ones but the most important.
Commands can have no more then one controller associated with it and that controller
maybe reused in another command if so desired. Each command has a name, controller
class (optional) and 1 to many view definitions. Each view element in the command
node represents a “flow” option for that command, as shown in the weblog command
example above, some views are defined inline (inside the command element like success
and some are defined globally like loginRequired. These are simply name representation
you are free to name them whatever you like.

The <views> as mentioned earlier, are a way to globally define a flow for your site which
is useful if you have common paths that most if not all <command> elements must follow
like how the loginRequired example does above, for Struts users these are similar to
<global forwards>. Those views that are either unique or sparsely used can be defined
inline with the <command>. DION rework: When defining a <view> you have the
option to specify a transform element. The transform element is similar to tiles yet not as
featureful but easier to use. The way it reads is the transform element wraps the view
JSP. By inspecting the trimInside.jsp file you will notice the following JSTL call,

<c:out value="${wrapped}" escapeXml="false"/>

This basically takes the views JSP converts it into a String and places it in the request
attributes with the key of “wrapped”. So in the maverick.xml example above, notice the
command called weblog, looked at the <view> called success, here the weblog.jsp will be
turned into a String and placed inside the trimInside.jsp file where the above JSTL call
for value{$wrapped}” is found. You can have as many transforms as you like but if you
need more then 2 or 3 then you might want to consider using Tiles, or SiteMesh.


Controller

There are 4 types of Controllers you can extend
   o ThrowawayBean2: Easiest of them to use. Uses controller-as-model pattern.
   o FormBeanUser: Similar to the Struts Action. Allows external beans to be
       populated as the model instead of the controller itself.
   o ThrowawayFormBeanUser: Similar to the ThrowawayBean2 but allows
       external beans to be populated.
   o ControllerWithParams: Allows you to pass parameters into the controller via
       the maverick.xml file.

ThrowawayBean2 is the controller I choose in the Wafer project and is also the
Controller used in the friendbook example that comes with Maverick. The
ThrowawayBean2 Controller follows the Controller-as-Model pattern, this means the
Controller acts both as an action class and both as the model. This is achieved by placing
getters and setters in the controller class which after execution places the entire controller
in the request with the key of “model”. With help of Apache BeanUtil package it
automatically populates the setters from the request in the controller. Typically you have
a separate class or set of classes to represent the model, take the example below, there
you will notice the properties that would be associated with a Comment object however
those properties are a part of a the controller ViewComment. In one class you have the
logic to retrieve the comment and store the values onto itself, instead of storing the values
in a object say called Comment. For simple applications this approach makes building
very easy once you get the hang of the Controller-as-Model pattern.

public class ViewComment extends ControllerProtected
{
      protected String subject = "";
      protected String body = "";
      protected Collection comments;
      protected Story story;
       public String getBody() {
             return body;
       }


       public String getSubject() {
             return subject;
       }

       public Collection getComments()
       {
             return this.comments;
       }

       public Story getStory()
       {
             return this.story;
       }

       public String securePerform() throws Exception
       {
             HttpServletRequest request = this.

               // Story id
               String key = (String)request.getParameter("key");
               if(key == null || key.equals(""))
                     addError("gen_error", "Invalid key");

               if(!this.hasErrors())
               {

                  WebLogStory weblogStory =
WebLogStory.getWebLogStories();
                  Story story = weblogStory.getStory(key);
                  this.story = story;
                  this.comments = story.findAllComments();
            }

               if (this.hasErrors())
               {
                     return ERROR;
               }
               else
               {
                     return SUCCESS;
               }
       }

Note: The above class extends ControllerProtected which itself extends a few other
classes (see below) and are very helpful since they provide a lot of fundamental features
used on a website, like error handling and authorization. While not part of the core
Maverick API, they are a part of the friendbook example bundled with Maverick.

ControllerProtected  ControllerAuth  ControllerErrorable  ThrowawayBean2
The above controller, ViewComment, is a presentation state which means the primary
purpose of the controller is to setup the next state/page for the user, in reference to the
Wafer weblog example the user clicked on the link to view the comments for a story
passing along one variable called key which has the storyId in it. The perform method
will load the story and then the comments into the controller, if any errors exist then the
method returns the String of “ERROR”. This is very similar to the Struts way of return
(mapping.findForward("error")). Just make sure that the String you are returning
is either defined as a global view or is defined as an inline view for that <command> in
the maverick.xml file. Behind the scenes, in the ThrowawayBean2 class, ViewComment,
is being placed in the request under the key name of model.

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<b><c:out value="${model.story.subject}"/></b>
<br />
<br />
<c:out value="${model.story.body}"/>
<br />
<br />
<a href="addComment.m?key=<c:out value="${model.story.storyId}"/>">Add
Comment</a>
</br>
<hr/>
<br />

<c:forEach var="comment" items="${model.comments}">
      <b><c:out value="${comment.subject}"/></b>
      <br />
      <br />
      <c:out value="${comment.body}"/><br/>
      <br />
      <br />
      <a href="addComment.m?key=<c:out
value="${model.story.storyId}"/>">Reply</a>
      <br/>
      <br/>
</c:forEach>

Section from viewComments.jsp. Notice how the controller-as-model is
used on the JSP side. Here the variable called model is the
ViewComment.java file hence that controller has getters for comments
and story.

Since we are using the ThrowawayBean2 Controller it uses the controller-as-model
pattern this means that any values you need to display on the JSP page will need to have
getters associated with them as I had done with Story and Comments (see above JSP
snip). Depending on your needs this can be a great strength or weakness, personally for
this example I feel that it worked fine. If this page and controller where associated to a
process state, i.e., submit of a form, then the controller would need to have setter methods
for any input values that you would want to collect and process in the perform method,
see AddCommentSubmit.java as an example.
FormBeanUser is different from ThrowawayBean2 in that this does not follow the
controller-as-model pattern. Here you pass to the controller the class that will be used to
represent the model. Helpful if you want to persist the model in the session or simply
don’t like the clutter of the controller-as-model pattern. Below is the same functionality
of ViewComment except it extends FormBeanUser. This Controller is similar to how
Struts operates.

public class ViewComments2 extends FormBeanUser
{
      public String perform(Object form, ControllerContext cctx) throws
Exception
      {
            HttpServletRequest request = cctx.getRequest();
            MyFormBean2 formBean = (MyFormBean2)form;
            // Story id
            String key = (String)request.getParameter("key");

               if(key == null || key.equals(""))
               {
                     return ERROR;
               }

               WebLogStory weblogStory = WebLogStory.getWebLogStories();
               Story story = weblogStory.getStory(key);
               formBean.setStory(story) ;
               formBean.setComments(story.findAllComments());

               return SUCCESS;
       }

       public Object makeFormBean(ControllerContext cctx)
       {
             HttpServletRequest request = cctx.getRequest();

               MyFormBean2 form = new MyFormBean2();

               return form;
       }


The big difference in the JSP would be to call the form after the
model.

<c:out value="${model.form.story.subject}"/>

MyFormBean2 has the getters and setters for the properties of the page.


ThrowawayFormBeanUser is a hybrid between ThrowawayBean2 and FormBeanUser
in that it is instantiated like the ThrowawayBean2 controller but allows a separate class to
act as the model instead of the controller.
ControllerWithParams is a controller which can have parameters passed to it. For
example you might need to do the following;

<controller class="Login">
      <param name="secure" value="true"/>
</controller>




Internationalization
Maverick has chosen a very different route from the other frameworks to tackle this
problem, they call it shunting. Shunts can be best viewed as switches, switching the view
depending on the locale set in the browser. These switches are referenced as modes.
Below I took the welcome command and added multiple views based on the mode set. If
your browser is set to German then welcome_de.jsp will be displayed to the user.

<command name="welcome">
     <view name="success" mode="en" path="welcome.jsp">
            <transform path="trimOutside.jsp"/>
     </view>

      <view name="success" mode="de" path="welcome_de.jsp">
             <transform path="trimOutside.jsp"/>
      </view>
</command>

You still have the problem of error messages being displayed in a single language and
now you have multiple pages to keep in sync when changes occur to the presentation but
for simple solutions this is very easy. See the JavaDocs for all of the possible modes.
DION: Link to the java docs



Maverick Options

While Maverick as a presentation framework provides all basic needs to build web sites it
also has available from their download page many optional features you can add to
project depending on your needs, here is where the extensibility of Maverick really shines
through! Below is a list of each option.
     Velocity – Provides Velocity support and examples, however not required for
        Velocity.
     FOP – Create PDF files as your views
     Domify – Originally created as part of Maverick but has since been separated out
        into a separate project. In a nutshell, this allows you to turn you model into a
        DOM object and then use XSL to display it to a view.
     Betwixt – alternative to Domify.
      Perl – Run Perl through a Maverick transform type
      Struts – provides tools to help migrate a Struts application to Maverick.

Many of these packages include the friendbook example to help you get a head start on
using it. Given the scope of this article I won’t go into any detail how you can use every
option here but I thought that going over the Velocity and Domify would be the most
used by users out there.


Velocity
Velocity is a Java templating engine used by many frameworks like Turbine, WebWork,
Jpublish, and with a few configuration changes from the default setting can be easily used
on Maverick too. According to the Maverick manual you do not need the velocity-opt
but this is simply not true, download the velocity-opt package and copy the velocity-
tools-view-0.6.jar and velocity-1.3-rc1.jar into your lib directory. Next, modify the
web.xml file by adding the VelocityViewServlet and the .vm mapping definition.

<servlet>
       <servlet-name>velocity</servlet-name>
       <servlet-class>
              org.apache.velocity.tools.view.servlet.VelocityViewServlet
       </servlet-class>

       <load-on-startup>10</load-on-startup>
</servlet>

<servlet-mapping>
       <servlet-name>velocity</servlet-name>
              <url-pattern>*.vm</url-pattern>
</servlet-mapping>

Lastly modify your maverick.xml like the following snip and your ready to roll.

<command name="welcome">
      <view path="welcome.vm">
             <transform path="trimOutside.vm"/>
      </view>
</command>

The opt-velocity download also provides a good friendbook example implement with
Velocity and the TransformFactory for the experimental DVSL technology that is
developed by the Velocity team.
Domify
Domify is a “cheap” way to implement XSLT. Domify started out as part of the
Maverick project but later broke away into its own project,
http://domify.sourceforge.net/. In a nutshell Domfiy allows you to take the Maverick
model object and turn it into a DOM object that can be used on the presentation side via
XSLT. The opt-domify package has the friendbook example done in Domify for further
inspection.

Conclusion

Having worked on many web projects myself and with many web frameworks I will
consider Maverick to be a “keeper” in my toolbox of Java apps. Its features of being easy
to use, easy to extend and quick to build make it my number one choice for simple apps
much like the Wafer weblog application was. Besides Maverick’s key features I was also
very impressed with the quality of the Maverick code itself, this stuff was not created by
any amateurs, which is important if you want to extend it. While the community may not
have been as large as other frameworks it is large enough to get help from the online
community.


Does Maverick mean an end to Struts?
Absolutely not. Struts has many more features and capabilities than Maverick does
however those features might not be of any interest to you. If you want to learn only one
framework then maybe Struts is your solution but remember when holding a hammer not
everything is a nail.


Author
Kris Thompson is the lead of a local java user group, www.frameworks-boulder.org in
Boulder Colorado that focuses solely on web frameworks and is also a contributor on the
Expresso framework and Wafer project. Email Kris at
info@flyingbuttressconsulting.com.

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:7
posted:12/27/2011
language:English
pages:9