Integrating JavaServer Faces with Beehive Page Flow
Pages: 1, 2, 3

Raising a Page Flow action from a backing bean

In the Basic Integration section above, you raised a Page Flow action directly from a JSF component. Often, this is simply all you need; when you click a button or a link, an action runs and takes you to another page. If you would like to run some page-related code before calling out to the controller, or if you would like the page to choose dynamically between several actions, then you can raise an action from within a command handler—a Java method that is run by the JSF page. Here is an sample command handler, which you can put in the backing bean page2.java (or in any other publicly-accessible bean):

public String

chooseNextPage()

{

  return "goPage3";

}

This is a very simple command handler, which chooses the goPage3 action. You bind to this command handler from a JSF command component in the standard JSF way:

<h:commandButton action="#{backing.chooseNextPage}" 

                 value="Submit"/>

When you click the link, your chooseNextPage command handler is run, and it chooses to raise action goPage3. You can optionally use a special Page Flow annotation— @Jpf.CommandHandler —on the command handler method:

@Jpf.CommandHandler(

 raiseActions={

      @Jpf.RaiseAction(action="goPage3")

 }

)

public String chooseNextPage()

{

 return "goPage3";

}

This annotation allows Beehive-aware tools to understand which actions are raised by a command handler in a backing bean, and it also allows you to extend the capabilities of JSF action processing (see the Sending data from a JSF page to a Page Flow section below).

Accessing the current Page Flow or a shared flow from the backing bean

In some cases, you may want to access the current Page Flow, or an active shared flow, directly from a backing bean. To do this, simply create a field of the correct type, and annotate it with @Jpf.PageFlowField or @Jpf.SharedFlowField as appropriate:

@Jpf.PageFlowField

private ExampleController myController;



@Jpf.SharedFlowField(name="sharedFlow2") // "sharedFlow2" is a 

                                         // name defined in the

                                         // page flow controller

private ExampleSharedFlow mySharedFlow;

These fields will be initialized when the backing bean is created. You never need to initialize them manually. Here is an example of using the auto-initialized ExampleController field. In this case, an event handler for a "show hints" radio button sets a general preference in the Page Flow.

 public void showHintsValueChanged(ValueChangeEvent event)

 {

   if (event.getNewValue().equals("show"))

   {

     myController.turnOnHints();

   }

   else

   {

     myController.turnOffHints();

   }

}

In many cases, your page will never need to interact directly with a Page Flow or a shared flow; instead, it's sufficient to use other means to pass data from a Page Flow to a JSF page, or vice versa. I'll show examples of these below.

Accessing the backing bean from a Page Flow controller

You can't access the backing bean from a Page Flow controller! At least, it's not easy, and intentionally so. The backing bean is associated tightly with your JSF page, and it is destroyed when you leave the page. The Page Flow controller should be no more aware of the backing bean than it should be aware of the specifics of a page. Of course, you can pass data from the backing bean to the controller (described below), and you can even pass the backing bean instance itself, but in most cases the content of the backing bean is not something that should leak out to the controller.

Lifecycle methods

Often, you want to run code when something happens to your backing bean such as when it is created or destroyed. The Page Flow framework will call several methods on the backing bean as it progresses through its lifecycle:

  • onCreate() : When the bean is created.
  • onDestroy() : When the bean is destroyed (removed from the user session).
  • onRestore() : This one bears a bit of explaining. I said that the backing bean is destroyed when you leave the page. In most cases this is true, but if your Page Flow uses the navigateTo feature, which allows you to revisit a previously shown page, the framework hangs onto your backing bean for a short time after you leave the page, in case it needs to be restored. When a JSF page is restored by going through a @Jpf.Forward or @Jpf.SimpleAction with navigateTo= Jpf.NavigateTo.currentPage or navigateTo= Jpf.NavigateTo.previousPage , both the page's component tree and its backing bean are restored by the Page Flow framework. When this happens, onRestore() is called.

To run code at any of these stages, you simply override the appropriate method:

protected void onCreate()

{

 /*some create-time logic */

}

When you override one of these methods, you do not need to call the super version, which is empty.

Passing Data Between a JSF Page and a Page Flow

Now you're ready to look at how to pass data between a JSF page and a Page Flow.

Sending data from a Page Flow to a JSF page

Often you will want to initialize a page with data from the page flow. To do this, add "action outputs" to the Forward for page2.faces:

@Jpf.Action(

 forwards={

  @Jpf.Forward(

    name="success", path="page2.faces",

     
                        
actionOutputs={

      @Jpf.ActionOutput(name="message", type=String.class,

       required=true)

    }

  )

 }

)



public Forward goPage2()

{

  Forward fwd = new

  Forward("success");

   fwd.addActionOutput("message", "Got the message.");

  return fwd;

}
                      

Once you have done this, you can access this value as a page input, either directly in your JSF page or in your backing bean. (If you don't like typing verbose annotations, you can leave out the ones in italics. They mainly serve to double-check that you added an object of the right type, and that it isn't missing.)

In your page you can bind to the value using the Page Flow pageInput binding context in the JSF expression language:

<h:outputText value="#{pageInput.message}"/>

Note that you can also bind to properties of the page flow controller itself, or of any available shared flow, using the pageFlow and sharedFlow binding contexts:

<h:outputText value="#{pageFlow.someProperty}"/>

<h:outputText value="#{sharedFlow.mySharedFlow.someProperty}"/>

Finally, to access a page input from a backing bean, just call getPageInput from code anywhere in the bean class:

String message = (String) getPageInput("message");

Pages: 1, 2, 3

Next Page »