webwork/src/docs/manual quickstart.html,NONE,1.1 index.html,1.14,1.15

[email protected] Mon, 10 Nov 2003 21:38:32 -0800
Newsgroups gmane.comp.java.open-symphony.cvs
Message-ID <[email protected]>
Update of /cvsroot/opensymphony/webwork/src/docs/manual
In directory sc8-pr-cvs1:/tmp/cvs-serv10933/src/docs/manual

Modified Files:
	index.html 
Added Files:
	quickstart.html 
Log Message:
Added quickstart guide from joe o.


--- NEW FILE: quickstart.html ---
<html>
<head>
  <title>QuickStart Guide</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <link rel="stylesheet" href="main.css" type="text/css">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h2>Introduction</h2>
<p><a href="http://www.opensymphony.com/webwork/">WebWork</a> is a service
invocation framework. It's built around the concept of actions and views.

<p>WebWork is web-agnostic (despite the name), although it's been more or
less geared for web applications. As such, we'll use the paradigms of the
web to show some simple concepts about it.

<p>WebWork uses a dispatcher to look up entry points, which resolve to
Actions. Actions return simple results, which are free-form in nature, and
those results map to either another action or a view. A dispatcher is the central
entry point to webwork.

<h2>Views</h2>

<p>A view in webwork is responsible for generating output. It's also an endpoint.
Views in WebWork can be done with anything: Swing, SWT, JSP, Velocity, XML/XSL,
Jasper are all good examples.

<p>A view gets its specific request data via a concept called the
"ValueStack" which will be explained later.

<h2>Actions</h2>

<p>An action in WebWork is a unit of code (usually, but not restricted to, a java class
 that has a definite entry point (which, oddly enough, is variable depending on the
 nature of the action itself). At its simplest, an Action uses a method called
 "execute()" to begin its processing.

<p>Actions have a specific lifecycle in WebWork. The dispatcher takes the
request itself, and in the simplest case, maps it to a specific Action. The
Action is instantiated, and request parameters are reflectively set in the
Action; then, after all possible matches have been made, the
<code>execute()</code> method is called. The <code>execute()</code> method
returns a <code>java.lang.String</code>, which is mapped to the "next step,"
which can be another Action, or a View.

<h3>The ValueStack</h3>

<p>The ValueStack is actually a set of Actions. As an Action is created,
it's put in an internal list for the request, and each action is accessible
via this list - so an Action that's third in a list of five has access to
the data created at steps one and two, in addition to having access to the
request data itself. The value stack can be interrogated via a rich expression
language, so it is possible to query any particular action and its properties.

<h2>How Views Get Data</h2>

<p>The ValueStack is also how actions provide data to views: a view takes a
request for data, and looks for it on the entire value stack, returning the
first (most recent) match for the data.

<h2>A Simple Example</h2>

<p>Here's a very simple example of a guestbook done in WebWork, to
illustrate how some of this works. We have a few use cases to work with:

<ul>
<li>Show Markers - This use case simply shows what names have "signed"
the application, by name and age.</li>

<li>Mark - This takes the name, age, and state of residence of a guest. If
the user is under a certain age, no information is preserved; if they're
under a different threshold, state of residence is ignored.</li>
</ul>

<p>We're purposefully leaving some aspects unimplemented (for example, "show
first visitor for all states") for the sake of simplicity.

<p>Our first flow is very simple, "Show Markers." For this, we have a simple
path: one action, one view. The Action is <code>ShowMarkersAction</code> (an
arbitrary name), and the view, in Velocity, is <code>showmarkers.vm</code>.

<p><code>ShowMarkersAction</code> takes no input, so it has no mutators -
only an accessor, <code>public java.util.List getMarkers()</code>. The
<code>execute()</code> method creates the list and populates it, and returns
<code>SUCCESS</code>, which is one of the four predefined return types. (As
stated earlier, return values are freeform - the four predefined values are
for convenience only.)

<p>The success response value maps to showmarkers.vm, which iterates over
$markers and shows the names in order. The configuration for this, using the
property file configuration format, would look like this:

<pre>show.action=ShowMarkersAction
show.success=showmarkers.vm</pre>

<p>The next flow is a little more complex. First, the configuration entries:

<pre>mark.action=IsAPreteenAction
mark.ageok=savename.action
mark.agenotok=underage.vm

savename.action=SaveNameAction
savename.success=isunder18.action

isunder18.action=IsAMinorAction
isunder18.ageok=savestate.action
isunder18.agenotok=show.action

savestate.action=SaveStateAction
savestate.success=show.action</pre>

<p>What's going on here? It's pretty simple: the first thing we do is hit a
"routing" action, that returns "ageok" or "agenotok" depending on the age of
the person. If the response is "agenotok" then it politely informs the user
that they were underage for the purposes of tracking information.

<p>If the age checked out (i.e., over 16), then it routes to
<code>savename.action</code> - which ends up being
<code>SaveNameAction</code>. <code>SaveNameAction</code> stores the name and
age of the user, and then returns an indicator of success, which does the
same sort of thing with a different age.

<p>The code for <code>IsAPreteenAction.java</code>:

<pre>package com.enigmastation.webwork.example;

public class IsAPreteenAction extends webwork.ActionSupport {
  int age;

  public void setAge(int newage) { age=newage; }

  public int getAge() { return age; }

  public String execute() throws Exception {
    if(getAge() &gt; 12) {
       return "ageok";
    } else {
       return "agenotok";
    }
  }
}</pre>

<p>That's it. The lifecycle first creates an instance, calls
<code>setAge(int)</code> (assuming, of course, an age was put in, which for
the purpose of simplicity we'll assume has been done), then calls
<code>execute()</code>, and chooses the next step based on the response of
this method.


<h2>Benefits of WebWork</h2>

<p>The power of WebWork manifests itself in the separation of your action
from your views. In this case, you could use the
<code>IsAPreteenAction</code> as a standalone router, to echo a
preteen-friendly version of a page or a teenager-aimed version of a page;
its use of a router in this case is simply an arbitrary choice on my part.
There'd be nothing preventing this kind of flow, requiring no changes on the
part of the action:

<pre>agedhello.action=IsAPreteenAction
agedhello.agenotok=mickeymousehello.vm
agedhello.ageok=rock-and-roll.vm</pre>

<p>This separation, enforced by the API itself, means that components tend
to fall naturally out of the system based on use cases - a great boon for
organizational and architectural strength, as a failure point is naturally
isolated and can be dealt with as needed. The view neutrality means that the
optimal solution for views - be it JSP, Velocity, RTF documents, etc - can
be chosen at will.

<h2>Writing Views</h2>

<p>Views aren't webwork-tailored. As mentioned before, you can use Velocity,
JSP, FreeMarker, or any number of other technologies to render results. To
do so, the dispatcher creates an environment from which the view can
retrieve data, and then executes the view. For JSP, the environment is left
alone (since there are WebWork tag libraries to pull out the data from the
ValueStack), and in Velocity, the ValueStack is propagated to the context as
well.

<p>Here's an example of a "Hello, World" application using WebWork, from
start to finish. First, our use cases:

<ul>
<li>Input view - invoked when no input is provided or invalid input is
provided.
<li>Hello, using JSP - invoked when input is provided and the JSP output
form is selected.
<li>Hello, using Velocity - invoked when input is provided and the Velocity
output form is selected.
</ul>

<p>Our configuration would look like this:

<pre>
hello.action=HelloAction
hello.input=hello.html
hello.jsp=hello.jsp
hello.vm=hello.vm
</pre>

<p><code>HelloAction</code> would look like this:

<pre>package com.enigmastation.webwork.example;

public class HelloAction imports webwork.ActionSupport {
  protected String view=null;
  protected String name=null;

  public String getView() { return view; }
  public void setView(String view) { this.view=view; }

  public String getName() { return name; }
  public void setName(String name) { this.name=name; }

  public void execute() throws Exception {
    String retval=INPUT;

    if(!(getName()==null || "".equals(getName().trim()))) {
      if("jsp".equalsIgnoreCase(view)) {
         retval="jsp";
      } else {
         retval="vm";
      }
    }

    return retval;
  }
}</pre>

<p>A quick explanation: if the name isn't null, return "jsp" or "vm"
depending on the view selection; otherwise, return the INPUT mapping.

<p>Here's the input form itself, which is plain (<em>very</em> plain) HTML:

<pre>
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Hello, World!&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;form action="hello.action"&gt;
      What's your name?
      &lt;input type="text" name="name"&gt;&lt;br&gt;
      What view would you like?
      &lt;select name="view"&gt;
        &lt;option&gt;jsp
        &lt;option&gt;vm
      &lt;/select&gt;&lt;br&gt;
      &lt;input type="submit"&gt;
    &lt;/form&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>

<h3>The Velocity view</h3>

<p>The Velocity view is trivial to write, so here it is:

<pre>
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Hello, $name!&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;Hi there, $name! Nice to meet you.
  &lt;/body&gt;
&lt;/html&gt;
</pre>

<p>As you can see, the values are pulled from the ValueStack by using normal
Velocity references, thus <code>$name</code> looks in the action for an
attribute called "name" and uses that value.

<h3>The JSP View</h3>

<p>In JSP, it's not that much different, except for the use of tag
libraries to pull data from the ValueStack, which have their own oddities
regarding namespacing:

<pre>
&lt;@ taglib uri="webwork" prefix="ww" %&gt;&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Hello, &lt;ww:property name="'name'" /&gt;!&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;Hi there, &lt;ww:property name="'name'" /&gt;! Nice to meet you.
  &lt;/body&gt;
&lt;/html&gt;
</pre>

<p>You'll notice that the "name" property has double-quotes <em>and</em>
single quotes; this is because the JSP tag libraries introspect values. If
'name' was left unquoted, it would be taken not as a literal name, but as
the name of a property, and the tag library would look up the name of the
property from that value. This may seem like a lot of extra obfuscation, but
it's actually extremely useful for internationalization, where you might
pull a bit of text from a property name, rather than a property value, as
we're doing here.
<p>Hopefully this brief guide has illustrated the main features of webwork.
Once you go through these examples and start feeling more confident in
using this framework, we encourage you to read through the rest of the manual
as well as the webwork cookbook in order to ensure you get the most out of
what is available. Enjoy and happy webworking!
</body>
</html>

Index: index.html
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/docs/manual/index.html,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- index.html	3 Nov 2003 16:58:39 -0000	1.14
+++ index.html	11 Nov 2003 05:38:30 -0000	1.15
@@ -17,6 +17,7 @@
 
 <p><b>Table Of Contents:</b></p>
 <ul>
+  <li><a href="quickstart.html"><b>QuickStart Guide</b></a></li>
   <li><b>Fundamentals</b>
    <ul>
       <li><a href="fundamentals-intro.html">Introduction</a></li>




-------------------------------------------------------
This SF.Net email sponsored by: ApacheCon 2003,
16-19 November in Las Vegas. Learn firsthand the latest
developments in Apache, PHP, Perl, XML, Java, MySQL,
WebDAV, and more! http://www.apachecon.com/