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

joi, 12 noiembrie 2015

JSF Scopes Tutorial - CDI Conversation Scope

The conversation scope allows developers to demarcate the lifespan of the session scope.
The conversation scope is committed to the user's interaction with JSF applications and represents a unit of work from the point of view of the user; a bean in this scope is able to follow a conversation with a user. We may charge the conversation scope as a developer-controlled session scope across multiple invocations of the JSF life cycle; while session scoped lives across unlimited requests, the conversation scopes lives only across a limited number of requests.

The developer can explicitly set the conversation scope boundaries and can start, stop, or propagate the conversation scope based on the business logic flow. All long-running conversations are scoped to a particular HTTP servlet session and may not cross session boundaries. In addition, conversation scope keeps the state associated with a particular Web browser window/tab in a JSF application.

Conversation Scope Annotations
CDI: The conversation scope annotation is @ConversationScoped and is defined in the javax.enterprise.context package for CDI.

Implements Serializable
The conversation scope bean might get passivated by the container and should be capable of passivity by implementing the java.io.Serializable interface

Simple Example
Dealing with the conversation scope is slightly different from the rest of the scopes. First, you mark the bean with @ConversationScope, represented by the javax.enterprise.context.ConversationScoped class. Second, CDI provides a built-in bean (javax.enterprise.context.Conversation) for controlling the life cycle of conversations in a JSF application—its main responsibility is to manage the conversation context. This bean may be obtained by injection, as shown in the following code:

private @Inject Conversation conversation;

By default, the Conversation object is in transient state and it should be transformed into a long-running conversation by calling the begin() method. You also need to prepare for the destruction of the conversation by calling the end() method. If we try to call the begin() method when the conversation is active, or the end() method when the conversation is inactive, IllegalStateException will be thrown. We can avoid this by testing the transitivity state of the Conversation objects using the method named isTransient(), which returns a boolean value.

Now, add the begin(), end(), and isTransient() methods together to the following conversations:

• For start conversation, the code is as follows:

if (conversation.isTransient()) {
    conversation.begin();
}

• For stop conversation, the code is as follows:

if (!conversation.isTransient()) {
    conversation.end();
}

For example, you can add the conversation scope in PlayersBean as follows:

@Named
@ConversationScoped
public class PlayersBean implements Serializable {

 private @Inject
 Conversation conversation;

 final String[] players_list = {"Nadal, Rafael (ESP)","Djokovic,
Novak (SRB)", "Ferrer, David (ESP)", "Murray, Andy (GBR)",
"Del Potro, Juan Martin (ARG)"};

 private ArrayList players = new ArrayList();
 private String player;

 public PlayersBean() {
 }

 //getters and setters

 public void newPlayer() {
  int nr = new Random().nextInt(4);
  player = players_list[nr];
  players.add(player);
 }

 public void startPlayerRnd() {
  if (conversation.isTransient()) {
      conversation.begin();
  }
 }

 public void stopPlayerRnd() {
  if (!conversation.isTransient()) {
      conversation.end();
  }
 }
}

Besides injecting the built-in CDI bean, notice that you have defined a method (startPlayerRnd()) for demarcating the conversation start point and another method (stopPlayerRnd()) for demarcating the conversation stop point. In this example, both the methods are exposed to the user through two buttons, but you can control the conversation programmatically by calling them conditionally.

In order to test the above bean we can have a simple JSF page, as below:

<h:body>
 Just generated:
 <h:outputText value="#{playersBean.player}"/><br/>

 List of generated numbers:
 <h:dataTable var="t" value="#{playersBean.players}">
  <h:column>
   <h:outputText value="#{t}"/>
  </h:column>
 </h:dataTable>      

 <h:form>
    <h:commandButton value="Start Conversation" style="background-color: #00cc00;" 
                     actionListener="#{playersBean.startPlayerRnd()}" action="index"/>
  <h:commandButton value="Get Players In Same View" actionListener="#{playersBean.newPlayer()}"/>
  <h:commandButton value="Get Players With Page Forward" actionListener="#{playersBean.newPlayer()}" 
                   action="index"/>
  <h:commandButton value="Get Players With Page Redirect" actionListener="#{playersBean.newPlayer()}" 
                   action="index?faces-redirect=true;"/>
  <h:commandButton value="Stop Conversation" style="background-color: #00cc00;" 
                   actionListener="#{playersBean.stopPlayerRnd()}" action="index"/>
 </h:form>
</h:body>

The complete application is available here.

The list of randomly extracted players will be empty or will contain only the current extracted player until the button labeled Start Conversation is clicked. At that moment the list will be stored in session, until the button labeled Stop Conversation is clicked.

During the conversation, the user may execute AJAX/non-AJAX requests against the bean or perform navigations to other pages that still reference this same managed bean. The bean will keep its state across user interactions using a conversation identifier generated by the container, and this is why the conversation scope can be the right choice when you need to implement wizards. But it might be a good idea to take into account the new JSF 2.2 flow scope as well, which solves several gaps of the conversation scope.

In this example, the conversation context automatically propagates with any JSF faces request or redirection (this facilitates the implementation of the common POST-then-redirect pattern), but it does not automatically propagate with non-faces requests, such as links. In this case, you need to include the unique identifier of the conversation as a request parameter. The CDI specification reserves the request parameter cid for this use. The following code will propagate the conversation context over a link:

<h:link outcome="/link.xhtml" value="Conversation Propagation">
 <f:param name="cid" value="#{conversation.id}"/>
</h:link>

A method annotated with @PostConstruct will be called for each request as long as the bean is not involved in a conversation. When the conversation begins, the method is called for that instance and subsequent requests will use this instance until the conversation ends. Therefore, be careful how you manage this method content.

See you in the next post about CDI flow scope.

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors