The Source for Java Technology Collaboration
User: Password:



Ed Burns's Blog

Community: Java Enterprise Archives


Most detailed JSF 2.0 reader: Manfred Riem

Posted by edburns on June 20, 2008 at 10:01 AM | Permalink | Comments (0)

At JavaOne 2006, Dennis Byrne shared with me an intimate fact that I'll now share with you: his Christmas 2005 wishlist included "a bound printout of the JSF 1.2 spec". He got his wish and went on to become a star committer to the MyFaces project. Dennis certainly gets the "most touching reading of the JSF spec" award. However, the award for "most detailed reading of the JSF spec" clearly goes to Manfred Riem, creator of the Manor 'n Rock JSF Components . Mr. Riem read the spec with a fine toothed comb and filed 50 issues in the issue tracker! Thanks Manfred. I owe it to you to fix every one.



JSF Usage and JSF 2.0 Update

Posted by edburns on November 06, 2007 at 08:35 AM | Permalink | Comments (3)

Graphical Indicators of JSF Usage

Graphical Indicators of JSF Usage

From time to time, the JSF team at Sun surfs around a bit looking for new Internet sites using JSF. This time, my colleague Roger Kitain discovered that Virgin Megastore is a JSF User.

Within Sun, we have an elevator pitch-like slide deck about JSF, and the most important slide therein is at the left. If you want more details about the sites pictured, or you want to add some more sites to the list using JSF, the wiki page is <http://wiki.java.net/bin/view/Projects/RealWorldJSFLinks>.

By way of update on JSF 2.0, Jacob Hookom, the developer of Facelets and JSF Expert Group member, is leading the drive toward our number one goal for JSF 2.0: Making custom components easier to develop. We're expecting an EG-private proposal from Jacob this week. Once we get it firmed up we'll share it publically in an Early Draft Review of the spec. In other JSF 2.0 news, we have provisionally closed on the issue of resource loading, as listed in [115-CompResources]. This will also be in the EDR.

Technorati Tags:

Swiss JSF User Group Formed

Posted by edburns on August 01, 2007 at 10:56 AM | Permalink | Comments (0)

Because I was presenting MCP at the first ever Jazoon conference, my friend and expert JSF Developer Alexander Jesse invited me to speak at the first ever JSF User Group meeting. The meeting was held at a Credit Suisse office in Zürich on the evening of the last day of the Jazoon conference.

Credit Suisse is the largest financial institution to go public with its investment in JSF, though I have it on good authority that Deutsche Bank, and Oesterreichische Kontrollbank also have made significant investments in JSF. Mr. Jesse's presentation at Jazoon detailed how Credit Suisse has achieved significant advances in developer productivity, UI uniformity, and maintainability by creating a custom JSF component library specific to the needs of Credit Suisse IT developers. Mr. Jesse printed up flyers announcing the JSF user group meeting and these were distributed in the Sun and Credit Suisse booths in the exhibitor area, as well as at every one of the five JSF related presentations at Jazoon.

The primary goals of this inaugural meeting was to decide if there was a need for a JSF user group in Switzerland, should the group be a special interest group (SIG) within JUGs or a standalone group, and how often should the group meet. Secondarily, Mr. Jesse and I would present some fun technical content, not found anywhere else at Jazoon.

The slides from the meeting can be found here:

We had about 22 people attending the meeting, about half of whom had heard of it from the conference. The response was enthusiastic. Alexander's notes from the meeting can be found at his blog, at <http://ajesse.wordpress.com/2007/07/12/jsf-usergroup-ch-meeting-1/>.

Please leave a comment on this blog if you're interested in the next meeting.

Technorati Tags:

Vacation: Backwards Compatibility Story

Posted by edburns on July 25, 2007 at 03:40 PM | Permalink | Comments (1)

Back in college I spent many hours of my copious Freshman year free time playing LHX on Will Day's PC. At the time, all I had was an Apple //c, which was already behind the times by then. As you can read in the Wikipedia entry, this was a flight simulation game. The thing I remember most was the "missle-cam" view, where you could fire a TOW missle and then switch to the missle's eye view, where you controlled the missle until it hit the target. Well, during my recent vacation, I decided to see if I could find a way to play it on a current computer. Sure enough, the thing still runs unmodified. No emulator or anything.

As we're starting up JSF 2.0 I'll keep this runtime backwards compatibility firmly in mind as I corral debate and discussion on new features.

Technorati Tags:

Testing Ajax Apps with JUnit

Posted by edburns on May 04, 2007 at 01:47 PM | Permalink | Comments (0)

JavaOne is practically here, so I thought I'd give a preview of one of the sessions I'm on next week. This one is close to my heart, BOF 6825 Testing Web 2.0 Features, Using Real-World Applications. I'll be talking about using The Mozilla Control Program (MCP) to write an automated test that exercise an Ajax application. Big deal, right? Well, yes because MCP enables you to make assertions about the actual Ajax transactions, and also allows you to access the browser DOM using the plain old W3C DOM API in Java.

To make this easy, I've recorded an Elluminate screencast showing MCP in action testing the Dynamic Faces and jMaki sample application. If you're a Sun employee and you choose not to view this screencast just because I'm making you use JavaWebStart to view it, please tell me so I can report you to the "eating our own dogfood" police.

To view the screencast, click here.



Compilllers are Helpful

Posted by edburns on March 12, 2007 at 09:11 AM | Permalink | Comments (2)

When working to revive Webclient as a means to enable one to write automated tests for Ajax Applications, I ended up fixing some thread safety assertions that were failing in native code. Part of this involved slightly recrafting the design of the native/Java DOM bridge, originally written over seven years ago by Igor Kushnirsky. Igor's original design had lots of public native methods. My problem was that I needed these methods to have their native code executed on a particular thread. However, the DOM methods can be called from any old thread in the application. Webclient already does this with an internal NativeEventThread class. All webclient methods that end up in native code happen on that thread. Basically, I had to go through the Java DOM code and turn this:



public native Element getElementById(String elementId);

into this:



public Element getElementById(String elementId) {
  // Make this happen on the NativeEventThread.
  return nativeGetElementById(elementId);
}
native Element nativeGetElementById(String elementId);

Of course, I would have to modify the function names in the native C++ source files as well.

In case you were wondering, I did consider these solutions but rejected them.

Use Javier Pedemonte's Java XPCOM bridge
I plan to completely rewrite the mozilla layer of webclient and dom to use this most excellent software after I get the 2.0 release done. I don't have time for that extensive rewrite now.
Use aspect oriented programming techniques
Sure, I could do this, but I don't want to introduce another dependency on another technology.

That said, I wrote some xemacs macros as I went along and it only took a couple hours of manual editing. While doing it, I re-compiled all along the way. Naturally, the compiler caught some things, which I easily fixed, as I went along.

This got me thinking. Say this code was written entirely in a scripting language. If so, this sort of "complicated, human-assisted global search and replace" change (I won't call it refactoring since this particular process was so specific to JNI) would be really error prone and hard to debug. The absence of a type checking compiler would really make this sort of change hard.

I assert that this sort of change is happens all the time in the maintenance phase of a large software project. I assert that the person making the change is seldom the same person who wrote the code originally. Given these assertions, I predict much woe for the maintenance programmer who has to do such a change on a scripting language based project. I continue to urge caution for those listening to scripting zealots when they consider moving more of their projects to scripting languages.

Technorati Tags:

##jsf irc channel usage

Posted by edburns on January 19, 2007 at 12:03 PM | Permalink | Comments (0)

Because JavaServer Faces technology is delivered by Sun as a part of the Java EE SDK and also Project Glassfish, the Sun JSF team strongly feels that community is important. To that end, I've been plugging the use of the ##jsf irc channel on irc.freenode.net as a community resource. My team and I try to maintain a daily presence in the channel. Since we started hanging out there, we've seen the daily traffic steadily grow.

Now that over a year has passed, I thought it would be fun to throw in a graph. Here is a chart of the daily log size for the ##jsf channel, where each data point is a weekly average of the size, in bytes, of the daily log file. The first datapoint in the x axis is from the fourth week of 2006, on up to today.

If you want to join the channel, please see the instructions at the JSF main site.

graph.jpg

Many thanks to Geert Bevin who, very graciously and professionally provides the log bot on the channel.

Technorati Tags:

Adding Dynamic Faces Support to a jMaki widget

Posted by edburns on December 07, 2006 at 09:09 AM | Permalink | Comments (1)

In this entry, I show how I added Dynamic Faces support to the Dojo Inline Editor widget in jMaki.

Background and History

If you've read my blog before, you know that I think JSF is a good fit for handling the motherhood and apple pie requirements of web applications. What you may not know is that jMaki intentionally leaves the work of satisfying these requirements as an exercise for the developer. No problem, just use jMaki and JSF together. This is indeed a valid answer, but there is a subtlety that bears clarification.

When using jMaki + JSF under J2EE 1.4 (the default target audience for jMaki), you miss out on the following features:

  • Ability to have the jMaki widget POST back to the faces page while preserving the JSF view state.

  • Ability to use jMaki widgets that represent components that accept user input within an iterating component such as dataTable.

  • Ability to attach valueChangeListeners to jMaki components in the view.

  • Ability to attach converters and validators to jMaki components in the view.

  • Ability to attach action and/or actionListeners to jMaki components in the view.

These deficiencies stem both from missing features in the built-in jMaki JSF support and from missing features in JSF 1.1 commonly used with J2EE 1.4.

The story about jMaki and Dynamic Faces

By using jMaki with Dynamic Faces on top of JavaEE 5, however, all of these deficiencies can be addressed (with the exception of the last two, and issues have been filed for these features). This section discusses how using jMaki and Dynamic Faces addresses all of the deficiencies mentioned above.

Ability to have the jMaki widget POST back to the faces page while preserving the JSF view state.

This is the big one, and it was at the heart of the JavaOne presentation in which I participated. The lack of this feature in many Ajax + JSF solutions is what prompted us to title the session, "Ajax done right". When you do not have the JSF view state, you cannot do any of the things that JSF does well. Including the JSF View state in the Ajax transaction is essential.

By using Dynamic Faces to send and receive Ajax transactions from the browser to the JSF view, the JSF view state is correctly preserved, allowing the entire JSF lifecycle to be used, including conversion, validation, events, etc.

Ability to use jMaki widgets that represent components that accept user input within an iterating component such as dataTable.

This one is near and dear to Jacob Hookom's heart. Not only do you need the JSF view state, but you need a way to apply individual values to an individual components within a composite component (such as a table or tree). This capability did not exist in JSF until version 1.2, and Dynamic Faces takes full advantage of it.

Ability to attach valueChangeListeners to jMaki components in the view.

This didn't exist in jMaki until issue 3 was fixed. However, even though you can add a valueChangeListener to a jMaki component now, you still need to preserve the JSF view state in order for it to ever have a chance of being invoked. Again, Dynamic Faces is the answer.

Ability to attach converters and validators to jMaki components in the view.

Ability to attach action and/or actionListeners to g jMaki components in the view.

As with valueChangeListener, these two need to be first implemented in jMaki, then they need to be used with Dynamic Faces.

How To

The whole point of jMaki is to put today's hot JavaScript widget libraries in the hands of Java web application developers. Each widget library has different ways of doing things, and indeed, each widget within each library does too. jMaki solves this by having specific files with each widget. Therefore, adding Dynamic Faces support to each widget involves making some modifications to the widget specific files. Currently, the only widgets that have been modified are the Dojo FishEye and Inline Editor, and the Scriptaculous Inplace Editor. This section shows some high level guidelines for how to add Dynamic Faces support to an arbitrary jMaki widget.

The widget specific files for a jMaki widget are:

File Name Purpose
component.css Any CSS style associated with an instance of this widget.
component.htm The markup that will be included in the page an instance of this widget.
component.js The JavaScript adapter file for this widget. This adapts between the widget library specific way of doing things and the jMaki server side framework. This is also the easiest place where Dynamic Faces support can be added.
widget.json Any name/value pairs that aid in the configuration of an instance of this widget.

In general, you'll probably just need to modify component.js to add Dynamic Faces support. Please follow Jennifer's Tutorial for how to get started with jMaki and Dynamic Faces. Once you've done that, you need to make sure to include the Dynamic Faces taglib and script tag in the page on which you are using the jMaki widgets.

Syntax highlighting courtesy of http://www.nopaste.com/.

Listing 1, the JSP Page

  1. <%@ taglib prefix="a" uri="http://java.sun.com/jmaki-jsf" %>
  2. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
  3. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
  4. <%@ taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions/dynafaces"%>
  5.  
  6. <h2>Editor Using JSF</h2>
  7.  
  8. <f:view>
  9.  
  10. <jsfExt:scripts />
  11.  
  12. <h:form prependId="false">
  13. <h:dataTable id="table" rows="10" binding="#{ResultSetBean.data}"
  14. value="#{ResultSetBean.list}" var="customer">
  15.  
  16. <h:column>
  17. <f:facet name="header">
  18. <h:outputText value="Account Id"/>
  19. </f:facet>
  20. <h:outputText id="accountId"
  21. value="#{customer.accountId}"/>
  22. </h:column>
  23.  
  24. <h:column>
  25. <f:facet name="header">
  26. <h:outputText value="Customer Name"/>
  27. </f:facet>
  28. <a:ajax name="dojo.inlineedit" value="#{customer.name}" />
  29. </h:column>
  30.  
  31. <h:column>
  32. <f:facet name="header">
  33. <h:outputText value="Symbol"/>
  34. </f:facet>
  35. <h:outputText id="symbol"
  36. value="#{customer.symbol}"/>
  37. </h:column>
  38.  
  39. <h:column>
  40. <f:facet name="header">
  41. <h:outputText value="Total Sales"/>
  42. </f:facet>
  43. <h:outputText id="totalSales"
  44. value="#{customer.totalSales}"/>
  45. </h:column>
  46.  
  47. </h:dataTable>
  48.  
  49. </h:form>
  50.  
  51. </f:view>
  52.  

Line 4 has the taglib for Dynamic Faces, line 11 uses the scripts tag. Line 29 has the use of the jMaki ajax component.

Let's take a look at the component.js for the Dojo Inline Edit widget, before Dynamic Faces support was added.

Listing 2, the component.js before Dynamic Faces is added

  1. dojo.require("dojo.widget.*");
  2. dojo.require("dojo.widget.InlineEditBox");
  3. dojo.require("dojo.event.*");
  4.  
  5. var container = document.getElementById(widget.uuid);
  6. var w = dojo.widget.createWidget(container);
  7.  
  8. w.getValue = function() {
  9. return w.textValue;
  10. }
  11.  
  12. // add a saveState function
  13. if (typeof widget.valueCallback != 'undefined') {
  14. w.onSave = function(newValue, oldValue) {
  15. // we need to be able to adjust this
  16. var url = widget.valueCallback;
  17. dojo.io.bind({
  18. url: url + "?cmd=update",
  19. method: "post",
  20. content: { "value" : newValue },
  21. load: function (type,data,evt) {
  22. // do something if there is an error
  23. }
  24. });
  25. }
  26. }
  27. w.saveState = w.onSave;
  28. jmaki.attributes.put(widget.uuid, w);

On lines 1 - 3 we have the dojo includes: uninteresting. Line 5 of listing 2 is interesting. The "widget" refererred to is this instance of this widget in the page. In this case, it's the widget on line 29 of Listing 1. However, keep in mind that line 29 of listing 1 is inside of a dataTable, therefore, there will be 10 instances of this widget in the page, each corresponding to an actual JavaScript object in the JavaScript VM. Therefore, the value of widget.uuid will be different for each widget, and will, most importantly, correspond to the JSF Client Id for the widget in the JSF view. This is important because in order to address the widget in the JSF view, you need its client id.

For example, the widget.uuid values for this page happen to be table:n:j_id_id34 where n is the numbers 0 to 9.

Returning to line 5 of listing 2, the actual DOM element returned by the call to document.getElementById is what jMaki renders based on the content of the component.htm file. For the dojo inline editor, this file is:

  1. <div id="${uuid}" dojoType="inlineEditBox" class="dInlineEdit">${value}</div>

The jMaki AjaxWrapperRenderer will cause the component.htm file to be rendered like this in the page from listing 1.

  1. <div id="table:0:j_id_id34" dojoType="inlineEditBox" class="dInlineEdit">name_0</div>

Therefore, when line 5 of listing 2 executes, the value of container is the div element with id table:n:j_id_id34, where n, of course, is the current row in the table.

Line 6 of listing 2 uses the dojo createWidget to create an instance of the inline edit box inside of the container element.

Lines 14 - 25 of listing 2 declares the JavaScript function that will be called when the user presses the "save" button in the widget UI.

Now, let's take a look at the changes to component.js necessary to add Dynamic Faces support, expressed as a diff.

Listing 3, the diffs to component.js to add Dynamic Faces support

  1. --- component-pre-DF.js 2006-12-07 10:32:25.000000000 -0500
  2. +++ component.js 2006-12-07 10:31:19.000000000 -0500
  3. @@ -12,6 +12,16 @@
  4. // add a saveState function
  5. if (typeof widget.valueCallback != 'undefined') {
  6. w.onSave = function(newValue, oldValue) {
  7. +
  8. + if (typeof _globalScope.DynaFaces != 'undefined') {
  9. + DynaFaces.fireAjaxTransaction(container,
  10. + {
  11. + execute: widget.uuid,
  12. + render: "none",
  13. + postBody: widget.uuid + "=" + newValue
  14. + });
  15. + }
  16. + else {
  17. // we need to be able to adjust this
  18. var url = widget.valueCallback;
  19. dojo.io.bind({
  20. @@ -22,7 +32,8 @@
  21. // do something if there is an error
  22. }
  23. });
  24. + }
  25. }
  26. }
  27. w.saveState = w.onSave;
  28. -jmaki.attributes.put(widget.uuid, w);
  29. \ No newline at end of file
  30. +jmaki.attributes.put(widget.uuid, w);

The only change is a conditional within the onSave function. jMaki defines a _globalScope global variable that allows you to access all things globally defined in the page. It so happens that the scripts included by virtue of line 11 of listing 1 define a global variable called DynaFaces. This JavaScript object has all the functions exposed by the Dynamic Faces JavaScript library. Therefore, you can safely test for the existing of Dynamic Faces in a page as shown on line 8 of listing 3. If Dynamic faces is not being used in the page, then the normal jMaki operation of the widget takes place, as shown on lines 17 - 23 of the diff.

Lines 9 - 14 of listing 3 cause a Dynamic Faces Ajax transaction to be made back to the JSF page currently being viewed in the browser. This transaction includes all the view state for the current f:view. The first argument to fireAjaxTransaction is the DOM element from which the transaction should be fired. It is important that this be the DOM element that corresponds to the actual JSF UIComponent in the view. The second argument to fireAjaxTransaction is a JavaScript associative array. In this case, we're saying three things:

  • do the 'execute' portion of the JSF lifecycle just on the JSF UIComponent for this widget instance.

  • do not re-render anything to the browser (in this case, Dojo handles it).

  • In the HTTP POST body of the request, include the name value pair for the currently entered value of the widget.

Note that newValue, on line 6 of listing 3, is an argument to the onSave function. It is the new value entered by the user.

For more information on the JavaScript functions exposed from Dynamic Faces, see the Dynamic Faces Reference.

Summary

jMaki gives you cool widgets. Dynamic Faces + jMaki gives you cool widgets you can use in a real enterprise web application.

Technorati Tags:

(near) Zero (re-)Deployment Time for JSF

Posted by edburns on December 01, 2006 at 06:52 PM | Permalink | Comments (4)

One oft cited complaint about Java Web Applications is the slow and laborious deployment step. This step seriously undermines the ability to get into a flow state and is generally a major buzz kill. The absense of a deployment step is one reason why people like Ruby on Rails so much.

JSF-Extensions Design Time brings good news for flow-impaired Java Web application Developers: the JMX PhaseListener.

The implementation of this was really simple. I just took Jean-Francios Arcand's JMXDeploy class, modded it ever so slightly, as you can see in the source code, and called it from a PhaseListener.

I did a screencast about it too.

Technorati Tags:

Motherhood, Apple Pie and Web apps

Posted by edburns on November 13, 2006 at 08:35 AM | Permalink | Comments (2)

In my recent spate of speaking engagements, I have been including a "motherhood and apple pie" slide in my presentations about JSF and Ajax. I put this in my slides in response to a question I sometimes hear when I make the case for JSF and Ajax. The question goes something like this:

Hey, why do I need JSF, or any other server side framework for that matter? With Ajax, or things like GWT, can't I just put it all in the client? I mean, let's just do everything in JavaScript!

You're welcome to do that, but if you do, please know that you'll have to do all of these things yourself. Screen capture of slide showing basic requirements of web apps As you may guess, JSF already does all of these for you, does them quite well, and does them in a way that is an industry standard, with the brainpower of leading minds from Oracle, Sun, IBM, Apache, the Open Source Community, and others.

This is why I have been spending my spare time trying to get Project jMaki to have first class support for JSF as a core part of its feature set and value proposition. In fact, if you support this idea, please send an email to the jMaki User list saying that you think this is important. For some exmples of this in action, please see here, here, here, and here.



Ed Burns Upcoming Speaking Engagements

Posted by edburns on September 08, 2006 at 08:32 AM | Permalink | Comments (0)

I'm currently cooking up two presentations about Ajax and JSF. Once they're fully baked, I'm taking them on the road! Of course, while on the road I'll be promoting my first book, JavaServer Faces: The Complete Reference. This book can be referenced from http://purl.oclc.org/NET/jsfbook/. Here are the stops on my fall 2006 tour.

At each of these engagements I'll be presenting one or two of the following two talks.

Enterprise Grade AJAX with JSF

This presentation will demonstrate how JSF and AJAX are perfect together. We begin with an insight into the design heritage of JSF, and how that heritage puts JSF in good stead to be productive in the AJAX world. Building on that foundation we dive into the code from the page author and component developer's perspective. We close with a look to the future of JSF.

Scripting JSF

The benefits of scripting languages for web development are well known. Python, Ruby, Perl, and other languages came to prominence largely due to their suitability for web development. With the inclusion of JSR 223 in the Java platform, Scripting will be fully supported. This presentation will present some trends for using Scripting to develop applications for Java EE.

I hope to meet lots of people and learn how you all are using JSF. If you're not using JSF, maybe I can find out why so we can fix it.

Technorati Tags:

Introducing Project Dynamic Faces

Posted by edburns on August 30, 2006 at 09:41 AM | Permalink | Comments (6)

After a few months of steady improvements, we're ready to announce an early access release of Project Dynamic Faces (DynaFaces). The project homepage is <https://jsf-extensions.dev.java.net/>. This page has live demos of DynaFaces in action.

This project is being developed in Open Source, using the OSI approved CDDL license. Your contributions and bug reports are very welcome!

Please visit the Slides and Screencasts page for an introductory presentation, and a screencast of that presentation, including demos.



I'm Lucy van Pelt this week.

Posted by edburns on August 15, 2006 at 09:11 AM | Permalink | Comments (0)

This week, my colleague Roger Kitain and I are sitting in the virtual advice booth, however, instead of doling out psychiatric help we're answering JSF questions.

Please stop by at http://java.sun.com/developer/community/askxprt/ and ask some questions.

My community support time that I normally spend on the JSF IRC channel is consumed with these questions this week, so you probably won't see me on the channel this week. However, other weeks please visit the channel and you can chat with me directly.

Technorati Tags:

JSF on Maven: refresh

Posted by edburns on July 18, 2006 at 12:33 PM | Permalink | Comments (1)

With the help of Kohsuke Kawaguchi's most excellent maven repository importer ant task, and several iterations of trial and error, we now have the JSF 1.2 and 1.1 api and impl jars available under the same license as Glassfish on the java.net maven repository.

Put this in your project.properties or build.properties:

maven.repo.remote=https://maven-repository.dev.java.net/nonav/repository/,http://www.ibiblio.org/maven/

    groupId: javax.faces

    artifactId: jsf-api

    artifactId: jsf-impl

    available versions: 1.1_02, 1.1_03-SNAPSHOT, 1.2, 1.2_01_B04, 1.2_01-SNAPSHOT

I have also updated the POMs. If you're a JSF developer with committer access, please update the pom file in the source tree if you want to be more officially recognized.

Technorati Tags:

JSR 252 Gantt Chart Video

Posted by edburns on June 16, 2006 at 09:17 AM | Permalink | Comments (2)

See the video here.

JavaOne Video: AJAX DONE RIGHT

Posted by edburns on May 31, 2006 at 11:15 AM | Permalink | Comments (7)

If you really want, you can skip the prose and go straight to the video. However, if you do, you'll miss out on where to download the demos.

This was an interesting JavaOne for me because I was in a funny position with respect to my talk. I had submitted a proposal for a JavaOne talk when the call for papers went around. JSF EG members Jacob Hookom and Adam Winer submitted a similar talk, unbeknownst to me. The JavaOne paper review team suggested we collaborate on a talk, and, since we were already collaborating informally on ideas, it was no problem to collaborate on a talk. But speaking of collaboration...

With AJAX being hot and new and all, everyone wants to get a piece of the pie, do something cool, and get famous. (I'm certainly no exception). With all of these chefs in the kitchen, approaches to AJAX are bound to overlap and in come cases conflict. I had been working with the Sun Blueprints team on their AJAX components, and some of the ideas we developed in those components have been picked up and extended by Shale Remoting. Meantime, Greg Murray had been working on his jMaki project. Then there's Jonas Jacobi and John Fallows and their weblets thing they have in their book. There is also ICESoft's icefaces and Exadel's ajax4jsf. Finally, there are a lot of ideas bobbing around on the myfaces dev list, some of them from my co-speakers Adam and Jacob. Clearly, there is a need for some community refactoring.

Now, here's the funny part. The approach to AJAX and JSF that Adam and Jacob have been advocating, and that I advocate as well, is different, yet potentially complimentary, to what Greg was doing with jMaki. It also does not align perfectly well with some of the things in Shale Remoting. It fits pretty well with ajax4jsf and I'm not sure really how it relates to icefaces. Now, come JavaOne, here I am standing on stage with Jacob and Adam, and the developers of all the AJAX technologies listed above (and probably more) were in the audience, and our talk was titled, "AJAX Done Right". As if to say, "everyone else is doing it wrong". I wasn't too comfortable with such a confrontational title, but, hey, this is the age of the technology smackdown and all that jazz, so I went along with it.

People tend to take critique of their creations personally, so I want to set the record straight and say that each approach has value and none of them have all the answers for all situations for doing AJAX. That's a good thing because we can harvest all these great ideas in the upcoming JSF 2.0 spec. In the meantime, Jacob and I are putting forward our take on JSF and AJAX in the JavaServer™ Faces Technology Extensions. Project. For more on the future of that project, I'll have an upcoming blog.

Now without further ado, here is the complete video of our talk AJAX DONE RIGHT in Flash Live Video format. Thanks to Dennis Byrne for shooting the video on Adam's camera.

The demo shown in this talk, as well as the demo shown at the Sun Web Tier Pod on the JavaOne 2006 show floor, are available for download here. You'll need to Get Java EE 5 Now or Glassfish to run them.

Technorati Tags:

New release of JSF AJAX Components (Updated)

Posted by edburns on April 20, 2006 at 06:51 AM | Permalink | Comments (14)

Many thanks to my pal Vernon Singleton for handholding me through the process of converting these huge QuickTime files down to much smaller FLV and SWF files. Maybe he'll do a blog on how to do it!

Nearly a year ago, the BluePrints and JSF teams at Sun began to work on the story of how AJAX and JSF would work together. As we began to get into it, we found that these two technologies were very complimentary. We developed and continue to refine techniques for how to use AJAX with JSF.

The landing page for the Java BluePrints AJAX components is: <https://blueprints.dev.java.net/ajaxcomponents.html>

I've recorded a screencast blog for each of the components in the catalog. Please excuse my slow pace of speaking, I'm aware that we have a large contingent of European JSF developers and my tendency is to speak fast American English. Therefore, I made a conscious effort to speak slowly.

These components leverage the Dojo Toolkit and make use of the JSF PhaseListener approach for serving up JavaScript files and handling AJAX requests on the JSF server. This approach was innovated by the Blueprints and JSF teams and generalized in the Shale Remoting library, which these components leverage to great effect.

Technorati Tags:

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:

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:

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:

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:



Java EE SDK Runs ADF Faces

Posted by edburns on February 27, 2006 at 08:15 AM | Permalink | Comments (1)

The saga of Oracle ADF Faces on the Java EE SDK continues. In our last installment, Adam Winer explained why ADF Faces won't run on Glassfish. I'm happy to report that after some minor tweaks to Sun's JSF implementation in the Java EE SDK, I think I have it running. However, I would appreciate any testing people could give to see if the entirety of ADF Faces works. ADF Faces is a large piece of software and their demo app is rather comprehensive. Incidentally, it's also a great testcase for extending JSF and exposed a few bugs which have also been fixed.

Here's how to try it. I'm using the jsf-glasssfish-updater technique described in an earlier blog.

  1. Download and install the Java EE 5 SDK. If you already have JDK 5.0 installed, you can just download Sun Java System Application Server PE 9 Beta. Currently there is no Mac OS X build of the Java EE SDK, but don't despair! Mac Users will have to use Glassfish, the Open Source Application Server from which the Java EE SDK is built. Mac OS X is my main development platform, so I know it works there.

  2. Go to the the nightly download area. If you're running the Java EE SDK Preview, download the jsf-sjsas9pebeta-updater.jar. If you're running Glassfish, download jsf-glassfish-updater.jar

  3. Execute this with the JDK 5 Java interpreter.

    
    java -jar jsf-<glassfish-or-sjsas9pebeta>-updater.jar <PATH_TO_YOUR_ASINSTALL_DIRECTORY>
    

    Where <glassfish-or-sjsas9pebeta> sjsas9pebeta or glassfish, and PATH_TO_YOUR_AS_INSTALL_DIRECTORY is the parent of the lib, bin, domains (and so on) directories.

  4. Download Oracle ADF Faces from Oracle's website. Note, you have to join their developer network to get it.

  5. Unfortunately, ADF Faces appears to have been developed without taking advantage of the benefits of the robust SecurityManager in Java EE 5. Therefore, you'll have to put the following entry in your server.policy file if you want the chooseDate component to work from the adf-faces-demo.war.

    
    grant codeBase "file:${com.sun.aas.installRoot}/domains/domain1/applications/j2ee-modules/adf-faces-demo/WEB-INF/lib/adf-faces-api-SNAPSHOT.jar" {
          permission java.net.NetPermission "specifyStreamHandler";
    };
    

    Of course, you'll have to tweak the entries if you use the components in your apps. Also of note, the Sun App Server team has been debating turning the security manager off by default, so this step may not be necessary in the future.

  6. Make sure any attempts to deploy a previous version of adf-faces-demo.war have been completely removed from the App Server. For example, I have noticed that occasionally the adf-faces-demo directory stick around in domains/domain1/applications/j2ee-modules. I had to manually remove this directory to enable the demo to work.

  7. From the ADF Faces download, deploy the adf-faces-demo.war to your running Java EE SDK App Server and visit the demo to enjoy ADF Faces on Java EE 5!

If you find any bugs when trying the demo please file them on the JSF issue tracker or the Glassfish issue tracker.

Also, note that this version of JSF includes the new invokeOnComponent feature we developed with help from Jacob Hookom and mentioned in his blog. Lastly, the jsf jars in the java.net Maven 1 Repository have been updated as well.

Technorati Tags:

New Drafts of Java EE Web Tier: JSF 1.2, JSP 2.1, Servlet 2.5

Posted by edburns on February 17, 2006 at 12:50 AM | Permalink | Comments (7)

I'm pleased to announce another revision of the Java EE Web Tier. In Jan Luehe's blog you can find out what's new in JSP 2.1 Proposed Final Draft 2 (PFD2). The Change Log for Servlet 2.5 will give you the scoop on the Servlet spec. This blog entry will show what's new in the JSF spec.

In JSF, the most visible new feature since the last draft of the spec is the addition of the invokeOnComponent() method on UIComponent. See below for more details.

This revision of the Java Web Tier is fully implemented in glassfish build 37, Sun's open source Java EE 5 Application Server, and the basis for the upcoming Java EE SDK.

Spec changes since PFD, chronologically by section number

  • 9.5: The TLDDocs for the h: and f: taglibs are now a normative part of the spec.

  • 5.4: Use of JSR-250 Common Annotations @PostConstruct and @PreDestroy for managed bean lifecycle notifications. See my August 2005 blog entry for more on this feature.

  • 3.1.10: Specify how EL ValueExpressions must me handled in the attributes map returned from UIComponent.getAttributes().

  • 5.4: List the supported Java EE 5 annotations one may put in a JSF Managed bean.

    
    @Resource
    @Resources
    @EJB
    @EJBs
    @WebServiceRef
    @WebServiceRefs
    @PersistenceContext
    @PersistenceContexts
    @PersistenceUnit
    @PersistenceUnits
    
  • 2.2.2: Define the term "local value" more concretely.

  • Preface: Added section on backwards compatibility with previous versions of the JSF spec.

  • 9.4.8: Explicitly state that the use and meaning of a UIParameter child is the responsibility of the parent component inside which it is nested.

  • 5.3: State that managed bean properties may be Java enum types. Define coercion rules.

  • 7.1.1: Widen the expected type returned from a UICommand action method to be Object instead of String. This allows the use of Java enum types as returns from action methods, which can simplify navigation rules.

  • 7.3: State that the Action method must return Object.

  • 3.1.8: New method: UIComponent.invokeOnComponent(), and supporting callback interface ContextCallback. This method allows you to execute a callback on an arbitrary node in the view given its clientId. An override is provided for UIData that provides for correctly positioning the table to the proper row before continuing to find the component.

  • 9.3.1.2: Add a note mentioning that tld-version in an explicit taglib def, and version in an implicit taglib def are semantically equivalent with respect to their use in determining the backwards compatability strategy employed.

JSF-API Contract Changes, chronological by