Using ICEfaces with CDI

compared with
Key
These lines were removed. This word was removed.
These lines were added. This word was added.

View page history


There are 1 changes. View first change.

 h1. Using ICEfaces-2.0.0 with Weld
 Weld is the reference implemention for JSR-299: Java Contexts and Dependency Injection for the Java EE platform (CDI). It comes bundled in some application servers already (namely jboss-6.0.0), so we have chosen that applications
 ----
 {panel}Here is the entire list of steps worked through during this exercise:
  
 # [Download Weld and examples|#step1]
 # [Servers|#step2]
 # [Begin With Weld Examples|#step3]
 # [War deployment|#step3a]
 # [Ear deployment|#step3b]
 # [Add push|#step4]
  
 {panel}
 ----
 h3. {anchor:step1}1. Download Weld and examples:-
 To download Weld the source and binaries, as well as documentation is here:-
 http://seamframework.org/Weld/WeldDistributionDownloads
 Weld is also available from the JBoss Maven Repository. *Maven 3.0* is a requirement, however, it appears that the samples can be built with a combination of Ant and Maven 2.
  
 h3. {anchor:step2}2. Servers
 Currently, it is easiest to test this all out with jboss-6.0.0.Final, but a good idea is to download whatever version is most recent of jboss application server 6.0. Weld is already built into this server and tested regularly.
  
 Weld also supports other containers, including tomcat, Glassfish and Jetty, but be sure to see which containers use jsf2.0.
  
 h3. {anchor:step3}3. Begin with Weld examples.
 Note that Weld requires Ant 1.7.0 to build and deploy the samples. Since the ant scripts perform maven calls for dependencies, simply modify the various pom's to include ICEfaces.
 Final distribution of ICEfaces jars (groupId=org.icefaces), including the ICEfaces component jars, are available on maven central repository, so no modification is required for access to these jars. If you wish to gain access to icepush.jar (groupId=org.icepush), or any of the pre-final release jars, then the addition of the following tag in your pom will gain you access to the snapshots maven repo.
 {code:xml}
  <repositories>
  <repository>
  <id>snapshots</id>
  <url>http://anonsvn.icefaces.org/repo/maven2/snapshots</url>
  </repository>
  </repositories>
 {code}
 Examples follow which show a war deployment and an ear deployment to jboss-6.
  
 h5. {anchor:step3a} a. War deployment Example
  
 Assuming that jboss-6.0.0.Final is the application server used, exclude the jsf jars as a dependency for icefaces-2.0.0.jar for the profile with id of jboss6 and add the following dependencies:-
 {code:xml}
  <dependency>
  <groupId>org.icefaces</groupId>
  <artifactId>icefaces</artifactId>
  <version>2.0.0</version>
  <exclusions>
  <exclusion>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-impl</artifactId>
  </exclusion>
  </exclusions>
  </dependency>
  <dependency>
  <groupId>org.icepush</groupId>
  <artifactId>icepush</artifactId>
  <version>2.0.0</version>
  </dependency>
 {code}
 If ICEfaces push capability is not a requirement, the entry for the icepush jar can be omitted.
  
 One more modification is required. In jsf/numberguess/src/main/webapp/template.xhtml, change the
 {code:xml}head{code} tag to that of {code:xml}h:head{code} and the {code:xml}body{code} tags to{code:xml} h:body{code}.
 If you have modified the build.properties file in the examples root folder to define the jboss.home property, then you may simply run the build.xml ant script in examples/jsf/numberguess, as the default is for jboss6 and will actually deploy the example after building it.
  
 Since numberguess was not designed with ajax (ie: no f:ajax tags), you are getting ajax without any markup at all, just by adding ICEfaces jars to the application. This tutorial does not maximize the benefits of ajax via ICEfaces, but simply adds it to the page. You may notice that the inputText for input of the number you guess is ajax-enabled (once the focus is lost on the input text by tab or enter for example, the number is updated to the backing bean), but the actionListener of the button is not activated. If an <ice:inputText> field is used, then you can trigger an action to do the check and dispose of the button altogether. That information can be reviewed on any ICEfaces example or tutorial.
  
 You can add the component jars (ice or ace) to the application by adding them as dependencies to the pom.xml that you already modified above and place the corresponding namespaces to the page.
  
 h5. {anchor:step3b} b. Ear deployment Example
 Since jee6 (jboss-6.0.0 application server) includes ebj3.1 and JPA2, this means that an ejb jar can now be included in a war deployment. The ear that is included in the weld examples is a standard ear deployment:- examples/jsf/weld-translator which will require the icefaces and icepush jar loaded at the ear level. It is assumed that icepush will be a requirement in this example. If only the icefaces and any of it's component jars are required, then the war level is fine.
  
 In examples/jsf/translator/ear/pom.xml, modify the build target to include the following:-
  
 {code:xml}
  
  <build>
  <finalName>weld-translator</finalName>
  <plugins>
  <plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-ear-plugin</artifactId>
  <configuration>
  <modules>
  <webModule>
  <groupId>org.jboss.weld.examples.jsf.translator</groupId>
  <artifactId>weld-jsf-translator-war</artifactId>
  <contextRoot>/weld-translator</contextRoot>
  </webModule>
  <jarModule>
  <groupId>org.icefaces</groupId>
  <artifactId>icefaces</artifactId>
  <bundleDir>lib</bundleDir>
  </jarModule>
  <jarModule>
  <groupId>org.icepush</groupId>
  <artifactId>icepush</artifactId>
  <bundleDir>lib</bundleDir>
  </jarModule>
  </modules>
  </configuration>
  </plugin>
  </plugins>
  </build>
 {code}
  
 Note that you will still need to refer to the repository and state the dependency as well. This entry just determines the packaging for where the jars are to be located when deployed.
  
 h3. {anchor:step4}6. Add Push.
 Since *icepush.jar* is already included in the numberguess example above, it will be used to show how simple it is to add ICEfaces push capability. No modifications are required to the configuration files (faces-config.xml or web.xml). If the jar is included in the deployed application, then push is available.
  
 Modify the numberguess application to include a StatsModel object, which will include the number of guesses a user (denoted by their sessionId) takes.
 {code:title=StatsModel.java|borderStyle=solid}
 package org.jboss.weld.examples.numberguess;
  
 import java.io.Serializable;
  //just holds the value pairs for example of push
 public class StatsModel implements Serializable {
  private String text;
  private int numberOfGuesses;
  
  public StatsModel() {
  }
  
  public StatsModel(String text, int guesses) {
  this.text = text;
  this.numberOfGuesses = guesses;
  }
  
  public String getText() {
  return text;
  }
  
  public void setText(String text) {
  this.text = text;
  }
  
  public int getNumberOfGuesses() {
  return this.numberOfGuesses;
  }
  
  public void setNumberOfGuesses(int guesses) {
  this.numberOfGuesses = guesses;
  }
  
  public String toString() {
  return text+" with guesses ="+this.numberOfGuesses;
  }
 }
  
 {code}
  
 Create an application-scoped message bean that will track all the entries of StatsModel in a list (once you get 25 records, clear it off and start again since this is only a demo):-
 {code:title=MessageBean.java|borderStyle=solid}
  
 package org.jboss.weld.examples.numberguess;
  
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
  
 import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.event.Observes;
 import javax.inject.Named;
  
 import javax.enterprise.inject.Produces;
  
  
 @ApplicationScoped
 public class MessageBean implements Serializable {
  private static final int MAX_SIZE = 25;
  
  private List<StatsModel> textList = new ArrayList<StatsModel>(0);
  
  public MessageBean() {
  
  }
  
  
  @Produces @Named public List<StatsModel> getTextList() {
  return textList;
  }
  
  
  public void addToList(@Observes StatsModel data){
  textList.add(data);
  if (textList.size() > MAX_SIZE) {
  textList.clear();
  }
  }
  
 }
 {code}
  
 Modify the Game class so the constructor includes the following:-
  
 {code:title=Game.java}
 package org.jboss.weld.examples.numberguess;
  
 import java.io.Serializable;
  
 import javax.annotation.PostConstruct;
 import javax.enterprise.context.SessionScoped;
 import javax.enterprise.inject.Instance;
  
 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIInput;
 import javax.faces.context.FacesContext;
 import javax.inject.Inject;
 import javax.inject.Named;
 //need these imports for PUsh
 import org.icefaces.application.PushRenderer;
 import javax.servlet.http.HttpSession;
  
 import javax.enterprise.event.Event;
 import javax.enterprise.inject.Any;
  
  
  
 @Named
 @SessionScoped
 public class Game implements Serializable
 {
  /**
  *
  */
  private static final long serialVersionUID = 991300443278089016L;
  //add this line for name of push group
  private static final String PUSH_GROUP = "stats";
  private String sessionId;
  
  private int number;
  
  private int guess;
  private int smallest;
  
  
  /* inject an event in to trigger when a StatsModel object can be created and added
  to the list in MessageBean class */
  @Inject @Any Event<StatsModel> statsEvent;
  
  @Inject @MaxNumber
  private int maxNumber;
  
  private int biggest;
  private int remainingGuesses;
  
  @Inject @Random Instance<Integer> randomNumber;
  
  public Game()
  {
  //add some stuff for push and getting sessionID to create StatsModel object to push
  PushRenderer.addCurrentSession(PUSH_GROUP);
  FacesContext fc = FacesContext.getCurrentInstance();
  HttpSession session = (HttpSession)fc.getExternalContext().getSession(false);
  sessionId = session.getId();
  }
  
  public int getNumber()
  {
  return number;
  }
  
  public int getGuess()
  {
  return guess;
  }
  
  public void setGuess(int guess)
  {
  this.guess = guess;
  }
  
  public int getSmallest()
  {
  return smallest;
  }
  
  public int getBiggest()
  {
  return biggest;
  }
  
  public int getRemainingGuesses()
  {
  return remainingGuesses;
  }
  
  public void check()
  {
  if (guess > number)
  {
  biggest = guess - 1;
  }
  else if (guess < number)
  {
  smallest = guess + 1;
  }
  else if (guess == number)
  {
  FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
  /*we now have the information to create our StatsModel object so trigger an
  event to update the list*/
  statsEvent.fire(new StatsModel(sessionId, 10-remainingGuesses));
  /* trigger the push */
  PushRenderer.render(PUSH_GROUP);
  }
  remainingGuesses--;
  }
  
  @PostConstruct
  public void reset()
  {
  this.smallest = 0;
  this.guess = 0;
  this.remainingGuesses = 10;
  this.biggest = maxNumber;
  this.number = randomNumber.get();
  }
  
  public void validateNumberRange(FacesContext context, UIComponent toValidate, Object value)
  {
  
  if (remainingGuesses <= 0)
  {
  FacesMessage message = new FacesMessage("No guesses left!");
  context.addMessage(toValidate.getClientId(context), message);
  ((UIInput) toValidate).setValid(false);
  return;
  }
  int input = (Integer) value;
  
  if (input < smallest || input > biggest)
  {
  ((UIInput) toValidate).setValid(false);
  
  FacesMessage message = new FacesMessage("Invalid guess");
  context.addMessage(toValidate.getClientId(context), message);
  }
  }
   /** remove this session from the render group when the bean is
  * no longer around
  */
  @PreDestroy
  public void destroy(){
  PushRenderer.removeCurrentSession(PUSH_GROUP);
  }
 }
 {code}
  
  

© Copyright 2017 ICEsoft Technologies Canada Corp.