
Beginning Apache Struts - From Novice To Professional (2006)
.pdf348 |
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
Listing 20-15. New <managed-bean> Declarations for the Registration Webapp
<managed-bean> <managed-bean-name>logon</managed-bean-name>
<managed-bean-class>net.thinksquared.reg.User</managed-bean-class> <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean> <managed-bean-name>register</managed-bean-name>
<managed-bean-class>net.thinksquared.reg.User</managed-bean-class> <managed-bean-scope>request</managed-bean-scope>
</managed-bean>
As you can see, we’ve used the naming rule we discussed earlier. Also, the binding and value attributes in register.jsp and logon.jsp will have to change. Instead of using
#{used.XXX}, you have to use either #{logon.XXX} or #{register.XXX}, as appropriate.
Dialog Manager
According to the Shale website, Shale’s Dialog Manager is a “mechanism to define a ‘conversation’ with a user that requires multiple HTTP requests to implement, modeled as a state diagram.”
So, a dialog is an interaction with the user spanning multiple HTTP requests. Shale lets you model a dialog (you can define more than one dialog) in an XML file, usually called dialog-config.xml. You must declare this in your web.xml file like so:
<context-param> <param-name>org.apache.shale.dialog.CONFIGURATION</param-name> <param-value>/WEB-INF/dialog-config.xml</param-value>
</context-param>
If you have more than one dialog configuration file, simply add them to the declaration using a comma as a separator.
Each “dialog” is modeled as a state diagram. Listing 20-16 shows how we might define a couple of dialogs for the Registration webapp.
Listing 20-16. Dialogs for the Registration Webapp (dialog-config.xml)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dialogs PUBLIC
"-//Apache Software Foundation//DTD Shale Dialog Configuration 1.0//EN" "http://struts.apache.org/dtds/shale-dialog-config_1_0.dtd">

C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
349 |
<dialogs>
<dialog name="Logon" start="Perform Logon">
<action name="Perform Logon" method="#{logon.Logon}"> <transition outcome="success" target="Exit"/> <transition outcome="register" target="Register User"/>
</action>
<subdialog name="Register User" dialogName="Register User"> <transition outcome="success" target="Exit"/>
</subdialog>
<end name="Exit" viewId="/success.jsp"/>
</dialog>
<dialog name="Register User" start="Registration Form">
<view name="Registration Form" viewId="/register.jsp"> <transition outcome="register" target="Perform Registration"/>
</view>
<action name="Perform Registration" method="#{register.Register}"> <transition outcome="success" target="Exit"/>
</action>
<end name="Exit" viewId="/success.jsp"/>
</dialog>
</dialogs>
The logic of Listing 20-16 should be obvious. Notice that we’ve used the new <managed-bean> declarations of Listing 20-15 here.
■Note The Registration webapp doesn’t fully reveal the usefulness of Shale’s dialogs, because the user interaction spans only a couple of pages.

350 |
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
Notice that in Listing 20-16 all the transition information is contained in the dialog-config.xml file. But in our earlier JSF implementation, the JSP pages invoked the functions on the user backing bean directly like so:
<h:commandButton action="#{user.Logon}" ... //see Listing 20-11 <h:commandLink action="register"> ... //see Listing 20-11 <h:commandButton action="#{user.Register}" ... //see Listing 20-12
We’ll have to change these to
<h:commandButton action="dialog:Logon" ...
<h:commandLink action="dialog:Register User"> ...
<h:commandButton action="register" ...
because the navigation is now performed using Shale’s Dialog Manager, not by JSF’s default navigation handler. Notice that the action attributes now begin with dialog:XXX, with XXX the “name” of the dialog. The command button that submits the registration information (on register.jsp):
<h:commandButton action="register" ...
is different because it needs to return a logical outcome and not enter into a dialog directly:
<view name="Registration Form" viewId="/register.jsp"> <transition outcome="register" target="Perform Registration"/>
</view>
Lastly, note that you can mix both JSF-type navigation and Shale’s dialog-based navigation. All you need to do in order to enter a Shale dialog is to use a logical outcome named dialog:XXX. In our case, we’ve moved all the navigation elements from Listing 20-8 into the dialog config file, so the faces-config.xml file should now only contain the <managed-bean> declarations.
Exercise
Download the latest copy of the Shale distribution (see “Useful Links”) and implement the Registration webapp as we’ve discussed up to this point.
Integration with the Validator Framework
At the time of this writing, the integration with the Validator framework does not include the use of a validations.xml file in which you can declare your validations.
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
351 |
Instead, Shale’s approach to integration with the Validator framework is very similar to the MyFaces approach of creating extensions to JSF. The one big advantage Shale has is that you can create client-side validations, as you can with Struts.
For server-side validations, however, the MyFaces approach appears cleaner, at least for the moment. Shale is a moving target!
Here’s how to use Shale’s validator tags:
1.Add validator-rules.xml from the Commons Validator distribution to your WEB-INF directory. You can use the one that comes with classic Struts.
2.Put in this taglib declaration: <%@ taglib uri="http://struts.apache.org/shale/ core" prefix="s" %>.
3.Add Shale’s validators to JSF input components with <s:commonsValidator>.
If you want client-side validation, you need to add the extra attribute onsubmit='validateForm(this)' and the child tag <s:validatorScript functionName= "validateForm"/> to the <h:form>. The former invokes the JavaScript functions to validate the form, while the latter instructs Shale to paste in the JavaScript validation code.
Listing 20-17 shows how we might rewrite logon.jsp (see Listing 20-11) using Shale’s Validator framework. As usual, we’ve stripped out the <f:verbatim> tags.
Listing 20-17. logon.jsp Using Shale
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://struts.apache.org/shale/core" prefix="s"%>
<f:loadBundle basename="net.thinksquared.reg.messages" var="reg_messages"/>
<html>
<body>
<f:view>
<h:panelGroup>
<h:messages style="color:red" globalOnly="true"/> <h:outputText value="#{reg_messages['title_reg']}"
style="font-weight:bold" />
<h:form binding="#{user.container}" onsubmit=”validateForm(this)”>
<h:outputText value="#{reg_messages['user_id']}"/>
352 |
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
<h:inputText id="userId"
value="#{logon.userId}" required="true">
<s:commonsValidator type="mask" mask="^[A-Za-z0-9]{5,10}$" arg="#{reg_messages['bad_user_id']}"
server="true"
client="true"/>
</h:inputText>
<h:message for="userId" />
<h:outputText value="#{reg_messages['password']}"/>
<h:inputText id="password" value="#{logon.password}" required="true">
<s:commonsValidator type="mask" mask="^[A-Za-z0-9\-\_]{5,10}$" arg="#{reg_messages['bad_user_id']}"
server="true"
client="true"/>
</h:inputText>
<h:message for="password" />
<h:commandButton action="dialog:Logon" value="#{reg_messages['logon']}"/>
<s:validatorScript functionName="validateForm"/>
</h:form>
<h:commandLink action="dialog:Register User"> <h:outputText value="#{reg_messages['new_user']}" />
</h:commandLink>
</h:panelGroup>
</f:view>
</body>
</html>
Notice that we’ve put in the changes we made in the previous two subsections.
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
353 |
JNDI Integration
JNDI (Java Naming and Directory Interface) is a Java Enterprise Edition feature that obtains handles to resources that are declared in either web.xml or configuration settings of an application server.
A thorough discussion of JNDI is outside the scope of this book. However, the Shale website gives a couple of simple examples, variations of which we’ll describe here.
JNDI addresses the concept of environment entries, which are simply variable declarations in web.xml. For example, suppose your webapp had to display your company’s logo on each page. You could use a message resource to store the URL, but another way is to use an environment entry (I’m not recommending this method, but just using it as an illustration).
First, you declare the environment entry in web.xml:
<env-entry>
<description>URL to company logo GIF</description> <env-entry-name>logo</env-entry-name> <env-entry-value>http://www.myco.myapp/logo.gif</env-entry-value> <env-entry-type>java.lang.String<env-entry-type>
</env-entry>
Your JSF tags can use Shale’s JNDI integration feature to access this environment entry:
<h:graphicImage value=#{jndi:logo} />
That’s it. The jndi: prefix tells Shale that the binding refers to a JNDI resource, in this case, the one environment entry named logo.
A more realistic scenario involves getting a database connection. JNDI allows you to declare data source references in web.xml. For example, you might define a data source reference to your company’s personnel database like so:
<resource-ref>
<description>MyCo Personnel Database</description> <res-ref-name>jdbc/MyCoPersonnelDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth>
</resource-ref>
Typically, you’d want to create and release the database connection in your backing beans. Listing 20-18 shows how we can use Shale’s JNDI integration to provide an implementation of init() of Listing 20-14.
354 |
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
Listing 20-18. An Implementation of User.init()
public void init(){ //get faces context
FacesContext context = FacesContext.getCurrentInstance();
//create _connection to database. ValueBinding vb =
context.getApplication()
.createValueBinding("#{jndi['jdbc/MyCoPersonnelDB'].connection}");
_connection = (Connection) vb.getValue(context);
}
Reusable Views with Clay
Clay is a subframework of Shale. It is essentially a custom JSF custom UI component, which acts as a stand-in for a sub-UI tree defined elsewhere. This idea should not be new to you. Tiles does something similar—you define the UI in a tiles-def.xml file, then use a Tiles tag to indicate where you want the UI placed.
Clay does the same, but provides more options for you to build the UI tree. Any meaningful exploration of Clay would require a whole chapter by itself, so I will leave it to you to explore this interesting technology on your own.
Server-Side Ajax Support
Ajax is not a single technology but refers to a broad spectrum of technologies characterized by their use of client-side JavaScripts and XML to pass data between client and server.
Server-side Ajax support (aka remoting) involves extracting data from the Model tier and serializing it as XML for delivery to the client.
Shale’s remoting support is mainly focused on the delivery of XML data to the client (e.g., the org.apache.shale.remote.ResponseWrapper class to write XML), and management of the remote sessions.
Test Framework
Unit testing is the process of incrementally building and testing your code. In the unittesting paradigm, you code a little, then test a little, and continue until your app is done. The tests you create are Java classes that you need to run in sequence, each testing portions of your code. JUnit (see “Useful Links”) is the universally used unit-testing framework of the Java world.

C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
355 |
Believe me, unit testing can save you a lot of trouble, even on moderately complex applications. Once you’ve tried it, you’ll wonder how you ever managed to produce Java code in the past.
Unfortunately, unit testing has made little inroads into the testing of webapps. Shale supports unit testing by providing you with a set of mock objects and JUnit test case base classes. Check out the JUnit website for more details.
Exercise
Download the latest Shale distribution (see “Useful Links”) and try out the example use-cases webapp.
JSF vs. Shale vs. Struts
Ultimately, which technology you choose (JSF, Shale, or Struts) depends on your requirements. Having said that, if you’re comfortable with the Apache offerings, then you’re likely to commit to Shale over pure JSF. Shale brings so much to the table that using it over pure JSF is a no-brainer.
The Achilles’ heel of Shale is that it’s in a state of flux, like any new piece of software. At the time of this writing many of the services are marked as “Developing,” meaning they could change at any time. I certainly expect Shale to change substantially by the time you read this book. So, if you’re planning to use Shale, you should carefully research the features you need to ensure that they are fairly stable. The Struts mailing list (Shale shares this with classic Struts, so you should mark your emails with [Shale]) and the Shale documentation are good resources.
The choice between Struts and Shale is more difficult to make. If you have an existing Struts webapp, it’s advisable to continue using Struts, because the cost of porting your existing JSP pages to using JSF tags is usually prohibitive.
For new projects, it’s difficult to give a clear answer. The Struts developers themselves and those involved in JSF and Shale appear to unconditionally advocate moving to Shale or JSF. I would be more circumspect, because as you’ve seen, JSF (and therefore Shale) is more complex than Struts. It isn’t rocket science, but there’s definitely a sharp learning curve involved.
However, if you find you’ve been using strange tricks to force Struts into getting your webapp to behave like a desktop application, then Shale is definitely something you’d want to explore along with other web application frameworks like Spring.
I’ve avoided giving you a feature-by-feature comparison of Struts, JSF, and Shale. Although they are all, broadly speaking, web application frameworks, their “sweetspots” (the scenarios in which they shine) are different.

356 |
C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
Instead, Table 20-3 compares classic Struts, JSF, and Shale to help you answer a simple question: “I’m starting a new project. Should I use Struts or Shale or JSF?” Take the ratings as being relative to each other. Please don’t take them to be absolute in any sense—“easy” for example, means “easy compared to” the other options.
Table 20-3 doesn’t take into account the Struts-Faces integration library. Even if it did, probably not much would change. Struts suffers from design issues that won’t go away easily. These deficiencies (poor extensibility, code modularity and code reuse) come to the fore when you’re developing more complex applications. The Struts-Faces library, though useful, doesn’t address architectural issues.
Table 20-3. Comparison Matrix for Struts, JSF and Shale
Factor |
Struts |
JSF |
Shale |
Comments |
|
|
(MyFaces) |
|
|
|
|
|
|
|
Learning curve |
Gentle |
Average |
Steep |
Shale’s learning curve is steepest because it |
|
|
|
|
introduces additional services on top of JSF. |
Developing |
Easy |
Difficult |
Average |
By a “simple” webapp I mean something like |
simple webapps |
|
|
|
LILLDEP in complexity. Many webapps cur- |
|
|
|
|
rently fall into this category. Shale, with its |
|
|
|
|
Dialog Manager, improves page transition |
|
|
|
|
maintenance. This is a definite plus over |
|
|
|
|
pure JSF. |
Developing |
Very |
Average |
Average/Easy |
By “complex” webapps I mean a webapp |
complex |
difficult |
|
|
that (for example) replicates the full func- |
webapps |
|
|
|
tionality of OpenOffice Writer (or Word). |
|
|
|
|
Shale, with its extensibility, and extras (like |
|
|
|
|
support for Ajax, dialogs, etc.) makes life |
|
|
|
|
much better. |
Extensibility |
Poor |
Very good |
Good |
Struts only offers plug-ins for extensibility |
|
|
|
|
(and more limited extensibility in the form of |
|
|
|
|
custom loaders for the configuration file). |
|
|
|
|
You can do a lot with the extensibility points |
|
|
|
|
that Struts offers, but you’d have to reinvent |
|
|
|
|
the wheel sometimes, as I did in Chapter 19. |
|
|
|
|
Both JSF and Shale offer much more struc- |
|
|
|
|
tured ways in which you can extend them. |
Longevity |
High |
Very high |
Moderate/Low |
By longevity, I mean “What’s the probability |
|
|
|
|
of this framework being around in five years’ |
|
|
|
|
time?” These are my forecasts: JSF’s survival |
|
|
|
|
is assured, given Sun’s endorsement of it as a |
|
|
|
|
spec, and as the only credible components- |
|
|
|
|
based web framework for the Java platform. |
|
|
|
|
Struts classic will probably survive because |
|
|
|
|
of its huge user base. Shale might be over- |
|
|
|
|
shadowed by competing technologies in the |
|
|
|
|
same niche, ones that don’t pretend to be a |
|
|
|
|
“Struts successor.” So it’s very unfortunate |
|
|
|
|
that it’s named Struts Shale. People then |
|
|
|
|
tend to think in terms of Struts classic versus |
|
|
|
|
Struts Shale, when in fact, they best apply to |
|
|
|
|
different niches. |

C H A P T E R 2 0 ■ J A V A S E R V E R F A C E S A N D S T R U T S S H A L E |
357 |
Table 20-3. Comparison Matrix for Struts, JSF and Shale
Factor |
Struts |
JSF |
Shale |
Comments |
|
|
(MyFaces) |
|
|
|
|
|
|
|
Ease of |
Easy |
Easy |
Difficult |
If classic Struts remains backward compati- |
upgrading |
|
|
|
ble, then obviously it’s easy to upgrade. JSF |
|
|
|
|
is a mature spec, so you shouldn’t expect |
|
|
|
|
surprises there either. Shale, on the other |
|
|
|
|
hand, is changing (at the time of this writing), |
|
|
|
|
so you might experience difficulty upgrad- |
|
|
|
|
ing to a newer version. |
Code reuse |
Low |
High |
Average |
Code reuse becomes important in more com- |
|
|
|
|
plex projects, so the ratings given here apply |
|
|
|
|
mainly to them. JSF was built with reuse and |
|
|
|
|
extensibility foremost. |
Modular Code |
Low |
Average |
Average |
It’s difficult to make modular code with |
|
|
|
|
Struts for complex webapps. You might have |
|
|
|
|
gotten a glimpse of this in Lab 14. It’s easy to |
|
|
|
|
create modular code with JSF if you know |
|
|
|
|
how, but it’s also easy to make a mess of it. |
|
|
|
|
Code modularity impacts maintenance and |
|
|
|
|
development. The more modular the code, |
|
|
|
|
the easier it is to maintain and develop. See |
|
|
|
|
the answer for the question raised in Chapter 1, |
|
|
|
|
given in Appendix D, for a short discussion |
|
|
|
|
of this. |
|
|
|
|
|
Useful Links
•The official JSF specification: http://java.sun.com/j2ee/javaserverfaces/ download.html
•MyFaces website: http://myfaces.apache.org/
•Struts-Faces integration library download site: http://jakarta.apache.org/site/ binindex.cgi
•The Sun JSF download site: http://java.sun.com/j2ee/javaserverfaces/ download.html
•The official Shale website: http://struts.apache.org/struts-shale/index.html
•Struts Ti website: http://struts.apache.org/struts-sandbox/struts-ti/index.html
•WebWork website: www.opensymphony.com/webwork/
•Struts OverDrive website: http://opensource2.atlassian.com/confluence/oss/ display/OVR/Home