RichFaces rich:isUserInRole function

I blogged earlier about four built-in RichFaces functions that come in very handy, especially the rich:component(id) one. Many rich components (from rich;* tag library) provide client-side JavaScript API. To access this API, you need to use rich:component(id) and add the JavaScript method name, such as: #{rich:component(‘id’)}.someMethod(). For example, go to rich:listShuttle component in RichFaces Developers Guide and scroll to ReferenceData/JavaScript API section. That’s the JavaScript API you can call on this component.

There is one more, less known function available in RichFaces. It’s called rich:isUserInRole(role). It lets you define security roles in web.xml file and then use the role on a page. For example, suppose only the administrator should see some part of a page:

<rich:panel header="Admin panel" rendered="#{rich:isUserInRole('admin')}">
  Very sensitive information
</rich:panel>
 
<rich:panel header="User panel">
   General information
</rich:panel>

In the above example, unless you were authenticated as ‘amdin’, you will not see the top panel. Of course you need the security role in web.xml file. It’s a nice and handy feature to have available.

RichFaces suggestion box component

It’s end of the day Friday (and end of they year), what’s a better time than to revisit one of the original RichFaces components: rich:suggestionbox. rich:suggestionbox shows a list of values in a pop-up based on the input provided. It has an action method that takes value from an input field. In that action, you write what values to return based the input provided. The list of values returned is then shown in a pop-up. The actual suggestion box is just the pop-up, it needs to be attached to an input field.

screenshot_096

JSF page:

<h:form>
   <h:panelGrid columns="2">
      <h:outputText value="Enter state:" />
      <h:inputText id="input" value="#{stateBean.state}" size="40"/>
   </h:panelGrid>
   <rich:suggestionbox width="290"
	suggestionAction="#{stateBean.suggest}" var="state" for="input">
	<h:column>
	   <h:outputText value="#{state.name}"/>
	</h:column>
	<h:column>
	   <h:outputText value="#{state.capital}" />
	</h:column>
	<h:column>
	   <h:graphicImage value="#{state.flagImage}" />
	</h:column>
   </rich:suggestionbox>
</h:form>

As you can see above, suggestion box works just like a data table in JSF. This allows to display any number of columns, including rich content such as images. Also, for attribute is used to attached suggestion box to input field.

This is how suggest action looks inside stateBean:

public ArrayList<State> suggest(Object input) {
   String userInput = (String) input;
   ArrayList<State> ret = new ArrayList<State>();
 
   for (State state : this.states) {
      if ((state.getName().toLowerCase()).startsWith(userInput.toLowerCase())) {
         ret.add(state);
      }
   }
   return ret;
}

input is what user entered in the browser. Use this value to filter states and return to the client to be shown inside a pop-up.

Let’s say that you need to enter the state capital into the input field instead of state. By default, the first column is the value inserted. You could move the capital column to be first but that’s not the best approach. Instead, use fetchValue attribute to specify which of the column values to set into the input field:

<h:panelGrid columns="2">
      <h:outputText value="Enter state:" />
      <h:inputText id="input" value="#{stateBean.state}" size="40"/>
</h:panelGrid>
<rich:suggestionbox width="290"
     suggestionAction="#{stateBean.suggest}" var="state" for="input"
     fetchValue="#{stateBean.capital}"> 
   ...
</rich:suggestionbox>

As the pop-up data is retrieved from the server, you might want the user to enter some minimum number of characters before sending a request to the server. To do that set minChars attribute:

<h:panelGrid columns="2">
      <h:outputText value="Enter state:" />
      <h:inputText id="input" value="#{stateBean.state}" size="40"/>
</h:panelGrid>
<rich:suggestionbox width="290"
     suggestionAction="#{stateBean.suggest}" var="state" for="input"
     fetchValue="#{stateBean.capital}"
    minChars="2" >
   ...
</rich:suggestionbox>

There is also a client-side suggestion box called rich:comboBox.

If the suggestion box is inside a form, most likely you only want to process this component on the server. You don’t really care to process and validate any other components inside the form. In such case, use ajaxSingle=”true” on rich:suggestionbox or nest the component inside a4j:region tag as shown here:

<a4j:region>
  <h:panelGrid columns="2">
      <h:outputText value="Enter state:" />
      <h:inputText id="input" value="#{stateBean.state}" size="40"/>
  </h:panelGrid>
  <rich:suggestionbox width="290"
     suggestionAction="#{stateBean.suggest}" var="state" for="input"
     fetchValue="#{stateBean.capital}"> 
   ...
  </rich:suggestionbox>
</a4j:region>

If you are also updating anything based on value selected, you can limit updates to this region by setting renderRegionOnly=”true”. More on regions and this attribute in this post.

RichFaces with Hibernate Validator

With release of Java EE 6, you can now use Bean Validation with JSF 2. If you are using JSF 1.2 (and that’s probably still most of you), you can use Seam to take advantage of Hibernate Validator. If you are not using Seam but would still like to use Hibernate Validator, RichFaces provides such functionality.

There are three tags in RichFaces which let you work with Hibernate Validator annotations:

  1. rich:beanValidator
  2. rich:ajaxValidator
  3. rich:graphValidator

Read more »

Find RichFaces how-to’s easier on my blog

I have many posts on my blog that show various RichFaces features, how-to’s tricks and tips. It wasn’t as easy to find them so I went and tagged them all with richfaces-howto tag. Any time you want to see all these posts, just select richfaces-howto tag from the right-hand side bar.

RichFaces built-in client functions

RichFaces comes with four useful functions that make it simple to work with JavaScript. The functions are:

  1. #{rich:clientId(‘id’)}
  2. #{rich:element(‘id’)}
  3. #{rich:component(‘id’)}
  4. #{rich:findComponent(‘id’)}

Suppose you have this on JSF page:

<h:form id="form">
   <rich:calendar popup="true" id="calendar"/>
</h:form>

#{rich:clientId(‘calendar’)}
Placing this on JSF page:

#{rich:clientId('calendar')}

will display the component client id:

form:calendar

#{rich:element(‘calendar’)}
Placing this on JSF page:

#{rich:element('calendar')}

is a reference to HTML element in DOM:

document.getElementById('form:calendar')

#{rich:component(‘calendar’)}
Placing this on JSF page:

#{rich:component('calendar')}

is a reference to a custom JavaScript property that allows to call JavaScript API on rich components:

document.getElementById('form:calendar').component

For example, let’s say you have a button and you want to show calendar’s next month. This is just a regular HTML button as we are only making a JavaScript call:

<input type="button" 
      value="Show next month"
      onclick="#{rich:component('calendar')}.nextMonth();Event.stop(event);" />

Above, #{rich:component(‘calendar’)} gets us reference to calendar HTML element custom JS property and then we call nextMonth() to advance the calendar to next months on the client. Many RichFaces components define some JavaScript API that you would call exactly the same way. To find out what API is available, look for that component in Developers Guide and then for JavaScript API section (usually in Reference section). Here is the API for rich:calendar component.

#{rich:findComponent(‘id’)}
Lastly, there is #{rich:findComponent(‘id’)}. It’s neat function that allows you to test, or prototype without binding components to model (you don’t need managed beans).

<h:inputText id="input">
  <a4j:support event="onkeyup" reRender="output" />
</h:inputText>
<a4j:outputPanel id="output">
   #{rich:findComponent('input').value}
</a4j:outputPanel>

Above, there is h:inputText tag but it has no value with binding #{…} to managed bean. This means that value in the component will not be pushed into the model (it stays in the component). a4j:support is attached to send an Ajax request when onkeyup event occurs and rerenders ‘output’ component. To echo, or rerender the input on the next line, we use #{rich:findComponent(‘input’)}.value function. This function locates the component with id ‘input’ in the JSF tree and displays its value.

RichFaces-like Ajax features in JSF 2

I attended David Geary’s talk on Killer Web Apps with JSF 2 Ajax at JSF Summit where he demonstrated Ajax features in JSF 2. As you start with JSF 2, you will notice that many Ajax features in JSF 2 are very similar to what RichFaces has been providing for a number of years now.

RichFaces 4 will be based on JSF 2 and will provide some interesting advanced features on top of standard JSF 2 Ajax. Some features are advanced queues, advanced rendering features and tags such as a4j:poll, a4j:status and more. Here is a blog entry that demonstrates Ajax features in RichFaces 3.3.x, JSF 2 and RichFaces 4.

Learning JSF2: Navigation

This is a second post in Learning JSF 2 series. The first one on Managed Beans can be found here.

Before I start, thanks to Nick Belaevski (RichFaces Team Lead – Exadel) for reviewing this posting.

In JSF 1.2 all navigation rules are placed in JSF configuration file. Although you can still places navigation rules inside JSF configuration file, JSF 2 upgrades navigation by introducing implicit navigation and conditional navigation.

Implicit navigation

In JSF 1.2, navigating from one page to another required something like this:

<navigation-rule>
   <from-view-id>page1.xhtml</from-view-id>
   <navigation-case>
       <from-outcome>next</from-outcome>
       <to-view-id>/page2.xhtml</to-view-id>
   </navigation-case>
</navigation-rule>

JSF 2 now supports implicit navigation where you don’t need to define a navigation rules inside JSF configuration file. You can do this:

<h:commandButton action="page2" value="Submit" />

JSF will try to find a view named page2.xhtml in the current directory.

The following will also work:

<h:commandButton action="page2.xhtml" value="Submit" />

or

<h:commandButton action="page2.jsf" value="Submit" />

Note: this is assuming that JSF servlet is mapped to .jsf.

or using the new h:link (or h:button) tags in JSF 2 (I’ll cover these tags in a separate posting):

<h:button outcome="page2" value="Go There"/>

Implicit navigation can also be used from within an action method:

public String next () {
   return "page2";
}

The following will also work:

public String next () {
   return "page2.jsf";
}
public String next () {
   return "page2.xhtml";
}

All examples above implied that both pages (page1.xhtml and page2.xhtml) are in the same directory (notice there is no / before page name). If pages are in different directories, then full path has to be used:

<h:commandButton action="/shopping/page2" value="Submit" />

or

public String next () {
   return "/shopping/page2" ;
}

Conditional navigation

In JSF 1.2, methods in managed beans would return arbitrary string values which are passed into the navigation. Navigation couldn’t use application state to help determine what page to select. The most you could is something like this, you could check what button/link was clicked in addition to using the outcome:

<navigation-rule>
   <from-view-id>/pages/course.xhtml</from-view-id>
   <navigation-case>
      <from-action>#{bean.register}</from-action>
      <from-outcome>success</from-outcome>
      <to-view-id>/pages/registered.xhtml</to-view-id>
   </navigation-case>
</navigation-rule>

In JSF 2, you can now do this:

<navigation-rule>
   <from-view-id>/pages/course.xhtml</from-view-id>
   <navigation-case>
      <from-action>#{bean.register}</from-action>
      <if>#{bean.prerequisiteCompleted}</if>
      <to-view-id>/pages/registered.xhtml</to-view-id>
  </navigation-case>
  <navigation-case>
   <from-action>#{bean.register}</from-action>
   <if>#{bean.advisingHold}</if>
   <to-view-id>/pages/scheduleAdvisingSession.xhtml</to-view-id>
  </navigation-case>
  <navigation-case>
   <from-action>#{bean.register}</from-action>
   <if>#{not bean.payment}</if>
   <to-view-id>/pages/payForCourse.xhtml</to-view-id>
  </navigation-case>
</navigation-rule>

When #{bean.register} action is invoked, based on .. condition (evaluates to true/false) in each case, it’s possible to navigate to three different pages. This allows to use application state to determine where to navigate. It’s not longer necessary to have model objects return arbitrary strings and thus could eliminate having your back-end know anything about navigation.

Forward/Redirect

When navigating to another page, both JSF 1.2 and JSF 2 perform a forward (default behavior) to the new page (Seam, for example does a redirect by default). Because it’s a server forward (the browser is not aware that we are displaying a different page), you might have noticed that the page address in the URL is always one behind.

If defining navigation rules in JSF configuration file, then the same tag is used in JSF 1.2 and JSF 2:

<navigation-rule>
   <from-view-id>/bar/enter.xhtml</from-view-id>
      <navigation-case>
	<from-outcome>enterBar</from-outcome>
        <to-view-id>/bar/welcome.xhtml</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

When using implicit navigation in JSF2, redirect is setup using faces-redirect=true request parameter:

<h:commandLink  action="/bar/welcome?faces-redirect=true" value="Go to page 5"/>

If returning an outcome from action method:

public String enter () {
   return "/bar/welcome?faces-redirect=true";
}

Using EL in to-view-id

You can also use EL in :

<navigation-rule>
   <from-view-id>/el/page1.xhtml</from-view-id>
   <navigation-case>
      <from-action>#{bean.navigate}</from-action>
      <from-outcome>success</from-outcome>
      <to-view-id>#{bean.page}</to-view-id>	
   </navigation-case>
</navigation-rule>

In the managed bean:

…
private String page;
 
public String getPage () {
    return this.page;
}
public String navigate () {
   this.page = "/el/page3";
   return "success";
}
…

A topic closely related to navigation is page parameters and how they are propagated, I will cover that in another posting.

Finally, one thing to be aware of. Suppose you have the following rule:

<navigation-rule>
   <from-view-id>/purchase.xhtml</from-view-id>
   <navigation-case>
      <from-action>#{bean.purchase}</from-action>
      <if>#{not bean.creditCardExpired}</if>
     <to-view-id>/confirmation.xhtml</to-view-id>
   </navigation-case>
</navigation-rule>

In managed bean:

public String purchase () {
   ...
   return "confirmation";
}

Suppose creditCardExpired evaluates to true and thus making condition false. In such case you would think that navigation shouldn’t take place. However, you still navigate to confirmation.xhtml because implicit navigation is used. First, the above case is matched but not selected as .. evaluates to false. Navigation continues to look for a match and because purchase() method returned a string value of “confirmation” is used by implicit navigation which matches a page with such name. Implicit navigation is used last.

Ajax in RichFaces 3.3, JSF 2 and RichFaces 4

During my RichFaces session at JBoss World 2009, I showed three small examples of using Ajax with RichFaces 3.3, JSF 2, and RichFaces 4. I thougth it would be a good idea to show you the difference or more correct the similarities between the three. I will be blogging more about RichFaces 4 and JSF 2 so this is just a quick introduction.

I will show a small “Echo” application. There is one input field and as as you type, the input is echoed on the next line. On another line, the length of the string entered is counted. It looks like this:

screenshot_036

As you type, an Ajax request is sent to the server. We then do partial view rendering by specifying what components (text, count) to render back to the browser.

RichFaces 3.3

<h:form>
   <h:panelGrid columns="2">
      <h:outputText value="Text:" />
      <h:inputText value="#{echoBean.text}" >
         <a4j:support event="onkeyup" action="#{echoBean.countAction}"
  	    reRender="text, count"/>
  	 </h:inputText>
      <h:outputText value="Echo:" />
      <h:outputText id="text" value="#{echoBean.text}" />
      <h:outputText value="Count:" />
      <h:outputText id="count" value="#{echoBean.count}" />
   </h:panelGrid>
</h:form>

Managed bean:

public class EchoBean {
   private String text; // getter and setter
   private Integer count;  // getter and setter
 
   public void countAction() {
	count = text.length();
   }
   ...
}

Bean is registered in JSF configuration file (not shown).

JSF 2

<h:form>
   <h:panelGrid columns="2">
      <h:outputText value="Text:" />
      <h:inputText value="#{echoBean.text}" >
         <f:ajax event="keyup" execute="@form" render="text count" 
  		       listener="#{echoBean.countListener}"/>
      </h:inputText>
      <h:outputText value="Echo:" />
      <h:outputText id="text" value="#{echoBean.text}" />
      <h:outputText value="Count:" />
      <h:outputText id="count" value="#{echoBean.count}" />
   </h:panelGrid>
</h:form>

Managed bean looks slightly different as instead of an action (see example above) we use a special Ajax listener:

@ManagedBean(name="echoBean")
@RequestScoped
public class EchoBean {
   private String text;
   private Integer count;
 
   public void countListener (AjaxBehaviorEvent event) {
	count = text.length();
   }
}

RichFaces 4.0

<h:form>
    <h:panelGrid columns="2">
       <h:outputText value="Text:" />
       <h:inputText value="#{echoBean.text}" >
          <a4j:ajax event="keyup" render="text,count" 
  			listener="#{echoBean.countListener}"/>
  	   </h:inputText>
  	<h:outputText value="Echo:" />
  	<h:outputText id="text" value="#{echoBean.text}" />
       <h:outputText value="Count:" />
       <h:outputText id="count" value="#{echoBean.count}" />
   </h:panelGrid>
</h:form>

Managed bean is same as in JSF 2.

  1. Ajax features in JS2 are very similar to what’s been available in RichFaces for a couple of year. The JSF standard continues to evolve by assimilating the best ideas in the community into the standard. A perfect example is how the Ajax support in JSF 2.0 almost matches that of RichFaces.
  2. a4j:support has been replaced with a4j:ajax in RichFaces 4
  3. a4j:ajax has all the functionality of standard JSF 2 Ajax tag with many additional features to give you more flexibility and power available only in RichFaces.
  4. For example, features such as client queues, more control on deciding what to process and render, defining parts of a view to always render and much much more.

Learning JSF2: Managed beans

I’m starting a series called Learning JSF 2 on my blog. It will cover JSF 2 with emphasis on new features. Every post will cover a different features, the first one covers managed beans.

Managed bean is a regular Java bean with a fancy name. When we register the bean with JSF it becomes a managed bean, in other words, it’s now managed by the framework (JSF). In JSF, managed beans are used as model for UI components. In JSF 1.2, for a bean to become a managed bean, you had to register it in JSF configuration file such as faces-config.xml. One of the biggest announces was that as the number of beans grew, the JSF configuration file grew as well, and it was difficult to keep track of all names annd changes in three different files that all were “connected” (JSF configuration file, the JSF view and the bean itself).

Luckily, JSF 2 team has introduced annotations to register managed beans. With annotations, the bean and its registration are in the same place (Java class) so it becomes much easier to manage. You can still use JSF configuration file to register managed beans, and in some cases as you will see it’s the only way. Let’s start.

Basic Configuration

In JSF 1.2, the simplest registration looks like this:

<managed -bean>
  </managed><managed -bean-name>userBean</managed>
  <managed -bean-class>example.UserBean</managed>
  <managed -bean-scope>request</managed>

Exactly the same registration in JSF 2 looks like this:

package example;
 
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
 
@ManagedBean(name="userBean")
@RequestScoped
public class UserBean {
 
   private String name;
 
   public String getName() {
	return name;
   }
   public void setName(String name) {
	this.name = name;
   }
   public UserBean() {}
}

Read more »

RichFaces push and partial data table update

Check out this great article by Ilya Shaikovsky (Exadel) on using RichFaces push to do partial table update. Ilya is also the author of chapter 10: Scrollable Data Table and Tree in Practical RichFaces book.

Next Page »