A Simple JSF Tutorial with PrimeFaces and JSON Object Parsing in Java

In this tutorial, you will see an example of parsing JSON objects containing exchange rates for certain currencies and displaying them on a web page using JSF 2.1 and PrimeFaces 2.2 which is a rich-component framework for JSF adding AJAX and Web 2.0 capabilities to your web application.

What you need for this tutorial

  • Oracle JDK 1.6 or later
  • Netbeans 7.0 or later (if you choose a different IDE, you will need to manually get the necessary libraries and components for this tutorial. See the following section)
  • Tomcat 7

Technologies and libraries used

  • JSF 2.1 (Mojarra 2 libraries a.k.a. jsf-api.jar, jsf-impl.jar, jstl.jar and standard.jar)
  • PrimeFaces 2.2.1
  • JSON (for Java)
  • commons-logging-1.1.1.jar
  • log4j-1.2.16.jar
  • httpcore-4.1.4.jar
  • httpclient-4.1.3.jar

Setting up the Project with JSF 2 and PrimeFaces Support

Launch Netbeans, and then go along the following steps:

  1. Choose New Project (Ctrl-Shift-N; ⌘-Shift-N on Mac) from the File menu. Select the Java Web category, then under Projects select Web Application. Click Next.
  2. In the Project Name field type ‘exchangeratesweb’ (without the quotes), and click Next.
  3. Netbeans - New > Java Web ApplicationIn this step, make sure the platform is selected as Java EE 6 and deselect the option ‘Enable contexts and dependency injection’ and also select Apache Tomcat 7 from the Server drop-down menu. Click Next
    Netbeans - Java EE 6 web application - Exchange Rates
  4. Select Java Server Faces from the list of Frameworks, then in the Libraries tab under the Java Server Faces Configuration, select JSF 2.1 from the Registered Libraries option (whose radio button must also be chosen).Netbeans > Frmaeworks > JSF
  5. Go to the Configuration tab now, and select “Facelets” as the preferred page language, and optionally specify the JSF Servlet URL pattern as ‘*.go’. (The most typical extension used by JSF developers is ‘*.jsf’ whereas in Sun’s legacy blueprints it would be ‘/faces/*’ which also comes as default. )JSF Configuration in Netbeans
  6. Finally open the Components tab and select PrimeFaces 2.2.1, and then click Finish.
  7. Now we’ll create a JSF Managed Bean which will be used as a controller for the entire project. Right-click the project (exchangeratesweb) and select New > JSF Managed Bean… from the pop-up menu. (If this item does not show up in the drop-down menu, select Other… and then JavaServer Faces > JSF Managed Bean in the pop-up window titled New File).New > JSF Managed Bean in NetBeans
  8. Name the managed bean class ‘ExchangeRatesBean‘ (without the quotes), type ‘net.ozar.egitim.jsf.kurlar.managed‘ for the package name, specify the bean name ‘exchangeRatesBean‘ and select ‘application‘ for the scope from the drop-down list. Specifying the Managed Bean settings in NetBeansClick Finish when you’re done.
  9. Enter the following code in the class source:
    package net.ozar.egitim.jsf.kurlar.managed;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.Calendar;
    import javax.annotation.PostConstruct;
    import javax.faces.application.FacesMessage;
    import javax.faces.bean.ApplicationScoped;
    import javax.faces.bean.ManagedBean;
    import javax.faces.context.FacesContext;
    import net.ozar.egitim.jsf.kurlar.pojo.ExchangeRate;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.log4j.Level;
    import org.apache.log4j.Logger;
    import org.json.JSONObject;
    
    /**
     * @author Gökhan Ozar
     * http://gokhan.ozar.net
     */
    @ManagedBean
    @ApplicationScoped
    public class ExchangeRatesBean implements java.io.Serializable {
        private static final String ERURL  = "http://openexchangerates.org/latest.json";
        private static final String APPINFO = "This application is intended as a simple tutorial example on JSF 2, PrimeFaces 2 (Web 2.0 &amp; AJAX) and JSON object parsing. Visit <a href="\&quot;http://gokhan.ozar.net\&quot;">http://gokhan.ozar.net</a> for more...  
    ";
    
        private ExchangeRate erate = new ExchangeRate();
        private String msj = "";
    
        public ExchangeRatesBean() {
        }
    
        @PostConstruct
        public void kurlariYukle() {
    
            HttpClient webIstemci = new DefaultHttpClient();
            HttpGet webdenGetir = new HttpGet(ERURL);
            HttpResponse donenCevap;
    
            try {
                donenCevap = webIstemci.execute(webdenGetir); // Getting the web (HTML) response from the URL
                HttpEntity birim = donenCevap.getEntity(); // Setting the HttpEntity to the Http Response object
                if (birim != null) {
                    InputStream gelenVeri = birim.getContent();
                    String sonuc = convertStreamToString(gelenVeri);
    
                    JSONObject json = new JSONObject(sonuc);
                    JSONObject currs = json.getJSONObject("rates");
    
                    msj = APPINFO.concat(json.getString("license" ));
    
                    erate.setBaseCurrency(json.getString("base" ));
                    erate.setEur         (currs.getDouble("EUR"));  // Euro
                    erate.setGbp         (currs.getDouble("GBP"));  // British Pound Sterling
                    erate.setJpy         (currs.getDouble("JPY"));  // Japanese Yen
                    erate.setCad         (currs.getDouble("CAD"));  // Canadian Dollars
                    erate.setMxn         (currs.getDouble("MXN"));  // Mexican Pezo
                    erate.setAed         (currs.getDouble("AED"));  // United Arab Emirates Dirham
                    erate.setTrl         (currs.getDouble("TRY"));  // Turkish Lira
    
                    long t = json.getLong("timestamp"); // getting the last update date &amp; time 
    
                    Calendar cal = Calendar.getInstance(); 
                    cal.setTimeInMillis(t*1000); // converting into a human-readable date format
    
                    erate.setLastModif(cal.getTime());
    
                    erate.setDisclaimer(json.getString("disclaimer").concat(APPINFO.replaceAll("\\", ""))); // Getting the disclaimer and stripping the HTML tags from the APPINFO String before concatenating it
                    erate.setMesaj         (msj);
    
                    FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msj, msj);
                    FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);
    
                    gelenVeri.close();
                }
            } catch (Exception e) {
                msj= "Loading the exchange rates failed!\nThere appears to be a problem with the server connection.";
                erate.setMesaj(msj);
                Logger.getLogger(ExchangeRatesBean.class.getName()).log(Level.ERROR, null, e);
                FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msj, msj);
                FacesContext.getCurrentInstance().addMessage(null, facesMsg);
            }
    
        }
    
        public String convertStreamToString(InputStream is) {
            // The incoming input stream is accumulated in a String to be returned
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
            } catch (IOException e) {
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            return sb.toString();
        }
    
        // Managed bean getter &amp; setter for the sake of abstraction
    
        public ExchangeRate getErate() {
            return erate;
        }
    
        public void setErate(ExchangeRate erate) {
            this.erate = erate;
        }
    }
  10. Now we need a POJO (plain old Java object) to hold the exchange rate data which will be acquired via JSON.Create a new Java class named ExchangeRate.java in a package called net.ozar.egitim.jsf.kurlar.pojo and enter the following code into its source:
    package net.ozar.egitim.jsf.kurlar.pojo;
    
    import java.util.Date;
    
    /**
     * @author Gökhan Ozar
     * http://gokhan.ozar.net
     */
    public class ExchangeRate implements java.io.Serializable {
    
        private String baseCurrency;
        private Double usd; // US dollar
        private Double gbp; // British Pound Sterling
        private Double eur; // Euro
        private Double jpy; // Japanese Yen
        private Double trl; // Turkish Lira "TRY"
        private Double cad; // Canadian Dollar
        private Double mxn; // Mexican Pezo
        private Double aed; // United Arab Emirates Dirham
    
        private Date lastModif;
        private String disclaimer;
        private String license;
        private String mesaj;
    
        public String getBaseCurrency() {
            return baseCurrency;
        }
    
        public void setBaseCurrency(String baseCurrency) {
            this.baseCurrency = baseCurrency;
        }
    
        public Double getEur() {
            return eur;
        }
    
        public void setEur(Double eur) {
            this.eur = eur;
        }
    
        public Date getLastModif() {
            return lastModif;
        }
    
        public void setLastModif(Date lastModif) {
            this.lastModif = lastModif;
        }
    
        public String getMesaj() {
            return mesaj;
        }
    
        public void setMesaj(String mesaj) {
            this.mesaj = mesaj;
        }
    
        public Double getUsd() {
            return usd;
        }
    
        public void setUsd(Double usd) {
            this.usd = usd;
        }
    
        public String getDisclaimer() {
            return disclaimer;
        }
    
        public void setDisclaimer(String disclaimer) {
            this.disclaimer = disclaimer;
        }
    
        public String getLicense() {
            return license;
        }
    
        public void setLicense(String license) {
            this.license = license;
        }
    
        public Double getAed() {
            return aed;
        }
    
        public void setAed(Double aed) {
            this.aed = aed;
        }
    
        public Double getCad() {
            return cad;
        }
    
        public void setCad(Double cad) {
            this.cad = cad;
        }
    
        public Double getGbp() {
            return gbp;
        }
    
        public void setGbp(Double gbp) {
            this.gbp = gbp;
        }
    
        public Double getJpy() {
            return jpy;
        }
    
        public void setJpy(Double jpy) {
            this.jpy = jpy;
        }
    
        public Double getMxn() {
            return mxn;
        }
    
        public void setMxn(Double mxn) {
            this.mxn = mxn;
        }
    
        public Double getTrl() {
            return trl;
        }
    
        public void setTrl(Double trl) {
            this.trl = trl;
        }
    }
  11. Now go to the Web Pages in the project folder and double-click index.xhtml. Modif its source code so as to match the following:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:p="http://primefaces.prime.com.tr/ui"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>Exchange Rates</title>
    </h:head>
    <h:body>
        <h:form>
            <p:commandButton value="Display the rates" onclick="dlg1.show();" type="button" />
            <p:commandButton id ="ref" value="Refresh" ajax="true" action="#{exchangeRatesBean.kurlariYukle}" type="submit" update="dovizKurPaneli, dovizKurPaneli2" />
            <p:dialog id="dlg" header="Exchange Rates" widgetVar="dlg1" width="500">
                <p:panel id="dovizKurPaneli">
                    <h:panelGrid columns="2">
                        #{exchangeRatesBean.erate.baseCurrency} 1.00 :  <h:outputText value="GBP #{exchangeRatesBean.erate.gbp}" /> 
                        #{exchangeRatesBean.erate.baseCurrency} 1.00 :  <h:outputText value="EUR #{exchangeRatesBean.erate.eur}" />
                        #{exchangeRatesBean.erate.baseCurrency} 1.00 :  <h:outputText value="JPY #{exchangeRatesBean.erate.jpy}" />
                        #{exchangeRatesBean.erate.baseCurrency} 1.00 :  <h:outputText value="CAD #{exchangeRatesBean.erate.cad}" />
                        #{exchangeRatesBean.erate.baseCurrency} 1.00 :  <h:outputText value="MXN #{exchangeRatesBean.erate.mxn}" />
                        #{exchangeRatesBean.erate.baseCurrency} 1.00 :  <h:outputText value="AED #{exchangeRatesBean.erate.aed}" />
                    </h:panelGrid>
                    <br />
                    <p:panel>
                        Last update: <h:outputText value="#{exchangeRatesBean.erate.lastModif}"><f:convertDateTime pattern="MM/dd/yyyy HH:mm" /></h:outputText>
                        <br /><br />
                        <h:outputText value="#{exchangeRatesBean.erate.disclaimer}" />
                    </p:panel>
                </p:panel>
            </p:dialog>
            <p:messages />
        </h:form>
    </h:body>
</html>

You can download a zip archive containing all the jar files of the used libraries here:
GO JSF2-PrimeFaces2-JSON-HttpClient libraries (1463)

And you can access the finished application here:
http://exchangeratesweb.gozar.cloudbees.net/index.go

Here is a screenshot from the finished application:

Be Sociable, Share!

11 thoughts on “A Simple JSF Tutorial with PrimeFaces and JSON Object Parsing in Java

    • A Managed Bean is instantiated as soon as a JSF action references a method contained in it, in the case of the ExchangeRatesBean, it’s invoked as index.xhtml is called in the browser.

    • Sure. The main strategy here is pulling the exchange rate data once and providing that very data to all visitors (until someone invokes the Refresh action, which will benefit every new visitor) as there’s a very very little chance that there would be dramatic changes in the rates. You could change to scope of the managed bean to “session” (i.e. @SessionScoped) or even lower the scope as low as to the “request” (@RequestScoped) but I didn’t want to add extra load to the service (data) provider for a free service and therefore chose to avoid pissing them off.

  1. Primefaces action commands does not function on cloudbees, though it is all wirk on local machine with the same server version. What could cause to this?

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">