Chapter 16. Developing The View in the MVC

Table of Contents

Introduction
Order of execution to a request.
How to get at your data.
Understanding JavaBean properties naming conventions
Rendering ControllerResponse With JSP
Which tag library is better: Struts or JSTL?
A Common Controller
Processing With Struts Tags
Processing with Struts Extended Tags
Processing with JSTL
Processing with JSTL Extended Tags
Rendering the ControllerResponse with XSLT
Rendering ControllerResponse With Velocity
Configuring Velocity in Expresso
Velocity Global Macros for Expresso Integration
Using Velocity within Expresso
How to shorten URLs in links
Universal Dispatch
Conclusion
Contributors

Note

If you find this EDG documentation helpful please consider DONATING! to keep the doc alive and current.

 Maintainer:Mike Traum

Introduction

Expresso relies heavily on the Struts MVC framework for its MVC architecture. As such it has quite a bit of view independence. Although we will be primarily focusing on JSP development, the first part of this chapter would apply to other developers who wish to use development systems such as FreeMarker or Velocity. For a specific chapter on how Struts integrates with Velocity, the book "Struts In Action" by Ted Husted et al. is recommended.

Order of execution to a request.

This is an important aspect to understand how your system gets to the jsp page. This is the order of execution when a web browser makes a request to the application server:

  • Web Browser Request The web browser fetches a URL. Lets say for the sake of this example, the url is: http://localhost:8080/Example.do

  • Servlet Engine Routing The application server looks at the request URL and sees that any request URL ending in .do should be sent to the ExpressoActionServlet (which is slightly modified from the Struts ActionServlet but for all purposes of this discussion, the two are equal). So the request is sent to the ActionServlet.

  • Servet Filters Servlet filters are executed, including Chapter 13, The Request Registry.

  • ActionServlet Routing Now the ActionServlet takes a look in its own configuration files and looks for any matches to /Example.do. If it fails to find one, it will return an error to the web browser about unable to locate resource. Once it finds the match that is specified in the struts-config.xml file, the ActionServlet will load the classname specified in the config file and pass that on to the particular class. For the purposes of this discussion, we'll assume that the class is derived from com.jcorporate.expresso.core.controller.DBController or com.jcorporate.expresso.core.controller.Controller

  • Controller State Handler Routing By the time you've hit this paragraph you probably get the idea that in any http request to an application server, there is a lot of 'hand offs' that go on. You're right, and we have more to go! The Expresso Controller examines the http parameter called 'state' and uses the information it gleans from there to invoke via java reflection either the actual function within the controller or the class derived from com.jcorporate.expresso.core.controller.State

  • Controller State Handler Work Finally! We've come to the step were some work is done! This is where you generate your Inputs,Outputs,Transitions and Blocks and add them to your ControllerRequest. This particular step was discussed in the chapter on Controllers.

  • Controller Saves Response Now that you're done, the Controller base class saves the entire controller response onto the Servlet Request Context under the name "controllerResponse". This part is important because this is the name of the 'javabean' you're going to be accessing while building your actual html page.

  • Action Servlet Forwards To The Renderer Action servlet sees that the Controller has successfully executed and it now looks in its configuration again to see where to hand off control. Let's say for the sake of discussion, your have the forward set to "/expresso/components/example/mySample.jsp" In this case, it will hand off control to the jsp to finish the job. Remember that a JSP is actually a special form of a java servlet, and is thus a running 'program' so to speak. Now again, it must be emphasized that the forward does not necessarily have to be sent to a jsp. For example, it can be sent to a servlet for special post-processing or rendering, or forward to a Velocity template for straight rendering as an html page.

How to get at your data.

In a typical Expresso data rendering situation, most of your data will be stored in the ControllerResponse object. As mentioned before, the ControllerResponse object basically contains ControllerElements and Error Collections. Below is a UML diagram highlighting the relationship with various ControllerElements and ControllerResponse. It also highlights some of the most common access methods used in view programming.

The basic principle behind getting at the controller elements you generated is the fact that the Controller class saves the controllerRequest object in the request context under the name controllerRequest. Whether you use Velocity, JSP, or raw servlets, you will need to access the ControllerResponse object by looking in the request scope and getting the object by that name. The actual implementation of how you do this, for obvious reasons varies drastically. Further on we'll talk about just how to do that in a JSP environment using two different tag libraries.

Understanding JavaBean properties naming conventions

Before we get into the actual taglibs, a quick note should be made for those of you that have never dealt much with JavaBean terminology. Consider the following code:

public class myBean {

	//Standard Read only property named 'var1'
	private int var1 =233;
	
	//Standard Read/Write property named 'var2'
	private String var2 = "Hello World!";
	
	//Mapped Property named 'values'
	private Map values = new HashMap();
	
	/**
	 *Default Constructor
	 */
	public myBean() {
	}
	
	/**
	 * Getter property for var1
	 */ 
	public int getVar1() {
		return var1;
	}
	
	/**
	 * Getter property for var2
	 */ 
	public String getVar2() {
		return var2;
	}
		
	/**
	 * Setter property for var2
	 */ 
	public void setVar2(String newValue) {
		var2=newValue;
	}
	
	
	/**
	 * Getter property for mapped property 'values'
	 */ 
	public String getValues(String key) {
		return (String)values.get(key);
	}
	
	/**
	 * Setter property for mapped property 'values'
	 */ 
	public String setValues(String key, String newValue) {
		values.put(key,newValue);
	}
}

Notice the naming pattern for the get/set values. You take the name of the variable, prepend 'get' or 'set' to it and then capitalize the first letter of the value. Java uses this naming convention to find what it calls properties for JavaBeans. What you tell many java libraries, for example, is to set the property var2 to "abcdefg". The underlying tools figure out that the function it needs to call is setVar2("abcdefg"). This naming method and corresponding method references are used extensively in jsp tag libraries.

The odd duck out that I want to mention is the so-called "Mapped Properties", which in the example above was called "values". While the Struts tag library can reference Mapped Properties, the Java Standard Tag Library (JSTL) does not. However, a workaround can be made by exposing the underlying Map object, which JSTL can work with. To add this compatibility layer, simply add the method:

public Map getValuesMap() {
		return Collections.unModifiableMap(values);
	}
and you now have a read only Map that JSTL can work with but not mess up the rest of your bean state.

Rendering ControllerResponse With JSP

Although we can use <jsp:usebean property="controllerResponse">, this gets troublesome when dealing with any controllerResponse of sufficient complexity. For the rest of the chapter we will focus on two methods of writing the JSP pages: The Java Standard Tag Library (JSTL), or the Struts Tag Library.

Which tag library is better: Struts or JSTL?

The answer is that famous ambiguous phrase: "It Depends."

JSTL has advantages in that it is now an official JSR-based specification and will continue to grow in popularity as 'the' way of working with jsp pages.

However, Struts tags have the advantage in that they support Servlet API 2.2 compliant application servers. JSTL requires Servlet API 2.3, and as such can easily eliminate many houses that rely on older application servers.

Finally, it may depend on what you've been trained in. Many people who work with Expresso do so with Struts experience, and therefore, they can easily be up to speed with Expresso JSP writing in much less time than it would take to learn JSTL.

If you are completely new to both and you have a Servlet API 2.3 compliant container (such as Jakarta Tomcat 4.0 or greater), the author recommends that you would be better off if you learn JSTL since it will eventually become a widely used specification. To get your feet wet, it is recommended that you take a look at "JSTL in Action" by Shawn Bayern, published by Manning Press. Shawn is implementation lead for the Jakarta JSTL implementation and is a member of the JCP Committee on JSTL. The book is amazingly easy to read and does not require previous experience with Struts, Expresso, or anything like that.

A Common Controller

Before we get started in this introduction, we need a sample ControllerResponse to work with from the JSTL side. Out goal is to output the contents of the ControllerResponse onto a jsp page.

public Controller myController {
	//declarations here
	
	public ControllerResponse runMyState(ControllerRequest request, 
		ControllerResponse response) {
		//Add an output named 'hello' to the response
		response.add(new Output("hello","This is a rather unusual Hello World");
		
		//Add a block to the response named 'aBlock'
		Block aBlock = new Block("aBlock");	
		response.add(aBlock);
		
		//Add an output to aBlock called 'prisonHello' with the attribute
		//'CellNumber' set.
		Output o = new Output("prisonHello","Hello World From A Block")
		o.setAttribute("CellNumber","591-A");
		aBlock.add(o);
		
		//
		//Add yet another cell man saying hello
		//
		o = new Output("prisonHello","Hello World From A Block Too!")
		o.setAttribute("CellNumber","592-B");
		aBlock.add(o);

	
		//
		//Add a new input for a form
		//
		Input i = new Input("input1","Enter a new value");
		i.setDefaultValue("Abcdefg");
		response.add(i);
		
		//Add a transition to the 'process state' of this controller
		//(Which isn't shown for brevity sake)
		Transition t = new Transition("process",this);		
		response.add(t);
		
		//
		//Add another transition that isn't necessarily supposed to
		//be a submit button, but rather a link to log out [logout
		//state also left out of the example]
		//
		t = new Transition("logout", this);
		response.add(t);	
	}

}

Processing With Struts Tags

A sample JSP code below will show how to access all the various items in the ControllerResponse. Formatting is kept out to keep the code short. Remember that with bean properties, if you see somebody reading the property 'content', that under the hood, the function getContent() is being called.

<%@ taglib uri="/WEB-INf/tld/struts-logic.tld" prefix="logic"%>
<%@ taglib uri="/WEB-INF/tld/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/tld/struts-bean.tld" prefix="bean"%>

<html>
<head>
<title>Hello World With Twist</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%-- 
	Write Output Hello 
--%>
	<h1><bean:write name="controllerResponse" property="output(hello)"/></h1>
	
<%--
Iterate over all of aBlock and for each output retrieved, write the message and
the cell they're from.
--%>
	<logic:iterate id="eachPrisoner" name="controllerResponse" 
			property="block(aBlock).outputs"/>
			
		<p><b>Message: </b> <bean:write name="eachPrisoner" property="content"/> 
		From Cell: <bean:write name="eachPrisoner" property="attribute(CellNumber)"/>
		</p>
	</logic:iterate>
	<hr/>
	<h1>Sample Form</h1>
	
<%-- Create a Sample form with one input and one button
--%>
	<html:form action="/myapp/MyForm.do" method="post">
	
<%-- Create the button
--%>
		<bean:define id="input1Value" name="controllerResponse" 
			property="input(input1).defaultValue"/>
		<html:text name="controllerResponse" property="input(input1)"
			 defaultValue="<%= input1Value %>"/>

<%--
The following hidden parameter is used so that when
the form posts, it gets routed to the state 'process'
--%>
		<bean:define id="stateVariable" name="controllerResponse"
			 property="transition(process).state/>
		<input type="hidden" name="state" value="<%=stateVariable%>"/>
		
<%--
Create the Submit label
--%>
		<bean:define id="submitLabel" name="controllerResponse"
			 property="transition(process).label"/>
		<bean:define id="submitName" name="controllerResponse" 
			property="transition(process).name"/>
		<input type="submit" name="Submit" value="<%=submitLabel%>" 
			id="<%=submitName%>/>
	</html:form>
	<hr />
	
<%--
And finally, create a 'logout' link
--%>	
	<p>
	<html:link name="controllerResponse" property="transition(logout).url">
	<bean:write name="controllerResponse" property="transition(logout).label"/>
	</html:link>
	</p>
</body>
</html>

Processing with Struts Extended Tags

The biggest limitation that Struts has is that when dealing with Expresso ControllerElements, you often have to perform multiple <bean:define> tags before you can write the actual code. The Struts Extended Tags included with Expresso are designed to reduce some of the coding work and still retain the same feel as the original Struts tags.

Syntax-wise, the extension tags are also significantly different. The tags were originally written before Struts had the ability to access items such as 'Mapped Properties'. As such, the syntax conforms more like XPath syntax.

  • Nesting is performed with '/' instead of periods.

  • ControllerElement attributes are accessed through the at sign(@).

  • Properties are accessed through periods.

Now let's look at a jsp page written entirely in Struts-Extension tags, that has the identical functionality as the pure-struts tags. Notice that his example uses the same prefix, but they point to the expresso-extension tag libraries instead. You can mix Struts extension tags and pure struts tags in the same page. Usually, the author assigns struts tag libraries to have the struts extension to them. So 'logic' becomes 'struts-logic', 'bean' becomes 'struts-bean' etc.

<%@ taglib uri="/WEB-INf/tld/expresso-logic.tld" prefix="logic"%>
<%@ taglib uri="/WEB-INF/tld/expresso-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/tld/expresso-bean.tld" prefix="bean"%>

<html>
<head>
<title>Hello World With Twist</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%-- 
	Write Output Hello 
--%>
	<h1><bean:write property="hello"/></h1>
	
<%--
Iterate over all of aBlock and for each output retrieved, write the message and
the cell they're from.
--%>
	<logic:iterate id="eachPrisoner" property="aBlock"/>
			
		<p><b>Message: </b> <bean:write name="eachPrisoner"/> 
		From Cell: <bean:write name="eachPrisoner" property="@CellNumber"/>
		</p>
	</logic:iterate>
	<hr/>
	<h1>Sample Form</h1>
	
<%-- Create a Sample form with one input and one button
--%>
	<html:form action="/myapp/MyForm.do" method="post">
	
<%-- Create the button
--%>
		<html:text property="input1"/>
		
<%--
Create the Submit label.  The Expresso extension automatically create
any and all hidden parameters.
--%>
		<html:submit property="process"/>
	</html:form>
	<hr />
	
<%--
And finally, create a 'logout' link.  The special exLink tag creates the link, the label, and the name based upon the designated transition.
--%>	
	<p>
	<html:exLink property="logout"/>
	</p>
</body>
</html>

You may notice in this example, that many pieces are calculated automatically for you. For example, unless you specify the tag's 'name', it is automatically assumed that you are talking about the object named 'controllerResponse'. Secondly, the XPath-like tags are smart enough to know that if it comes across an output, bean:write is talking about writing the contents of the output. So significant typing can be saved using the Struts-extension tags rather than pure struts tags. But sometimes the logic in dealing with the struts-extension tags can be rather confusing, especially when dealing with nested elements. So sometimes, the pure struts tags or JSTL tags make more sense.

Processing with JSTL

JSTL has its own advantages and detractions. Among its advantages are:

  • Standards Based. The JSTL expression language is part of the JSP 2.0 specification.

  • Powerful Expression Language. The JSTL expression language has great flexibility, and provides a viable alternative to including scriptlets in your JSP pages.

  • Very friendly with Visual HTML builders. Include <c:out> tags inside the appropriate items in a standard html page, and programs such as Dreamweaver will be quite happy.

At the same time, its detractions are:

  • Very Verbose. JSTL expressions are much more verbose than, for example, the struts extension tags.

  • Incapable of Mapped Properties. Unlike the Struts 1.1 tags, JSTL cannot handle mapped properties in a bean. To be compatible with JSTL, you must include methods to expose an entire underlying java.util.Map interface.

  • Slower performance. JSTL expressions are much more complicated than Struts-extensions, and are thus likely to lead to slower performance. This penalty, of course, will tend to become less of a factor as time goes on as more people analyze the JSTL-EL and optimize its performance.

Processing with JSTL Extended Tags

Like the basic Struts tags, the JSTL tags are limited when dealing with Expresso ControllerElements: you often have to perform multiple <c:out> tags before you can write the actual code. The JSTL Extended Tags included with Expresso are designed to reduce some of the coding work and still retain the use of the JSTL expression language.

For example, a number of rows of 'dropdown menu' are created by 'select' tags below. Each dropdown menu is an Input, added to the 'row' block, and each Input has a list of ValidValues which are its menu items.

<table border="0" cellspacing="0" cellpadding="5">
    <c:forEach items="${controllerResponse.nestedMap['row'].nested}" var="oneBlock">
        <tr>
            <td>
                <c:out value="${oneBlock.name}"/>
            </td>
            <td>
                <select name="<c:out value='${oneBlock.inputs[0].name}'/>" >
                    <expresso_el:options value="${oneBlock.inputs[0]}"/>
                </select>
            </td>
        </tr>
    </c:forEach>
</table>

For a checkbox Input, we indicated the 'selected' attribute to indicate check-ness:

<input  type="checkbox" class="mediumtext"
        name="<c:out value="${oneInput.name}" />"
        value="<c:out value="${oneInput.defaultValue}" />"
        <c:if test="${not empty oneInput.attributes['selected']}"> CHECKED </c:if>
/>

For a checkbox Input, we use a 'selected' attribute to indicate checked-ness:

<input  type="checkbox" class="mediumtext"
        name="<c:out value="${oneInput.name}" />"
        value="<c:out value="${oneInput.defaultValue}" />"
        <c:if test="${not empty oneInput.attributes['selected']}"> CHECKED </c:if>
/>

A submit button requires two special tags:

<input type="submit" name="<expresso_el:submitname value='${controllerResponse.namedTransitions['doScore']}'/>"
       value="Save">
       <expresso_el:buttonparams value="${controllerResponse.namedTransitions['doScore']}"
/>

Rendering the ControllerResponse with XSLT

As of Expresso 5.1, XSL stylesheets are first class citizens. To have a response processed with an XML stylesheet, simply add the location of the stylesheet to your 'struts-configuration'. The following listing gives an example of this.

<action path="/SampleController" type="org.example.myapp" name="default" scope="request" validate="false">
    <!-- this state forwards to a jsp -->
    <forward name="start" path="/expresso/components/myapp/start.jsp"/>
    <!-- this state forwards to a stylesheet for processing -->
    <forward name="process" path="/expresso/components/myapp/process.xslt"/>
</action>

Rendering ControllerResponse With Velocity

As of Expresso 5.6, Velocity can be used within Expresso. Velocity is a “simple yet powerful template language” . If the developer wishes, Velocity and JSP can be used within the same application. For more information about Velocity, see the Velocity homepage.

Configuring Velocity in Expresso

Velocity support is provided through an Expresso extension of Velocity's VelocityView tool. The following are required to enable velocity support:

  1. Download the VelocityTools package. Copy the velocity-dep-{version}.jar , velocity-tools-{version}.jar , and velocity-tools-view-{version}.jar files to WEB-INF/lib .

  2. Make sure the /WEB-INF/velocity directory exists with all files. This is distributed with Expresso 5.6 and above, but may not be present if upgrading from an older version.

  3. Add the following to web.xml :

    <servlet>
    	<servlet-name>velocity</servlet-name>
    	<servlet-class>
    		org.apache.velocity.tools.view.servlet.VelocityLayoutServlet
    	</servlet-class>
    	<init-param>
    		<param-name>org.apache.velocity.toolbox</param-name>
    		<param-value>/WEB-INF/velocity/toolbox.xml</param-value>
    	</init-param>
    	<init-param>
    		<param-name>org.apache.velocity.properties</param-name>
    		<param-value>
    			/WEB-INF/velocity/velocity.properties
    		</param-value>
    	</init-param>
    	<load-on-startup>10</load-on-startup>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name>velocity</servlet-name>
    	<url-pattern>*.vm</url-pattern>
    </servlet-mapping>

Velocity Global Macros for Expresso Integration

Several global macros have been defined to make using Velocity within Expresso easier.

Table 16.1. Expresso Global Macros

Macro DefinitionArgumentsDescription
exp_string( $code )
code

The String to lookup

Get a string from schema resources
exp_string_args( $code $args )
code

The String to lookup

Get a string from schema resources - supplying replacement arguments
exp_element( $var $path )
var

variable to load the element into

path

path to search for the element, relative to the root

Get a ControllerElement in the path relative to the root

Examples:

  • #exp_element( $myelement "lists/groups/tests" )

    returns the element named 'tests'

  • #exp_element( $myelement "lists/groups/@style" )

    returns the string for attribute 'style' in 'groups'

exp_elementFrom( $var $from $path )
var

variable to load the element into

from

element to search for the element in

path

path to search for the element, relative to $from

Get a ControllerElement in the path relative to the supplied element. A leading / will make it relative to the root
exp_content( $var $from $path )
var

variable to load the content into

from

element to search for the element in. 'null' for root

path

path to search for the element, relative to $from

Get the content item inside an element.
exp_printContent( $from $path )
from

element to search for the element in. 'null' for root

path

path to search for the element, relative to $from

Print the content item inside an element.
exp_standard() Setup the standard environment. Sets the following variables:
configManager

The com.jcorporate.expresso.core.misc.ConfigManager object

imagesDir

The images directory defined in the context

contextPath

The path of the current context

expressoDir

The location of the expresso directory as defined in the context

expressoContextPath

The full path of the expresso directory as defined in the context

errorMarkup() Print all errors, wrapped in html markup

Using Velocity within Expresso

Using velocity with Expresso is simple: just define the .vm file as the forward of your action. For example, the following shows 2 examples of Login's promptSendPassword state. One uses jsp and the other uses Velocity:

Example 16.1. Login's promptSendPassword state using jsp

struts-config.xml :

<action path="/Login" type="com.jcorporate.expresso.services.controller.SimpleLoginController" name="default" scope="request" validate="false">
	<forward name="promptLogin" path="/expresso/jsp/register/login.jsp"/>
	<forward name="processLogin" path="/expresso/jsp/register/redirect.jsp"/>
	<forward name="processLogout" path="/expresso/jsp/register/logout.jsp"/>
	<forward name="promptChangePassword" path="/expresso/jsp/register/change.jsp"/>
	<forward name="processChangePassword" path="/expresso/jsp/register/status.jsp"/>
	<forward name="emailValidate" path="/expresso/jsp/register/status.jsp"/>
	<forward name="promptSendPassword" path="/expresso/jsp/register/sendPassword.jsp"/>
	<forward name="processSendPassword" path="/expresso/jsp/register/status.jsp"/>
</action>

/expresso/jsp/register/sendPassword.jsp (simplified for illustrative purposes):

<%@ page language="java" errorPage="../../error.jsp"%>
<%@ taglib uri="/WEB-INF/tld/expresso.tld" prefix="expresso"%>
<%@ taglib uri="/WEB-INF/tld/expresso-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/tld/expresso-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/tld/expresso-logic.tld" prefix="logic"%>
<%@ taglib uri="/WEB-INF/tld/struts-bean.tld" prefix="struts-bean"%>
<%@ taglib uri="/WEB-INF/tld/struts-html.tld" prefix="struts-html"%>
<%@ taglib uri="/WEB-INF/tld/struts-logic.tld" prefix="struts-logic"%>

<%@ page import="com.jcorporate.expresso.core.misc.StringUtil" %>
<%@ page import="com.jcorporate.expresso.services.dbobj.Setup" %>
<%@ page import="com.jcorporate.expresso.core.jsdkapi.GenericSession" %>
<%@ page import="com.jcorporate.expresso.core.misc.ConfigManager" %>

<%	
    String db = StringUtil.notNull(GenericSession.getAttributeString(request, "db"));
	if (db.length() == 0) {
		db = "default";
	}
	String contextPath = StringUtil.notNull(Setup.getValue(db, "ContextPath"));
%>

<html>
<head>
<expresso:stylesheet />
<title><bean:message key="passwdResetSubject" /></title>

</head>
<body class="jc-default">

<!-- top.inc -->
<table border="0" width="100%" class="statuspage" cellpadding="3"
	cellspacing="0">
	<tr>
		<td align="left" class="statuspage">
		<td align="left" width="33%" class="statuspage">Logged in as: <expresso:UserName /></td>
		<td align="center" width="33%" class="statuspage">&nbsp;</td>
		<td align="right" width=33% class="statuspage"><expresso:DBDescription /></td>
	</tr>
</table>
<table border="0" width="100%" class="jc-datadivider" cellpadding="5"
	cellspacing=0">
	<tr class="jc-datadivider">
		<td align="left" class="jc-datadivider">&nbsp;Login and Registration</td>
	</tr>
</table>

<!-- errorRow.inc -->
<expresso:IfErrorExists>
	<tr>
		<td colspan=2>
		<hr>
		</td>
	</tr>
	<tr>
		<td colspan=2>
		<p><font class="jc-error-field"> <expresso:ErrorMessages /> </font></p>
		</td>
	</tr>
</expresso:IfErrorExists>

<form class="jc-default" action="<%=contextPath%>/Login.do" method=POST>

<div align="center">
<TABLE border="0" cellspacing="0" align="center">
	<tr>
		<td>
		<P class="jc-emphasis"><bean:message key="passwdResetSubject" /></P>
		</td>
		<td align=right></td>
	</tr>
	<TR>
		<TD nowrap><B>Email</B></TD>
		<TD nowrap>
			<html:text property="Email" />
		</TD>
	</TR>
	<tr>
		<td colspan=2>
		<hr>
		</td>
	</tr>
	<tr>
		<td ALIGN="center" colspan=2>
			<expresso:TransitionTag	name="processSendPassword" />
		</td>
	</tr>
</TABLE>
</div>
</form>
</body>
</html>

Example 16.2. Login's promptSendPassword state using Velocity

struts-config.xml (note the filename change in the path of the promptSendPassword forward):

<action path="/Login" type="com.jcorporate.expresso.services.controller.SimpleLoginController" name="default" scope="request" validate="false">
	<forward name="promptLogin" path="/expresso/jsp/register/login.jsp"/>
	<forward name="processLogin" path="/expresso/jsp/register/redirect.jsp"/>
	<forward name="processLogout" path="/expresso/jsp/register/logout.jsp"/>
	<forward name="promptChangePassword" path="/expresso/jsp/register/change.jsp"/>
	<forward name="processChangePassword" path="/expresso/jsp/register/status.jsp"/>
	<forward name="emailValidate" path="/expresso/jsp/register/status.jsp"/>
	<forward name="promptSendPassword" path="/expresso/jsp/register/sendPassword.vm"/>
	<forward name="processSendPassword" path="/expresso/jsp/register/status.jsp"/>
</action>

/expresso/jsp/register/sendPassword.vm :

<html>
<head>
#exp_standard()
<link rel="stylesheet" type="text/css" href="$contextPath/expresso/style/default.css">
<title>#exp_string( "passwdResetSubject" )</title>

</head>
<body class="jc-default">

<!-- top.inc -->
<table border="0" width="100%" class="statuspage" cellpadding="3"
	cellspacing="0">
	<tr>
		<td align="left" class="statuspage">
		<td align="left" width="33%" class="statuspage">Logged in as: $controllerResponse.getUser()</td>
		<td align="center" width="33%" class="statuspage">&nbsp;</td>
		<td align="right" width=33% class="statuspage">$configManager.getContext($db).getDescription()</td>
	</tr>
</table>
<table border="0" width="100%" class="jc-datadivider" cellpadding="5"
	cellspacing=0">
	<tr class="jc-datadivider">
		<td align="left" class="jc-datadivider">&nbsp;Login and Registration</td>
	</tr>
</table>

<!-- errorRow.inc -->
#if ($errors.exist() )
	<tr>
		<td colspan=2>
		<hr>
		</td>
	</tr>
	<tr>
		<td colspan=2>
		<p><font class="jc-error-field"> #errorMarkup() </font></p>
		</td>
	</tr>
#end

<form class="jc-default" action="$contextPath/Login.do" method=POST>

<div align="center">
<TABLE border="0" cellspacing="0" align="center">
	<tr>
		<td>
		<P class="jc-emphasis">#exp_string( "passwdResetSubject" )</P>
		</td>
		<td align=right></td>
	</tr>
	<TR>
		<TD nowrap><B>Email</B></TD>
		<TD nowrap>
			#exp_element($Email "Email")
			<input type="text" name="Email" value="#exp_printContent($Email null)" />
		</TD>
	</TR>
	<tr>
		<td colspan=2>
		<hr>
		</td>
	</tr>
	<tr>
		<td ALIGN="center" colspan=2>
			#exp_element( $processSendPassword "processSendPassword" )
			<input type="submit" name="button_$processSendPassword.getName()" value="$processSendPassword.getLabel()">
			$processSendPassword.getHTMLParamString()
		</td>
	</tr>
</TABLE>
</div>
</form>
</body>
</html>

How to shorten URLs in links

How to make the URLs in links shorter: JSTL does this by default, or an option in the Expresso tag library will omit the controller parameter if you know you do not want it. Here's the deal: In JSTL, the URL is generated in whole by "fullUrl", and is automatically "optimized" to remove the controller parameter if it is unnecessary. For example, if you have a Transition object with name "attribCustom" in the response, then the following will provide a nice HTML link:

<a href="<c:out value='${controllerResponse.nestedMap['attribCustom'].fullUrl}'/>"><small>View</small></a>
However, with the old Expresso tag library, links are created partly from 'naked' text in the JSP and partly from the Expresso tag:
<a href="<sri_expresso:Context/>AddNodeAction.do?<sri_expresso:TransitionParamsTag name="<%=AddNodeAction.VIEW_NODE%>"/>">blah</a></td>
note that we supplied the "file" part of the URL, "AddNodeAction.do" in this example. I've added an option "omitControllerParam" to the TransitionParamsTag that will omit the controller parameter. This is appropriate for most cases where the transition is going to the same controller that we manually put into the "file" section:
<a href="<sri_expresso:Context/>/do/AddNodeAction?<sri_expresso:TransitionParamsTag omitControllerParam="true" name="<%=AddNodeAction.VIEW_NODE%>"/>">blah</a></td>
So to reduce the size of URLs, you can go through all the TransitionParamsTag's and add this option (after confirming that the destination controller is the same as the naked text), or you can translate to JSTL.

Universal Dispatch

Expresso's controller/state system is a finite-state machine, where each state can be determined by the HTTP parameters "controller" and "state" (assumptions apply if these are missing). By convention in Expresso, these parameter will take precedence over the 'file' part of the URL. Therefore, if you have a URL like http://myapp/somecontroller.do?controller=blah , then the "controller" parameter will win out: instead of going to the controller "somecontroller", you will end up at controller "blah".

This leads to a concept called "universal dispatch", where you may assume that expresso will do the 'right thing' when POSTing a form. For example, consider a design where you wish for the 'view' to be relatively ignorant of how it is used by controllers. The view gets inputs, outputs, and transitions, and lays them out. But to where does it submit the form for a POST? We don't want the view to know about where the 'action' attribute should be headed. That is controlled by the controller. For example, consider a scenario where one submit button in a POST form directs the user to controller A, while other submit buttons in the form send the user to controler B. What should the 'action' URL be in the HTML form tag? That is where universal dispatch comes in. The submit button's parameters (if you use the expresso tags) are complete with controller and state parameter, so the view (the JSP) does not need to know. If we assume the 'prompt' page for submission (i.e., the page with the HTML form tag) came from an expresso controller, the action can be omitted on the form tag. HTTP will direct the submission back to the URL from where it came, and in turn, the 'controller' param will be parsed by expresso, and the submission will finally be forwarded to the correct controller. Below is an example.

<%-- form deliberately has no action attribute (assumes that this page
        was generated by an expresso controller) --%>
<form method="POST" name="form1" >
        <%-- ... various inputs and outputs ... --%>

        <%-- button's controller param will control destination of POST --%>
         <input type="submit" value="Add"
            name="<expresso_el:submitname
                value='${controllerResponse.namedTransitions['mySubmitTrans']}'/>"
         >
            <expresso_el:buttonparams
                value="${controllerResponse.namedTransitions['mySubmitTrans']}"/>
</form>

If you want an 'action' attribute instead of omitting it, you can put in any controller you like. (Note: this feature was partially broken in v.5.5, but fixed in cvs in whatever version comes after 5.5.1.) For example, you can use a randomly-chosen expresso controller

<form method="POST" name="form1" action="<c:url value='/Download.do' />" >

Conclusion

Contributors

The following persons have contributed their time to this chapter:

Note

Was this EDG documentation helpful? Do you wish to express your appreciation for the time expended over years developing the EDG doc? We now accept and appreciate monetary donations. Your support will keep the EDG doc alive and current. Please click the Donate button and enter ANY amount you think the EDG doc is worth. In appreciation of a $35+ donation, we'll give you a subscription service by emailing you notifications of doc updates; and donations $75+ will also receive an Expresso T-shirt. All online donation forms are SSL secured and payment can be made via Credit Card or your Paypal account. Thank you in advance.

Copyright © 2001-2004 Jcorporate Ltd. All rights reserved.