Ryan Lubke's Blog

JSF 2.0 - Bookmarability/View Parameters

Monday May 18, 2009

This seems to be one of the top features users have been requesting for JSF 2.0.  For those of you not reading the specification revisions as it has been published, the feature is available.

Bookmarkability is achieved using two new components:

  • h:link
  • h:button
Both of these components will generate a URL based on the specified navigation outcome.  Keep in mind, that in JSF 2.0, implicit navigation is available, so this outcome can be defined within the view or using standard navigation rules.

So, let's start with a simple example using one of these new components with implicit navigation.  Please note that the following examples assume that the FacesServlet is mapped to '*.xhtml'.
    <h:link outcome="viewEntry" value="Link">
        <f:param name="entryName" value="#{someBean.entry}"/>
    </h:link>
In the example above, outcome, again, is the result of the navigation.  In this case, since we're assuming no navigation rules have been defined in the faces-config.xml, we're navigating to viewEntry.xhtml.  The f:param tag is adding a query parameter to the generated link.  When the component is rendered, the end result is something like:
<a href="http://localhost:8080/myapp/viewEntry.xhtml?entryName=entry1">Link</a>
The same can be achieved using navigation rules defined in the faces-config.xml.  For example:
<navigation-rule>
    <from-view-id>/page1.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>redirectOutcome</from-outcome>
            <to-view-id>/page2.xhtml</to-view-id>
            <redirect>
                <view-param>
                    <name>entryName</name>
                    <value>#{someBean.value}</value>
                </view-param>
        </redirect>
    </navigation-case>
</navigation-rule>

Then reference the navigation outcome in one of the new components:
<h:link outcome="redirectOutcome" value="Link" />
which generates:
<a href="http://localhost:8080/myapp/page2.xhtml?entryName=entry1">Link</a>
Now, there's a third source of parameters that has been introduced in JSF 2.0 called 'View Parameters'.  These parameters are specified as metadata to the page and can be included in the generated URLs.  There's a lot more to view parameters than what is about to be shown.  I'll go more into that later on in this entry. 

Here's a simple example of a View Parameter (assume this is defined within somepage.xhtml):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
<head><title>somepage</title></head>
<body>
        <f:metadata>
            <f:viewParam id="id" name="viewParam" value="#{someBean.id}" />       
         </f:metadata>
         .
         .
</body>
</html>

If the developer sets the 'includeViewParams' attribute on h:link or h:button or the include-view-params attribute on the redirect element of a navigation-case to true, then the UIViewParameters will be a part of the generated URL.

So, building off of the metadata example above, consider the following h:link within another view:
<h:link outcome="sompage.xhtml" value="Link">
    <f:param name="componentParam" value="component"/>
</h:link>
The generated URL would look like:
<a href="http://localhost:8080/myapp/somepage.xhtml?componentParam=component&viewParam=view">Link</a>
Keep in mind that the view parameters that are included in the generated URL will be those of of the view being navigated to.

It's also important to note that there is an order of precedence for adding the parameters from the different sources.  This order is essentially, component, navigation-case parameters, followed by view parameters.  This means that if a component specifies a parameter via f:param that has the same name as that in a navigation-case or in the view metadata, then the parameter value from the navigation-case or view metadata will not be included in the query string.  

Now, getting back to view parameters, there's some other details I'd like to share.  In 1.2, the typical GET lifecycle would result in the restore view phase being invoked immediately followed by render response.  This is still true in 2.0 *except* when the view being processed has view parameters.  In this case, the view parameters are processed using the standard post-back processing lifecycle (i.e. apply request values,  process validations, update model, invoke application, then render response).   Processing view parameters in this fashion allows developers to attach converters and validators to the view parameters to enforce the integrity of the parameter data being passed to the view.  For example:

         <f:metadata>
            <f:viewParam id="id" name="id" value="#{newsReader.selectedStoryId}"
                     required="true"
                     requiredMessage="You did not specify an id. (The id parameter is missing)"
                     converterMessage="Invalid id. (The id parameter is not a number)"
                     validatorMessage="Invalid id. (The id parameter is not a positive number)">
                <f:validateLongRange minimum="1"/>
            </f:viewParam>       
         </f:metadata>


Lastly, developers need not restrict their usage of f:metadata to view parameters only.  Facelets templating features and view events (i.e. f:event) can also be specified.  One useage restriction of f:metadata needs to be kept in mind though - it must be defined within the view and not within a template.  If this restriction isn't observed, the content within f:metadata will not be processed.

That should cover the basics for now.  Please download the Mojarra 2.0.0 nightly and give this feature a shot.  Feel free to ask questions on the GlassFish Webtier forums, and if you think you found an issue, please let us know about it.

[10] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

Custom Managed Bean Scopes

Wednesday Apr 15, 2009

The JSF 2.0 specification has added custom scopes for managed beans.  I think this is something that will be quite useful to extension developers (think homegrown conversation scopes). 

In previous versions of JSF, managed bean scopes were restricted to application, session, request, and none.  JSF 2.0 adds one new custom scope called 'view' which I've touched on in previous blog entries.  But how does support for non-standard scopes work?

It's pretty simple actually.  The custom scope can be referenced in the managed-bean-scope element of the faces-config.xml or via the @CustomScoped annotation.  The value for this scope, in either the xml or annotation case, must be an EL expression that resolves to a Map.

For example, if you reference this custom scope using the 'managed-bean-scope' in xml, it could look something like:

<managed-bean>
   <managed-bean-name>bean</managed-bean-name>
   <managed-bean-class>somepackage.Bean</managed-bean-class>
   <managed-bean-scope>#{customScope}</managed-bean-scope>
</managed-bean>


If you're into using the annotations, then the @CustomScoped annotation might look like:

@CustomScoped(value="#{customScope}")

The managed bean facility in 2.0 will use the expression to resolve the Map that backs the custom scope.  If the Map doesn't already contain the bean, the managed bean facility will create the bean and push it to the custom scope for you.

This new functionality is available as of last night's build of Mojarra 2.0.0.

I've also written a simple example that shows how to write an ELResolver to resolve/manage a custom scope.

UPDATE (April 15, 2009 1:50 PM-ish)

The example has been updated to show how to use the PostConstructCustomScopeEvent and PreDestroyCustomScopeEvent system events.  PreDestroyCustomScopeEvent is particularly import for custom scope authors to publish if they want managed bean methods annotated with @PreDestroy to be invoked.

[5] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

Faces-config.xml? ... We don't need no stinkin' faces-config.xml!

Tuesday Mar 03, 2009

The new feature set of JSF 2.0 makes the life of the faces application developer much easier.

First, annotations.  I'm sure some of you have already read up on the annotations added in 2.0, so I'll only touch on them briefly here. 

  • ManagedBean (this includes ManagedProperty and the scope annotations)
  • FacesConverter
  • FacesValidator
  • FacesComponent
  • FacesRenderer
  • ResourceDependency
  • ResourceDependencies
  • FacesBehavior
  • ListenerFor
  • ListenersFor
In particular using ManagedBean, FacesConverter, FacesValidator, and FacesRenderer allows the developer to skip editing the face-config.xml.

The other common complaint with the faces-config.xml has been with navigation rules.  To ease the pain there, we've added implict navigation. 

Let's start with a simple example of this feature:

    <h:commandButton value="Click" action="nextPage"/>

Give the above, if there is no explicit rule defined in the faces-config.xml for the nextPage outcome, the default JSF 2.0 navigation handler will try to match a view on disk (i.e. nextPage.xhtml).  If found, it will navigate the user to that view.  Note that you could specify nextPage or nextPage.xhtml.

What if you want the navigation to trigger a redirect?  This can be handled as well.  Building off the example above...

    <h:commandButton value="Click" action="nextPage?faces-redirect=true" />

If the faces-redirect parameter is present and the value is true, the navigation will result in a client redirect.

So, with the annotations and the implicit navigation, it is possible to write an application without needing a faces-config.xml, but there are still cases where the configuration file is needed.

For example, localization information such as the default and supported locales, or using any of the advanced features such as ELResolvers, PhaseListeners, or any artifact that can rely on the decorator pattern (such as application factories, Application, RenderKit, etc). 

Feel free to give these features a go and don't hesitate to provide feedback on the forums or our issue tracker.

[7] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

Migration path from Woodstock to ICEfaces

Tuesday Jan 20, 2009

As those of you using the Woodstock component set know, all new development on Woodstock has been stopped.

In an effort to help developers easily transition from Woodstock, the following announcement was made:


We are happy to announce a relationship between the NetBeans and ICEfaces
communities to facilitate migration for current Woodstock users. With the
latest ICEface NetBeans plugin (v1.7.2SP1), you can add the ICEfaces
framework to an existing project and begin to develop ICEface pages along
side existing Woodstock pages. Resources have been created to aid migration,
including a detailed Migration Guide and a Component Comparision Matrix
between Woodstock and ICEfaces components. This is just the beginning of a
relationship between the NetBeans and ICEfaces communities. Additional
migration utilities are planned for upcoming ICEfaces releases.

Resources:   *Learn more at the Woodstock to ICEfaces Migration page
   http://www.icefaces.org/main/product/woodstock-migration.iface

 *Download the ICEfaces plugin from ICEfaces.org

http://www.icefaces.org/main/downloads/os-downloads.iface?category=NetBeans
   or from the NetBeans Update Center by choosing Tools > Plugins from
within the NetBeans IDE.

 *Read the Woodstock to ICEfaces Porting Guide
   http://www.netbeans.org/kb/docs/web/icefaces-migration-1.html

 *Join theWoodstock to ICEfaces Migration Forum
   http://www.icefaces.org/JForum/forums/list.page

Like this post? del.icio.us | furl | slashdot | technorati | digg

Going Green

Thursday Jan 01, 2009

I'm not one to normally post much of anything personal on the web, however, since several co-workers found my family's new situation interesting, I thought I might share.

This year my family and I are going green(er).  Specificially, we've moved into a house that is off the grid meaning the house doesn't use the typical public utilities (i.e. city water, electric, etc).

For electricity, the house has a solar array hooked up to a set of batteries.  The setup provides enough power for two days of typical usage with no sunlight.  Even though we live in California, there are days when you don't get sun during the winter.  For those cases we do have a propane generator that can provide power to the house and also acts as an alternator to charge the batteries so that the generator wouldn't have to continually run.

For water, we have two pumps.  One is attached to a windmill and the other is electric.  So we have two choices for drawing water into our storage tank.  Not much wind as of late, so the electric has of course been in use.

Being an employee of the tech industry (and a player of MMOs), high speed access is important.  We have this via a microwave dish directed at a local communications tower. 

The house itself is a very nice log cabin.  Now don't think that we're backwoods living.  The house has all of the normal amenities:  wood stove (there is forced hot air heating if needed), central air, several baths, dishwasher, etc. 

So for a small change in lifestyle, we get to enjoy this new house, with a great view in the mountains.  While we've only been here a few days now, we've already gotten into the groove of being more conscience about power usage and you find there's a lot of things you just take for granted.  A perfect example of this is a microwave.  Most microwaves have a digital clock.  While it's a small draw on power, it's continuous and can drain the batteries.  Because little things like that have such an impact in our new reality, we can't have them.  So for a microwave, we're using one with a mechanical timer.  I could rattle on about other devices that you may not think twice about (we never did), but I think you get the point. 

At any rate, off or on the grid, it seems that thinking about the impact of the smallest things would be of some benefit as little stuff starts to add up over time.  Something to think about.

Oh!  And you haven't truly lived until you've driven a fully loaded 16-foot moving truck on muddy, windy mountain roads.  If we move again, we're leaving our stuff behind!

P.S.  Happy New Year!

[3] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

Mojarra 1.2_11 and 2.0.0 Public Review (PR) are now available for download

Friday Dec 19, 2008

Just a quick heads up that the Project Mojarra team has pushed two releases to the project site today.

1.2_11 is a minor bug fix release.  2.0.0 PR is our release that is feature complete with respect to the JavaServer Faces 2.0 PR specification

Both releases should be available on the update center for GlassFish V3 Prelude by the end of the day.  For those running JSF on GlassFish V2, please review the release notes for upgrade instructions.

As usual, if you have feed back on potential implementation features or think you've found a bug, please log an issue on our tracker.

Feedback for the 2.0 PR specification should be mailed to jsr-314-comments@jcp.org.

UPDATE (12/22/2008) We're working out a small snag with the two releases on the UpdateCenter.  For now, I'd recommend the manual upgrade steps detailed in the release notes.  As soon as the UC issues are resolved, I'll post another update to this entry.

UPDATE (12/24/2008) We've ironed out the UC repository issues, so 1.2_11 and 2.0.0 PR are now available on the GlassFish V3 Prelude UpdateCenter (just in time for Christmas too!).

[8] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg