My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

luni, 29 februarie 2016

Validating multiple fields by a custom validator method or by a managed bean instance which implements the MultiFieldValidator interface

The OmniFaces <o:validateMultiple/> allows the developer to validate multiple fields by either a custom validator method or, by a managed bean instance which implements the MultiFieldValidator interface. In the first approach, the method that performs the validation must respect the following signature:

public class FooBean {
 // ...
 public boolean fooMethod(FacesContext context, List<UIInput> components, List<Object> values) {
  // ...
 }
 // ...
}

And, it is referenced from <o:validateMultiple/> like below:

<o:validateMultiple ... validator="#{fooBean.fooMethod}" />

In the second approach, we implement the MultiFieldValidator interface and override the validateValues() method:

@Override
public class FooBean implements MultiFieldValidator {
 // ...
 public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
  // ...
 }
 // ...
}

And, it is referenced from <o:validateMultiple/> like below:

<o:validateMultiple ... validator="#{fooBean}" />

Let's have an examples that uses the second approach. For this let's suppose that we have a PrimeFaces PickList and a SelectManyCheckbox. Both components will be populated with the same data and our validation constraint imposes that the selected data from the PickList should contain the data checked in the SelectManyCheckbox. Before we add the validation constrains, let's have some preparations. So, let's say that the used data are instances of the Player class listed below:

public class Player implements Serializable {

 private static final long serialVersionUID = 1L;

 private int rank;
 private String name;

 public Player(int rank, String name) {
  this.rank = rank;
  this.name = name;
 }

 // getters and setters

 // This method is needed for using the OmniFaces ListConverter
 // and SelectItemsConverter. Both need  that our entity has a
 // good toString() implementation
 @Override
 public String toString() {
  return "Player{" + "rank=" + rank + ", name=" + name + '}';
 }
}

Furthermore, let's create a few Players and let's prepare the data accordingly to PickList and SelectManyCheckbox requirements:

@Named
@ViewScoped
public class PlayerBean implements Serializable {

 private static final long serialVersionUID = 1L;

 private List<Player> players;
 private List<Player> selectedviaCheckbox;
 private DualListModel<Player> model;

 @PostConstruct
 public void init() {
  selectedviaCheckbox = new ArrayList<>();
  players = asList(
   new Player(8, "Tomas Berdych"),
   new Player(20, "Jurgen Melzer"),
   ...
  );

  model = new DualListModel<>(
          new ArrayList<>(players),
          new ArrayList<Player>()
  );
 }

 // getters and setters

 // some dummy action
 public void playersAction(){
  Messages.addGlobalInfo("The selected players are valid");
 }
}

Next, we can expose this data to the user (notice that we have used the omnifaces.ListConverter for PickList and omnifaces.SelectItemsConverter for SelectManyCheckbox.

<h:form>
 <p:messages id="msgs"/>
 <p:pickList id="playersList" value="#{playerBean.model}" var="t"
             itemLabel="#{t.rank}.#{t.name}" itemValue="#{t}">
  <o:converter converterId="omnifaces.ListConverter" list="#{playerBean.players}" />
 </p:pickList>

 <p:selectManyCheckbox id="playersCheckbox" value="#{playerBean.selectedviaCheckbox}"
                       converter="omnifaces.SelectItemsConverter"
                       layout="responsive" style="width: 435px; margin-top: 5px;" columns="3">
  <f:selectItems value="#{playerBean.players}" var="t"
                 itemLabel="#{t.rank}.#{t.name}" itemValue="#{t}" />
 </p:selectManyCheckbox>

 <p:commandButton value="Submit" action="#{playerBean.playersAction()}"
                  update="msgs" style="margin-top:5px" />           
</h:form>

At this moment any combination of selections will be valid, as you can see in figure below:


Is time for ValidateMultiple to enter in the scene! As we said earlier, we will implement the MultiFieldValidator interface and override the validateValues() method. This method receives a list of UIInputs representing the input components that enters in validation and a list of Objects representing the local values of these components (these are the values that should be validated). Now, we need to provide the code specific to our validation constraint. We can accomplish this in multiple ways, but notice that our list of components contains two instances: one instance of org.primefaces.component.picklist.PickList and one instance of org.primefaces.component.selectmanycheckbox.SelectManyCheckbox; moreover, the list of values should contain an instance of org.primefaces.model.DualListModel and an instance of List):

@Named
@ApplicationScoped
public class ValidatePlayers implements MultiFieldValidator {

 @Override
 public boolean validateValues(FacesContext fc, List<UIInput> components, List<Object> values) {

  List<Player> fromModel;

  if (values.get(0) instanceof DualListModel) {
      fromModel = ((DualListModel) values.get(0)).getTarget();
      return fromModel.containsAll((List) values.get(1));
  } else {
      fromModel = ((DualListModel) values.get(1)).getTarget();
      return fromModel.containsAll((List) values.get(0));
  }
 }
}

Finally, we need to use <o:validateMultiple/> in page. This is pretty straightforward:

<h:form>
 ...
 <o:validateMultiple id="validateMultiple"
                     components="playersList playersCheckbox"
                     validator="#{validatePlayers}"
                     message="The selected players via checkboxes must be contained by the selected player list." />
</h:form>

This time the selection from above picture is not valid. Checkout the figure below:


But, if in the PickList, we also select the Pablo Cuevas and Jeremy Chardy players then the submission will become valid:


The complete application is named ValidateMultiple.

Read more such goodies in:

PrimeFaces & OmniFaces - Powers Combined

sâmbătă, 27 februarie 2016

[OmniFaces utilities (2.3)] Format the given number in the default pattern of the given locale


[OmniFaces utilities] The formatNumberDefaultForLocale() method formats the given number in the default pattern of the given locale. This is useful when you want to format numbers in for example the title attribute of an UI component, or the itemLabel attribute of select item, or wherever you can't use the <f:convertNumber> tag. The given locale can be a Locale object or a string representation.

Method
Usage

We will pass to Numbers#formatNumberDefaultForLocale() a locale of type xx_yy conforming to JDK 8 and JRE 8 Supported Locales, but we will pass a string of type xxx_yy also. The xxx part represents the ISO 639 alpha-2/3 code, and the yy represents the ISO 3166-1 alpha-2country code. For example for Japan we have, jpn_JP. Moreover, we will pass an instance of current Locale:

@Named
@RequestScoped
public class AmountBean {
   
 private double amount = 10242556643.23d;

 public double getAmount() {
  return amount;
 }       
}

// 10,242,556,643.23
<h:outputText value="Amount (Japan): #{of:formatNumberDefaultForLocale(amountBean.amount, 'jpn_JP')}"/>

// 10.242.556.643,23
<h:outputText value="Amount (Romania): #{of:formatNumberDefaultForLocale(amountBean.amount, 'ro_RO')}"/>

// 10 242 556 643,23
<h:outputText value="Amount (France): #{of:formatNumberDefaultForLocale(amountBean.amount, 'fr_FR')}"/>

// 10,242,556,643.23
<h:outputText value="Amount (Lule Sami): #{of:formatNumberDefaultForLocale(amountBean.amount, 'smj')}"/>

// 10,242,556,643.23
<h:outputText value="Amount (your locale): #{of:formatNumberDefaultForLocale(amountBean.amount, facesContext.viewRoot.locale)}"/>

In practice we can use it whenever <f:convertNumber/> is not an option. For example, we can used for formatting the value of itemLabel, as below:

@Named
@RequestScoped
public class AmountBean {

 private double amount;   
 List<Double> amounts;
   
 @PostConstruct
 public void init(){       
      
  amounts = new ArrayList<>();
       
  amounts.add(6943.322d);
  amounts.add(119033933.2d);
  amounts.add(444055493302.22222d);
  amounts.add(775.2133d);
  amounts.add(21331.2200d);
 }

 public double getAmount() {
  return amount;
 }
 public void setAmount(double amount) {
  this.amount = amount;
 }       

 public List<Double> getAmounts() {
  return amounts;
 }       
}

<h:form>
 <h:panelGrid columns="3">
  <h:selectOneMenu value="#{amountBean.amount}">
   <f:selectItems value="#{amountBean.amounts}" var="t"
                  itemLabel="#{of:formatNumberDefaultForLocale(t, 'ro_RO')}" itemValue="#{t}"/>
  </h:selectOneMenu>
  <h:commandButton value="Select amount"/>
  <h:outputText value="Selected amount (Romania): #{of:formatNumberDefaultForLocale(amountBean.amount, 'ro_RO')}"/>
 </h:panelGrid>
</h:form>

[OmniFaces utilities (2.3)] Parsing the given object representing the locale to a Locale object


[OmniFaces utilities] The parseLocale() method parses the given object representing the locale to a Locale object. If it is null, then return null. Else if it is already an instance of Locale, then just return it. Else if it is in pattern ISO 639 alpha-2/3, optionally followed by "_" and ISO 3166-1 alpha-2 country code, then split the language/country and construct a new Locale with it. Else parse it via Locale#forLanguageTag(String) and return it.

Method
Usage

We will pass to Utils#parseLocale() a string of type xxx_yy. The xxx part represents the ISO 639 alpha-2/3 code, and the yy represents the ISO 3166-1 alpha-2 country code. For example for Japan we have, jpn_JP.

<h:form>
 <h:outputText value="Country: #{localeBean.locale.country}"/>
 <h:outputText value="Display Country: #{localeBean.locale.displayCountry}"/>
 <h:outputText value="Display Language: #{localeBean.locale.displayLanguage}"/>

 <h:commandButton value="Japan" action="#{localeBean.localeAction('jpn_JP')}"/>
 <h:commandButton value="Italy" action="#{localeBean.localeAction('ita_IT')}"/>
 <h:commandButton value="Lule Sami" action="#{localeBean.localeAction('smj')}"/>
</h:form>

import org.omnifaces.util.Faces;
import org.omnifaces.util.Utils;
import java.util.Locale;
...
@Named
@RequestScoped
public class LocaleBean {
 
 private Locale locale;
 
 @PostConstruct
 public void init(){       
  // init with the current locale
  locale=Faces.getLocale();
 }

 public void localeAction(String code) {
  locale =  Utils.parseLocale(code);               
 }

 public Locale getLocale() {
  return locale;
 }       
}

The output will be:

// initial
Country: US
Display Country: United States
Display Language: English

// after pressing Japan button
Country: JP
Display Country: the Japan
Display Language: Japanese

// after pressing the Italy button
Country: IT
Display Country: Italy
Display Language: Italian

// after pressing the Lule Sami button
Country:
Display Country:
Display Language: Lule Sami

joi, 25 februarie 2016

Updated PrimeFaces&OmniFaces Powers Combined Book

JSF linking together components, renderers and render kits

Introduction

In order to understand what a render kit is we have to be aware of some major notions that are very important in this context. For a better understanding please check out the below picture and identify the notions described here, and the relationships between them. The subject of this picture is the OmniFaces DeferredScript component, but don't worry, you don't have to understand that component. The role and functionality of this component is not our goal. We use it because it is a professional approach for writing custom components and sustains the topic of this article by exposing best practices of accomplishing such tasks.


A JSF component is annotated with @FacesComponent and it is characterized by three coordinates (we won't take here into account the declarative approach):

component-family -This is a piece of information that groups more components under the same family/category (e.g. ScriptFamily - a family of components that deals with scripts). Typically, a family of components are logically related, but there is no written rule. Nevertheless, a family name can be represented by the package name that holds the classes of the related components (e.g. org.omnifaces.component.script). It is a common practice that the classes of the components that are related to be placed in the same package, so the package name can be considered a family. But, again, there is no rule to sustain this practice. In order to expose into public is family a component will override the getFamily() method. Since JSF 2.2, the component-type can be omitted in @FacesComponent, because JSF will determine it like this (ComponentConfigHandler class):

...
String value = ((FacesComponent) annotation).value();
if (null == value || 0 == value.length()) {
    value = target.getSimpleName();
    value = Character.toLowerCase(value.charAt(0)) + value.substring(1);
}
...

component-type - This is a piece of information that uniquely identifies a component and can be used as the argument of the Application.createComponent(java.lang.String) method for creating instances of the UIComponent class. JSF uses the component-type for creating components. Typically a component type will be the fully qualified named of the component class (e.g. org.omnifaces.component.script.DeferredScript). There is a common practice to define the component-type as a static final string directly in component class and to name it COMPONENT_TYPE. Some developers tend to place the component-type string directly in annotation, which somehow restricts the programmatic access to this information, since, by default, there is no public UIComponent.getComponentType() method to override. Components of different types can be grouped in families.

renderer-type - This is a piece of information that uniquely identifies a renderer (e.g. org.omnifaces.DeferredScript). A component will used its setRendererType() method to point to the render-type that should render this component. Components can call this method as setRendererType(null) to point out that they will render themselves. But, by delegating the rendering to a separate renderer, the component makes itself more versatile because multiple renderers would be able to render it to different clients.

If you extend UIInput, you will inherit its type and family, but if you extend UIComponentBase, then you need to explicitly provide the component-type and component-family.

A Renderer is not selected based on the component-type and renderer-type! Is selected based on component-family and renderer-type, which allows a renderer to be used for multiple components in the same family. The component-type is used for creating components in view root!

Overview of Renderer

What is the main goal of a renderer ?
Is responsible to decode the values from the incoming request and to encode the values to be displayed by transforming the component tree into the HTML markup that will be displayed to the client machine. Shortly, to transform a JSF component in markup (e.g. HTML, XML, etc).

When you commonly need a custom renderer ?
When you need to render a custom component (brand new or extension of a built-in one), because none of the built-ins do what you want to achieve.

When you want to alter the look/functionality of an built-in component.

What should I know before start writing a custom renderer ?
Mainly you need to know that a renderer extends directly/indirectly the Renderer class.
Starting with JSF 2.2, you can extend RendererWrapper, which is a simple implementation of Renderer. JSF 2.2 comes with many wrappers, which are simple implementations of what they are wrapping, and they help developer to override only the necessary methods, and to provide specialized behavior to an existing wrapped instance (e.g. RendererWrapper can be used for providing specialized behavior to an existing Renderer instance). The wrapped instance is available via the getWrapped() method.

The main three methods of a Renderer are encodeBegin(), encodeChildren() and encodeEnd(). By default, JSF calls them in this order, and the first one usually renders the beginning of the markup - "open" tags (e.g. <head>, <input>, <form>, etc), the second one  renders the children (this is configurable via getRendersChildren() flag), and the last one is ending the markup - "close" tags (e.g. </head>, </input>, </form>).

In order to link a component with a renderer, you should know how to work with the UIComponent.setRenderType() method and with the component-family, component-type and renderer-type artifacts as level of annotations or with the <render-kit>  and <renderer> tags in faces-config.xml.

How do I usually write a Renderer skeleton ?
•when you write a brand new component (extending UIComponentBase), you will extend the Renderer class directly and override most of its methods. Usually in these cases you will link the custom component with the renderer via annotations and setRendererType() method.


More examples:

Create and render a brand new component (source code).

When you write a custom component which extends a built-in component, you usually extend the renderer of the built-in component also - directly (most probably) or indirectly. Usually in these cases you will link the custom component with the renderer via the setRenderType() method. Of course, you can also use the renderer of the built-in component without any modifications (source code).
When you just want to alter a built-in component at rendering level, you usually extend the built-in renderer and you instruct JSF to use your renderer instead of the default one via faces-config.xml, <renderer> tag. E.g. use a custom Renderer for the JSF UIOutput component (source code). In order to run this application you have to keep in mind that we are extending a Mojarra renderer (com.sun.faces.renderkit.html_basic.TextRenderer), so you need to:

- manually install the JSF 2.2 JAR so your IDE will find the TextRenderer.
- in pom.xml, the entry for JSF 2.2 should have its scope set to provided, as it shouldn't be copied into the deployment.

Overview of RenderKit

What is the main goal of a RenderKit ?
While the Renderer class converts the internal representation of UI components into markup (e.g. HTML), RenderKit represents a collection of Renderer instances capable to render JSF UI component's instances for a specific client (for example, a specific device). Each time JSF needs to render a UI component, it will call the RenderKit.getRenderer() method which is capable of returning an instance of the corresponding renderer based on two arguments that uniquely identifies it: the component-family and the renderer-type. Moreover, RenderKit registers renderers via RenderKit.addRenderer() method based on the component-family, renderer-type and Renderer instance. When we write a correct renderer (respecting the JSF specification) JSF will automatically find it and register it for us.

When you commonly need a custom RenderKit ?
You may use a custom RenderKit to instruct JSF to delegate renderers in a specific approach. Per example, a custom RenderKit can choose the right renderer depending on device (PC, tablet, iPhone, etc). Or, you may have a custom Renderer that extends the RendererWrapper, and use a custom RenderKit to pass an instance of an existing Renderer to the custom Renderer.

What should I know before start writing a custom RenderKit ?
Mainly, you need to know that a custom RenderKit extends directly/indirectly the RenderKit class.

Starting with JSF 2.0, you can extend RenderKitWrapper, which is a simple implementation of RenderKit. Via RenderKitWrapper, you can provide a specialized behavior to an existing RenderKit instance. The wrapped instance is available via the getWrapped() method.

The main two methods of a RenderKit are addRenderer() and getRenderer(). By overriding these methods, you can take control over the Renderers registration and delegation. Of course, there are many other useful methods listed in documentation.

How do I usually write a RenderKit skeleton ?
Usually, you will extend the RenderKitWrapper class, override the necessary methods, and configure it in the faces-config.xml via <render-kit> tag.

So, as you can see in figure below, the RenderKit sits between components and renderers and act as a conductor:

Now, we know that each component is rendered after its component-family and renderer-type passes through the RenderKit.getRenderer() method:

public abstract Renderer getRenderer(java.lang.String family,
                                     java.lang.String rendererType)

This method match the correct renderer , like this:

private ConcurrentHashMap<String, HashMap<String, Renderer>> rendererFamilies =
  new ConcurrentHashMap<String, HashMap<String, Renderer>>();
...
HashMap<String,Renderer> renderers = rendererFamilies.get(family);
return ((renderers != null) ? renderers.get(rendererType) : null);

So, in order to obtain its renderer, each component must reveal its family (COMPONENT_FAMILY) and renderer-type to this method (with a simple custom RenderKit you can check out the JSF/OmniFaces components families and renderer types). Programmatically, a family, component-family, is obtained via UIComponent.getFamily(), and the renderer-type via UIComponent.getRendererType():

public abstract java.lang.String getFamily()
public abstract java.lang.String getRendererType()

Now, JSF search through available renderers that was added via RenderKit.addRenderer().  JSF has inspected faces-config.xml file for:

<render-kit>
    <renderer>
        <component-family>component-family</component-family>
        <renderer-type>renderer-type</renderer-type>
        <renderer-class>RendererClass</renderer-class>
    </renderer>
</render-kit>

 and all classes annotated with @FacesRenderer:

@FacesRenderer(componentFamily=ComponentClass.COMPONENT_FAMILY, rendererType= RendererClass.RENDERER_TYPE)
public class RendererClass extends Renderer {
 public static final String RENDERER_TYPE = "renderer-type";
 ...
}

Optionally, Facelets can be also informed by the render type in *taglib.xml. When you do that, you instruct Facelets to create a component of the given component-type. The component class is annotated with @FacesComponent or has been defined in faces-config.xml. In addition Facelets will set to the given renderer type.

<tag>
 ...
 <component>
  <component-type>component-type</component-type>
  <renderer-type>renderer-type</renderer-type>
 </component>
 ...
</tag>

Ok, so now let's have several examples of custom RenderKits:

Log how JSF renderers are added/delegated by JSF (source code).

Instruct JSF to render all components of a family via a common custom renderer (we simply apply a common CSS style to all components from javax.faces.Input family) (source code).

Instruct JSF to render UIOutput components via a custom renderer that was registered for other type of components, but pass to it an instance of the original renderer (source code).

Overview of a RendererKitFactory

What is the main goal of a RenderKitFactory ?
It manages (register/provide) instances of available RenderKits.

When you commonly need a custom RenderKitFactory ?
You may use a custom RenderKitFactory to instruct JSF to delegate RenderKits in a specific approach. By default, JSF has a single RenderKit, identified by an ID, HTML_BASIC_RENDER_KIT. But, if want to write another RenderKit then you can programmatically choose between them using a custom RenderKitFactory.

What should I know before start writing a custom RenderKitFactory ?
Mainly, you need to know that a render kit factory extends directly/indirectly the RendererKitFactory class.

The main two methods of a RenderKitFactory are addRenderKit() and getRenderKit() . By overriding these methods, you can take control over the RenderKits registration and delegation. The render kits IDs can be obtained via getRenderKitIds() method. If this factory has been decorated, the implementation doing the decorating may override the getWrapped() method to provide access to the implementation being wrapped.

In order to link a component with a renderer, you should know how to work with the UIComponent.setRenderType() method and with the component-family, component-type and renderer-type artifacts as level of annotations or with the <render-kit>  and <renderer> tag in faces-config.xml.

How do I usually write a RenderKitFactory skeleton ?
Usually, you will extend the RenderKitFactory class, override the necessary methods, and configure it in the faces-config.xml via <render-kit-factory> tag.

For example, replace the default JSF RenderKit with the DummyRenderKit (source code).

miercuri, 24 februarie 2016

[OmniFaces utilities 2.3] Expose protected state helper into public


[OmniFaces utilities] The getStateHelper() method exposes protected state helper into public.

Method:
Usage:

import org.omnifaces.util.Hacks;
...
StateHelper stateHelper = Hacks.getStateHelper(foo_component);
// now use the StateHelper API via stateHelper object

Note Do not forget about the OmniFaces State utils for finding/putting a value associated with the specified key in the component's state.

duminică, 21 februarie 2016

JSF Navigation Tutorial - Implicit Navigation

Check also:
The three golden rules of use
JSF Navigation Tutorial - Declarative Navigation
JSF Navigation Tutorial - Conditional Navigation
JSF Navigation Tutorial - Preemptive Navigation
JSF Navigation Tutorial - Programmatic Navigation
JSF VS Series: Implicit Navigation VS Declarative (explicit) Navigation

Implicit navigation is available starting with JSF 2 and is the most common type of navigation used in JSF applications. Until JSF 2, we had to declare all navigation cases in faces-config.xml which was a time consuming task and the result was snippets of XML code hard to maintain. By implicit navigation we don't need the declarative approach anymore and specifying simple navigation cases become pretty straightforward. JSF provides a mechanism for mapping logical outcomes to actual web pages. Now, we have two types of implicit navigation: with no explicit navigation outcome and with explicit navigation outcome.

The simplest implicit navigation case is accomplished by JSF itself whenever you perform an action (request) and no navigation is indicated. When an outcome is indicated the implicit navigation interprets navigation outcomes as target view IDs.


So implicit navigation save us from the tedious task of declaring navigation rules in faces-config.xml and provides us a very intuitive and easy to use mechanism of navigation. Whenever we want to navigate back to the current view, we simply do nothing! What could be simpler than that? Whenever we want to navigate to another view, we simply specify the corresponding outcome in the outcome or action attribute depending on the used navigation tag.

Let's see some examples of using implicit navigation. The managed bean used in the next examples is listed first and the application is named ImplicitNavigation:

@Named
@RequestScoped
public class TheBean {
   
 private static final Logger LOG = Logger.getLogger(TheBean.class.getName());
           
 public void theActionWithVoid(){
  LOG.info("TheBean#theActionWithVoid() called ...");
 }

 public String theActionWithViewID() {
  LOG.info("TheBean#theActionWithViewID() called ...");
  return "success.xhtml";
 }

 public String theActionWithExternalURL() {
  LOG.info("TheBean#theActionWithExternalURL() called ...");
  return "http://showcase.omnifaces.org/";
 }
   
 public String theActionWithOutcome(){
  LOG.info("TheBean#theActionWithOutcome() called ...");
  return "success";
 }
   
 public String theActionWithRedirect(){
  LOG.info("TheBean#theActionWithRedirect() called ...");
  return "success?faces-redirect=true;";
 }   
}

FIRE A JSF GET REQUEST AND NAVIGATE BACK TO THIS VIEW ID
Since there is no outcome JSF will consider this page as the targeted page name

<h:link value="Click me!"/>
<h:button value="Click me!"/>

JSF will render the following HTML (as you see the navigation cases have been hard-coded in page source code):

<a href="/ImplicitNavigation/faces/index.xhtml">Click me!</a>

<input type="button" onclick="window.location.href='/ImplicitNavigation/faces/index.xhtml'; return false;" value="Click me!" />

FIRE A JSF GET REQUEST AND NAVIGATE TO THE VIEW ID COMPUTED FROM THE SPECIFIED OUTCOME
JSF will interpret the outcome value of <h:link/>/<h:button/> as the targeted page name (success becomes success.xhtml)

<h:link value="Click me!" outcome="success"/>
<h:button value="Click me!" outcome="success"/>

JSF will render the following HTML (as you see the navigation cases have been hard-coded in page source code and they contain success.xhtml):

<a href="/ImplicitNavigation/faces/success.xhtml">Click me!</a>

<input type="button" onclick="window.location.href='/ImplicitNavigation/faces/success.xhtml'; return false;" value="Click me!" />

FIRE A JSF GET REQUEST. PROVIDE THE NAVIGATION OUTCOME VIA A SERVER-SIDE METHOD CALLED DURING COMPUTING THE VIEW ID (AT RENDERING TIME)
JSF will interpret the outcome value of of <h:link/>/<h:button/> as the targeted page name (success returned by theActionWithOutcome() becomes success.xhtml)

<h:link value="Click me!" outcome="#{theBean.theActionWithOutcome()}"/>
<h:button value="Click me!" outcome="#{theBean.theActionWithOutcome()}"/>

JSF will render the following HTML (as you see the navigation cases have been hard-coded in page source code and they contain success.xhtml):

<a href="/ImplicitNavigation/faces/success.xhtml">Click me!</a>

<input type="button" onclick="window.location.href='/ImplicitNavigation/faces/success.xhtml'; return false;" value="Click me!" />

Note The server-side method must return a string representing the outcome.

FIRE A GET REQUEST THAT DOESN'T INTERACT WITH JSF
The <h:outputLink/> will navigate independently of JSF (that means it doesn't interact with JSF)

<h:outputLink value="success.xhtml">Click me!</h:outputLink>
<h:outputLink value="http://showcase.omnifaces.org/">OmniFaces Showcase</h:outputLink>

JSF will render the following HTML (as you see the navigation cases have been hard-coded in page source code; notice that /faces is missing!):

<a href="success.xhtml">Click me!</a>
<a href="http://showcase.omnifaces.org/">OmniFaces Showcase</a>

FIRE A GET REQUEST THAT DOESN'T INTERACT WITH JSF. PROVIDE THE NAVIGATION TARGET VIA A SERVER-SIDE METHOD CALLED DURING COMPUTING THE VIEW ID (AT RENDERING TIME)
The <h:outputLink/> will navigate independently of JSF (that means it doesn't interact with JSF)

<h:outputLink value="#{theBean.theActionWithViewID()}">Click me!</h:outputLink>
<h:outputLink value="#{theBean.theActionWithExternalURL()}">OmniFaces Showcase</h:outputLink>

JSF will render the following HTML (as you see the navigation cases have been hard-coded in page source code; notice that /faces is missing!):

<a href="success.xhtml">Click me!</a>
<a href="http://showcase.omnifaces.org/">OmniFaces Showcase</a>

Note The server-side method must return a string representing the navigation target NOT an outcome (e.g. you must return success.xhtml, not success). Since the fired GET request will not pass through JSF  the outcome will not be computed!

FIRE (SUBMIT) A POST REQUEST VIA FORWARD MECHANISM AND NAVIGATE BACK TO THIS VIEW ID
Since there is no action JSF will consider this page as the targeted page name

<h:form>
 <h:commandLink value="Click Me!"/>
 <h:commandButton value="Click Me!"/>
</h:form>

JSF will render the following HTML (as you see the navigation cases are not hard-coded). Even if we have a HTML <a> and an <input type="submit">  there is no functional difference between them. Both will submit the form and navigate back to the current view ID.

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt30'),{'j_idt30:j_idt32':'j_idt30:j_idt32'},'');return false">
 Click Me!
</a>

<input type="submit" name="j_idt30:j_idt34" value="Click Me!" />

FIRE (SUBMIT) A POST REQUEST VIA FORWARD MECHANISM. INVOKE A VOID ACTION METHOD AND NAVIGATE BACK TO THIS VIEW ID
There is an action but it points to an void action method. JSF will invoke the theBean#theActionWithVoid() action method and consider this page as the targeted page name

<h:form>
 <h:commandLink value="Click Me!" action="#{theBean.theActionWithVoid()}"/>
 <h:commandButton value="Click Me!" action="#{theBean.theActionWithVoid()}"/>
</h:form>

JSF will render the following HTML:

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt36'),{'j_idt36:j_idt38':'j_idt36:j_idt38'},'');return false">
 Click Me!
</a>

<input type="submit" name="j_idt36:j_idt40" value="Click Me!" />

FIRE (SUBMIT) A POST REQUEST VIA FORWARD MECHANISM AND NAVIGATE TO THE VIEW ID COMPUTED FROM THE SPECIFIED OUTCOME
JSF will interpret the action value of <h:commandLink/Button/> as the targeted page name (success becomes success.xhtml)

<h:form>
 <h:commandLink value="Click Me!" action="success"/>
 <h:commandButton value="Click Me!" action="success"/>
</h:form>

JSF will render the following HTML:

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt42'),{'j_idt42:j_idt44':'j_idt42:j_idt44'},'');return false">
 Click Me!
</a>

<input type="submit" name="j_idt42:j_idt46" value="Click Me!" />

FIRE (SUBMIT) A POST REQUEST VIA REDIRECT MECHANISM AND NAVIGATE TO THE VIEW ID COMPUTED FROM THE SPECIFIED OUTCOME
The presence of ?faces-redirect=true; will instruct JSF to rely on POST-redirect-GET (PRG) navigation pattern

<h:form>
 <h:commandLink value="Click Me!" action="success?faces-redirect=true;"/>
 <h:commandButton value="Click Me!" action="success?faces-redirect=true;"/>
</h:form>

JSF will render the following HTML:

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt48'),{'j_idt48:j_idt50':'j_idt48:j_idt50'},'');return false">
 Click Me!
</a>

<input type="submit" name="j_idt48:j_idt52" value="Click Me!" />

FIRE (SUBMIT) A POST REQUEST VIA FORWARD MECHANISM. INVOKE AN ACTION METHOD AND NAVIGATE TO THE VIEW ID COMPUTED BASED ON THE OUTCOME RETURNED BY THIS METHOD
The action can point to an action method that returns a String. This string is considered the outcome and it will be interpreted as the targeted page name (success becomes success.xhtml)

<h:form>
 <h:commandLink value="Click Me!" action="#{theBean.theActionWithOutcome()}"/>
 <h:commandButton value="Click Me!" action="#{theBean.theActionWithOutcome()}"/>
</h:form>

JSF will render the following HTML:

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt54'),{'j_idt54:j_idt56':'j_idt54:j_idt56'},'');return false">
 Click Me!
</a>

<input type="submit" name="j_idt54:j_idt58" value="Click Me!" />

FIRE (SUBMIT) A POST REQUEST VIA REDIRECT MECHANISM. INVOKE AN ACTION METHOD AND NAVIGATE TO THE VIEW ID COMPUTED BASED ON THE OUTCOME RETURNED BY THIS METHOD
The action can point to an action method that returns a String suffixed with ?faces-redirect=true; (will instruct JSF to rely on POST-redirect-GET (PRG) navigation pattern). This string is considered the outcome and it will be interpreted as the targeted page name (success becomes success.xhtml)

<h:form>
 <h:commandLink value="Click Me!" action="#{theBean.theActionWithRedirect()}"/>
 <h:commandButton value="Click Me!" action="#{theBean.theActionWithRedirect()}"/>
</h:form>

JSF will render the following HTML:

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('j_idt60'),{'j_idt60:j_idt62':'j_idt60:j_idt62'},'');return false">
 Click Me!
</a>

<input type="submit" name="j_idt60:j_idt64" value="Click Me!" />

The complete application is available here.

Notes
Logic of outcome
When implicit navigation takes place it follows the next steps:

1.Look for the ? character in the logical outcome. If it is found then capture the query string and look for the presence of faces-redirect=true request parameter. Remember that this parameter points to a redirect navigation case.

2.Look for the file extension attached to the logical outcome. If none is found then automatically attached the extension of current view ID (e.g. xhtml)

3.If the logical outcome doesn't begin with a / then prepend the location of the current view ID (e.g., /, /pages/, etc.).

4. Locate the view ID. If it is not found then abort implicit navigation.

5.For non-redirect cases simply build and render the view ID in the current request. If it is a redirect then build a redirect URL. The query string parameters captured earlier is appended to this URL. Redirect to this URL.

Use Sub-folders
If your views are stored in subfolders then simply prefix the outcome with the corresponding path (e.g. if the view login.xhtml is stored in /mypages/credentials folder then an outcome will be: mypages/credentials/login).

Use Application Context
Whenever you want to add the application context path in a URL (for example, the URL generated via <h:outputLink>, you can use the ExternalContext.getApplicationContextPath method of JSF 2.2. For example, take a look at the following code:

<h:outputLink value="#{facesContext.externalContext.applicationContextPath}/next.xhtml">Next</h:outputLink>

Forward vs Redirect
By default, between forward and redirect, JSF will navigate from one page to another using the forward mechanism (HTTP POST). When JSF receives the user action, it will forward the user to the determined target page, which means that the URL displayed by the browser will not be updated to reflect the current target. Keeping the browser URL updated implies the page redirection mechanism; in this case, JSF, delegates the browser to send a separate GET request to the target page. You can use the page redirection mechanism by attaching the faces-redirect=true as you saw in the above examples. In the forward case, the browser URL is not updated (is with a step behind navigation URL), but there is a single request. In the redirect case, the browser URL is up to date, but there are two requests. Since forward needs a single request, it is faster than page redirection. The speed is lower, but page redirection solves the duplicated form submission problem found in the Post-Redirect-Get design pattern. Of course, this is not the case for <h:link/>, <h:button/>, and <h:outputLink/>.
We can conclude that POST via forward result in non-bookmarkable URL while POST via redirect result in bookmarkable URL and this is a major SEO aspect also.

Outcome vs View ID
In all the examples above we have used the outcome version (success) instead of view ID (success.xhtml).  In not a good idea to use view ID directly since you may decide to give up on *.xhtml mapping and use *.jsf. In such case, you will have to modify the success.xhtml in success.jsf. This will happen for all such navigation cases. Using the success outcome will not require any further adjustments.

Outcome vs Action
If you are a novice then is very possible to confuse these two attributes. Basically, the outcome attribute is specific to <h:link/> and <h:button/> tags. Its role is to point to the logical outcome used to resolve a navigation case and the tags that support it cannot submit a form. On the other hand, the action attribute is specific to commands capable to submit forms (<h:commandLink/> and <h:commandButton/>).  This attribute is a String representing the logical outcome or a MethodExpression representing the application action to invoke when this component is activated by the user. The expression must evaluate to a public method that takes no parameters, and returns an Object (the toString() of which is called to derive the logical outcome) which is passed to the NavigationHandler for this application. 

JSF BOOKS COLLECTION

Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors