Using ICEfaces with CDI

Table of Contents

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


Here is the entire list of steps worked through during this exercise:

  1. Download Weld and examples
  2. Servers
  3. Begin With Weld Examples
  4. War deployment
  5. Ear deployment
  6. Add push

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.

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.

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.

   <repositories>
        <repository>
           <id>snapshots</id>
           <url>http://anonsvn.icefaces.org/repo/maven2/snapshots</url>
        </repository>
   </repositories>

Examples follow which show a war deployment and an ear deployment to jboss-6.

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:-

          <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>

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

head
tag to that of
h:head
and the
body
tags to
 h:body
.
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.

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:-


   <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>

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.

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.

StatsModel.java
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;
	}
}

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):-

MessageBean.java

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();
		}
    }

}

Modify the Game class so the constructor includes the following:-

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);
    }
}

A few things to note are the @Event and @Observes annotations that Weld provides. Also check out the @Produces on the @ApplicationScoped MessageBean class. Weld documentation is included in the bundled distribution that the samples came in, if you don't know what these annotations represent. When given a choice with the same annotation in jsf or Weld, choose the Weld (like @ApplicationScoped) import. Will make life easier.

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

© Copyright 2018 ICEsoft Technologies Canada Corp.