 |
March 2006 Archives
Survey: JSF Implementations in App Servers and Developer Tools
Posted by edburns on March 27, 2006 at 10:22 AM | Permalink
| Comments (1)
Updated: app servers added to query
Rather than spend lots of time researching this, I thought I'd try my hand at asking a question of the blogosphere.
I'd like to know what developer tools and application servers are using which JSF implementation. I know that WebSphere Studio (or RAD, or whatever it's called these days) used Sun's JSF impl pretty much off-the-shelf, and that Oracle uses Sun's with major Oracle extensions in its JDeveloper product. What about other application servers, tools and IDEs? Does any tool use MyFaces?
Thanks,
Ed (JSF co-spec-lead)
Technorati Tags: edburns
Using JSP Immediate Expressions to access JSF Data
Posted by edburns on March 15, 2006 at 10:48 AM | Permalink
| Comments (7)
Here is an ultra-quick blog entry sharing something in JSF 1.2 about
which I'm not sure many people are aware. Thanks to the unified EL, it
is possible to refer to JSF managed beans and other JSF concepts using
plain old JSP expressions in the page. For example, let's say you have
a JSF app that is a bookstore. In the app is a managed bean that is a
Map where the keys are ISBN numbers and the values are Book JavaBeans
that have properties like author, title, ISBN, etc.
In JSF 1.1, to display any information from the book Map, you had to
use JSF components. In JSF 1.2, you can use plain old JSP ${}
expressions to access this data, like this:
The title is ${books["0072262400"].title}.
Even though books is a managed bean, you can still
access it without JSF.
Keep in mind that you can also access all the implicit objects,
including JSF ones, in this manner. For example, if you wanted to use
EL to get the locale of the current view, you could say:
${view.locale}
As a final example, if you wanted to get the remote user name of the
current user using standard Servlet authentication APIs you could
say:
${facesContext.externalContext.remoteUser}
Basically anything that conforms to JavaBeans naming conventions and
is accessible from the FacesContext or
UIViewRoot can be reached via the EL in this way.
Technorati Tags: edburns
Repost: Using JAAS with JSF
Posted by edburns on March 07, 2006 at 01:33 PM | Permalink
| Comments (13)
The content and ideas in this blog entry are taken from my upcoming
McGraw Hill Osborne book JavaServer Faces: The Complete
Reference, which I am co-authoring with Chris Schalk. In the
book, we have a chapter on Securing JavaServer Faces applications. This
excerpt shows how the extensible design of JavaServer Faces can be used
to allow JAAS to provide authentication to a JSF Web application. JAAS
Authorization with JSF is also covered in the book, but not in this
excerpt.
|
We will conclude this chapter by showing how to enhance the example
application by leveraging the standard security infrastructure of the
Java platform. From its inception, the Java platform has treated
security as a first class concern. Indeed, one of the first benefits of
Java was to securely bring dynamic behavior to web deployed
applications. Over the years, the implementation and API to security
has evolved, but the core principals have improved and become steadily
more secure. Therefore, choosing to build your application managed
security on top of the standard Java security features is a very safe
bet.
A term often applied to Java security is JAAS, which is short for
Java Authentication and Authorization Service. JAAS started out as an
optional package in JDK 1.3 but has become a core part of the Java
platform as of JDK 1.4. As the name implies, JAAS covers the first two
of the three main aspects of security: authentication and authorization.
Let's explore one way to integrate JAAS style authentication and
authorization into the application
Using JAAS Authentication in the example application
While it would certainly be possible to call into the JAAS layer
directly from the example application logic, for example, from the
UserRegistry bean, a more re-usable solution is to encapsulate the JAAS
interface in a custom ActionListener. This approach de-couples the
security completely from your application and takes advantage of the
intended use of the ActionListener extension hook.
The mechanics of providing such an ActionListener are described in
Chapter 11, but let's review briefly here. The first step is to modify
the faces-config.xml file for the example reusable component library so
that it includes the action-listener declaration, as shown here.
<application>
<action-listener>
com.jsfcompref.examplecomponents.util.JAASActionListener
</action-listener>
</application>
Then, leverage the decorator pattern, as described in Chapter 10, to
delegate most of the work to the "real" ActionListener by providing a
constructor that saves a reference to it. Following the constructor,
the processAction( ) method must be implemented, as described below.
private ActionListener parent = null;
public JAASActionListener(ActionListener parent) {
this.parent = parent;
}
public void processAction(ActionEvent event)
throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
UIOutput comp = null;
String userid = null, password = null;
JAASHelper jaasHelper = new JAASHelper();
// Check to see if they are on the login page.
boolean onLoginPage = (-1 != context.getViewRoot().getViewId().
lastIndexOf("login")) ? true : false;
if (onLoginPage) {
if (null != (comp = (UIOutput)
context.getViewRoot().findComponent("form:userid"))) {
userid = (String) comp.getValue();
}
if (null != (comp = (UIOutput)
context.getViewRoot().findComponent("form:password"))) {
password = (String) comp.getValue();
}
// If JAAS authentication failed
if (!jaasHelper.authenticate(userid, password)) {
context.getApplication().getNavigationHandler().
handleNavigation(context, null, "login");
return;
}
else {
// Subject must not be null, since authentication succeeded
assert(null != jaasHelper.getSubject());
// Put the authenticated subject in the session.
context.getExternalContext().getSessionMap().put(JAASSubject,
jaasHelper.getSubject());
}
}
parent.processAction(event);
}
The first thing to note is that part of the usage contract for
JAASActionListener is the requirement that the username and password
components be nested inside a UIForm named "form", and be named "userid"
and "password" respectively. This expedient measure allows the
JAASActionListener to easily extract the user-provided values for
username and password so that they can be passed on to the JAASHelper
class. The second thing to note about the usage contract is the
requirement that the application provide a navigation rule for the
outcome "login" that causes the user to be directed to the login page if
the authentication failed. In the failure case, processAction( ) is not
called until after redirecting to the "login" outcome using
NavigationHandler. If authentication succeeded, the Subject is stored
in the session for later access. The java.security.Subject is the Java
class that represents the user to the runtime. (We'll cover Subject in
greater detail in the section on JAAS authentication.) Finally, the
parent processAction( ) method is called to do the normal action
handling. Note that this causes the existing application managed
authentication, as described in Chapter 9, to take place. A production
quality implementation would probably remove the application managed
authentication in favor of using JAAS, rather than just supplementing
it, as we have done here.
Let's examine the JAASHelper class.
public class JAASHelper {
LoginContext loginContext = null;
public JAASHelper() {
}
public boolean authenticate(String userid, String password) {
boolean result = false;
try {
loginContext = new LoginContext("FileLogin",
new LoginCallback(userid, password));
loginContext.login();
result = true;
}
catch (LoginException e) {
// A production quality implementation would log this message
result = false;
}
return result;
}
public Subject getSubject () {
Subject result = null;
if (null != loginContext) {
result = loginContext.getSubject();
}
return result;
}
public static class LoginCallback implements CallbackHandler {
private String userName = null;
private String password = null;
public LoginCallback(String userName, String password) {
this.userName = userName;
this.password = password;
}
public void handle(Callback[] callbacks) {
for (int i = 0; i< callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(userName);
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(password.toCharArray());
}
}
}
}
}
The authenticate( ) method uses the class
java.security.auth.login.LoginContext to perform the login. The login(
) method of this class will throw a LoginException if the login fails
for any reason. This exception is caught by authenticate( ) and it
responds by setting result to false. false. If no exception is thrown,
result is set to true. authenticate( ) ends by returning the value of
result.
The two arguments to the LoginContext constructor are the most
important part of this example. The first, the literal string
"FileLogin", refers to an implementation of the
javax.security.auth.spi.LoginModule interface. This interface is
implemented by a provider of a particular implementation of
authentication technology, for example JNDI, LDAP, or database. In this
example, we use a free software implementation called "tagish" that
provides a simple file based authentication scheme. The implementation
comes from John Gardner and can be found at http://free.tagish.net/jaas/.
Providing a LoginModule implementation is beyond the scope of this
chapter, but we must illustrate how to use one, once it has been
provided. This is the beauty of JAAS, the authentication technology
itself is separated from the rest of the system. In other words, if you
want to plug in LDAP, do it by providing a custom LoginModule.
The JVM is made aware of the existence of a LoginModule
implementation either through a -D flag, or via a modification to the
JAVA_HOME/jre/lib/java.security file. In our case, we use
the former option: -Djava.security.auth.login.config==
D:/Projects/example/chapterCode/ch14/example/src/resources/tagish.login
Note the use of forward slashes instead of the standard Windows
backslashes. Also note the "==" instead of just one "=". The format of
this file is prescribed by JAAS:
FileLogin
{
com.tagish.auth.FileLogin required
pwdFile="D:/Projects/example/chapterCode/ch14/example/src/resources/passwd";
};
The FileLogin identifier must match the argument to the LoginContext
constructor. The first element inside the FileLogin declaration is the
fully qualified class name of the class implementing LoginModule. In
our application, we have bundled tagish.jar, which contains this class,
into the WEB-INF/lib directory of the application. The required flag
tells the system that the login must succeed, and whether it succeeds or
fails, the login must still proceed down the LoginModule chain. Other
valid values for this flag are requisite, sufficient, and optional and
are described in the javadocs for the class
javax.security.auth.login.Configuration. The pwdFile argument is an
implementation specific parameter to the code in tagish.jar that tells
it where to find its password file. The format of this file is also
implementation specific and for the example app looks like this:
username:MD5 Hash Of Password:group*
The specific file for the example follows:
# Passwords for com.tagish.auth.FileLogin
jfitness:5a64edabc9358c603103053a3c600a88:user
stiger:40be4e59b9a2a2b5dffb918c0e86b3d7:user
guest:084e0343a0486ff05530df6c705c8bb4:user
jake:1200cf8ad328a60559cf5e7c5f46ee6d:user:manager
Obviously, a simple MD5 hash of the password is not at all secure and
a production quality implementation would use an actual encryption
algorithm. For the purposes of security, MD5 is just as secure as
Base64 encoding, described earlier in the chapter, which is to say, not
at all secure. A handy MD5 hash calculator can be found at
http://bfl.rctek.com/tools/?tool=hasher. Note that user jake is a
member of the user and manager groups, while all the other users are
simply members of the user group. Groups will come into play in the
next section.
The second argument to the LoginContext constructor is an
implementation of the javax.security.auth.callback.CallbackHandler
interface. The LoginCallback implementation saves the username and
password ultimately originating from the userid and password components
in its constructor and uses standard boilerplate code to propagate them
to the JAAS system.
|
Technorati Tags: edburns
Repost: Bringing Ruby on Rails's Flash to JSF
Posted by edburns on March 01, 2006 at 12:20 PM | Permalink
| Comments (5)
With the demise of the Sun Engineer's Sandbox, my content posted there has disappeared. Thankfully I saved a copy. Thanks to srcerer on the ##jsf chat room on freenode for reminding me to repost this.
Overview
To celebrate the release of Ruby on Rails (RoR) 1.0, I have taken the
flash
concept from Rails's ActionController and brought it to
JSF. For those unfamiliar with RoR or the flash, the flash is basically
a map whose entries have a finite, container enforced lifetime. The
concept is familiar; it's the same old "scope" concept used in the
"request", "session" and "application" classes in the Servlet spec. The
point of the flash is to hold information you discover on this
request, that you want to use on the next request, but want to be
forgotten after the next request is finished
Figure 1 is a cheesy graphical depiction of the request, flash,
dialog, session, and application scopes.

The nice thing about these scopes is that they all have a Map into
which you can stick things. These Maps have the special property that
they will be cleared when the scope ends. In the case of the flash, the
map is cleared after exactly two runs through the JSF request processing
lifecycle.
I included Shale's Dialog
concept for good measure since I believe this concept is important to
the future of JSF For example, it's so important that JBoss Seam also
provides a similar concept. A Shale dialog or Seam conversation is
a scope whose length is determined by the application developer.
Background
Of course, I needed a release-vehicle for this thing so I created a
new glassfish
sub-project on java.net called jsf-extensions. My
intent is to use this project for a number of extensions to the core jsf
implementation. The flash is just the first the first that is ready for
public use. Others in the works include:
A completion and implementation of Jacob Hookom's JSF
Avatar proposal
A generalization of the Sun JSF implementation's JSP
tag library generator. This tool is used in the Sun
implementation to generate the TLD and tag handlers for the
html_basic taglib from the existing standard JSF component
metadata in the standard-html-renderkit.xml file.
The idea is to generalize this tool so it can be used to
generate the taglib for any JSF component.
A generalization of the PhaseListener
approach used in the Sun
Blueprints Solutions Catalog AJAX components to serve up
JavaScript files so that it can serve up any file out of a
component jar. This problem is solved in MyFaces using the Extensions
Filter but a PhaseListener is a more self-container
approach. This problem is also solved by the Weblets Project
but personally I don't think the problem of loading resources
is big enough to warrant an entire top-level project. Also,
weblets has extra XML configuration steps that simply are not
necessary if you use the PhaseListener approach.
But enough about the future of jsf-extensions, let's
quickly examine how to use the flash by examining the sample war
included in the jsf-extensions download.
Getting Started
Download and unpack the jsf-extensions
download.
Download a recent build of glassfish, I used Build
31.
Start it up by going to the bin directory and
running:
./asadmin start-domain domain1
Then deploy the sample app by executing:
./asadmin deploy --user admin --password adminadmin ~/jsf-extensions-1.0alpha1/wars/run-time-test-0.1.war
Of course, you need to adjust your path to the war accordingly. The
app will then be accessible at http://localhost:8080/run-time-test-0.1/.
This will take you to an index page where you should click on the "Ruby
on Rails-style Flash" link.
App Traversal
This app illustrates using the Flash from JSP. It is also possible
to use the flash directly from Java Code, or via the EL API. These
latter two methods are described in the JavaDocs.
As you may know from Jennifer
and Pierre's article on the Unified EL, JSF expressions can be
accessed in a "get" context, or a "set context", otherwise known as
"rvalue" or "lvalue", respectively. Thefore, the EL Expression
#{flash.foo} will store a value into the hash under the key
"foo" when evaluated as an lvalue, while it will retrieve the value
under key "foo" from the flash when evaluated as an rvalue.
In JSP pages, most expressions act as rvalues, whereas the lvalue
behavior does not occurr until the form is submitted and the values
entered by the user are stored into the expressions. However, to make
it easier to set expression values from JSP, including setting into the
flash, the jsf-extensions library includes the jsfExt:set
tag. A simple usage of this tag found on the first page in the sample
app, flash.jsp, is shown below.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>RoR Flash Test Page 1</title>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions" %>
</head>
<body>
<f:view>
<h:form id="form1">
<h:panelGrid columns="2" border="1" width="600">
Store into the flash when rendering this page
<jsfExt:set var="#{flash.foo}" value="fooValue" />
Value of <code>\#{flash.foo}</code>, should be <code>null</code>.
<h:outputText value="#{flash.foo}" />
<h:commandButton value="reload" />
<h:commandButton value="next" action="next" />
</h:panelGrid>
</h:form>
</f:view>
</body>
</html>
|
We're using the panelGrid tag (in way we not possible before JSF 1.2,
due to the problems pointed out in Hans
Bergsten challenge) to lay out the contents in a simple two column
table. The first row shows the use of the jsfExt:set tag
to store a value into the flash. The second row shows how to get things
from the flash. When viewing this page the first time, you won't see
anything in the "Value of #{flash.foo} row" until you press the "reload"
button in the page. This is because the normal use-case of the flash is
to store things in this request that will be accessed on the next
request.
If you want to store something in the flash for use on this request,
click on the "next" button in the sample app for an example. In this
page we use the "flash.now" syntax, shown below in JSP.
<jsfExt:set var="#{flash.now.bar}" value="barValue" />
<h:outputText value="#{flash.now.bar}" />
|
By inserting the special keyword "now" we tell the flash that this
store operation should be accessible on this request, rather than the
next request. If, during processing, you decide you want to promote the
value from flash.now to the real flash, use "flash.next" as shown on the
next page of the sample app.
<f:verbatim>
<jsfExt:set var="\#{flash.now.buckaroo}" value="banzai" />
</f:verbatim>
Value of <code>\#{flash.now.buckaroo}</code>, should be
<code>banzai</code>.
<h:outputText value="#{flash.now.buckaroo}" />
Promote buckaroo to stick around for the next request.
<jsfExt:set var="#{flash.keep.buckaroo}" value="#{flash.now.buckaroo}" />
|
When you click on the next button, you will be shown a page that
shows that the value in the flash has indeed survived the postback.
Show that buckaroo is still here.
<h:outputText value="#{flash.buckaroo}" />
|
This is a brief introduction to using the flash, a more in-depth
article would cover a common real-world use-case, such as doing
master-detail, and also cover the other two entry points to using the
flash, the EL API, and direct programmatic use.
Technorati Tags: edburns
|