some comparison on JSF and GWT

GWT and JSF are very different technologies and one of the major differencies is in server state : in GWT is generally none and in JSF full.
That means that JSF in one request/response perform on server component tree build and this build takes some time. GWT normally holds complete state in client (in compiled mode), in javascript components and communicate with server only with object serialized to JSON [1]

Google designed GWT in this way: to distribute GUI components on clients with minimalistic server side state. This solution is very fast. Although I’m a JSF fan, for many many users would I use GWT :). But GWT solution has also disadvantages: it is very slow in old browses (because of tons of javascript) and very unmaintainable for large application with many views and complex GUI : java syntax is very verbose for GUIs (compared with xhtml facelets files)

enable / disable a JSF Command Button

primeface page goes like this,

 <p:commandButton update="panel1"  actionListener="#{bean.button1}" value="button1" disabled="#{bean.disable}"> 
     <f:setPropertyActionListener value="#{false}" target="#{bean.disable}"/>   
 </p:commandButton> 


 <p:commandButton update="panel2"  actionListener="#{bean.button2}" value="button1" disabled="#{!(bean.disable)}"> 
     <f:setPropertyActionListener value="#{true}" target="#{bean.disable}"/>    
 </p:commandButton> 

Manage Bean:

 public class Bean {

    private boolean disable;

    // default constructor 
    public Bean(){
       this.disable= false;
    }

    public boolean isDisable() {
       return disable;
    }
    public void setDisable(boolean disable) {
       this.disable = disable;
    }
}

 

Persist and pass FacesMessages over multiple page redirects

Very Simple

In a JSF Reference Implementation, passing global faces messages between pages doesn’t work. It’s not designed that way “out of the box.” Fortunately there is a way to do this, which will even support redirects between pages, forwards through a RequestDispatcher, and also through standard JSF navigation cases.

There is a 5 minute solution to this problem.

Messages should be displayed IF:

  • …the RENDER_RESPONSE phase has been reached, and JSF completed all phases “naturally.” This means that messages should not be displayed if the HttpResponse has been completed BEFORE the RENDER_RESPONSE phase has been reached.
  • …the RENDER_RESPONSE phase is reached, and the HttpResponse is already completed, then FacesMessages could not have been rendered; they need to be saved again for the next RENDER_RESPONSE phase.

I found an almost solution to this problem in a mailing list that I’ve long since forgotten, but I saved the original accreditation, fixed the bugs (messages would not originally save through a redirect,) and here you go.

It’s a MultiPageMessagesSupport PhaseListener:

Copy this file into your project classpath.

package com.yoursite.jsf;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

/**
 * Enables messages to be rendered on different pages from which they were set.
 *
 * After each phase where messages may be added, this moves the messages
 * from the page-scoped FacesContext to the session-scoped session map.
 *
 * Before messages are rendered, this moves the messages from the
 * session-scoped session map back to the page-scoped FacesContext.
 *
 * Only global messages, not associated with a particular component, are
 * moved. Component messages cannot be rendered on pages other than the one on
 * which they were added.
 *
 * To enable multi-page messages support, add a &lt;code&gt;lifecycle&lt;/code&gt; block to your
 * faces-config.xml file. That block should contain a single
 * &lt;code&gt;phase-listener&lt;/code&gt; block containing the fully-qualified classname
 * of this file.
 *
 * @author Jesse Wilson jesse[AT]odel.on.ca
 * @secondaryAuthor Lincoln Baxter III lincoln[AT]ocpsoft.com 
 */
public class MultiPageMessagesSupport implements PhaseListener
{

    private static final long serialVersionUID = 1250469273857785274L;
    private static final String sessionToken = "MULTI_PAGE_MESSAGES_SUPPORT";

    public PhaseId getPhaseId()
    {
        return PhaseId.ANY_PHASE;
    }

    /*
     * Check to see if we are "naturally" in the RENDER_RESPONSE phase. If we
     * have arrived here and the response is already complete, then the page is
     * not going to show up: don't display messages yet.
     */
    // TODO: Blog this (MultiPageMessagesSupport)
    public void beforePhase(final PhaseEvent event)
    {
        FacesContext facesContext = event.getFacesContext();
        this.saveMessages(facesContext);

        if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
        {
            if (!facesContext.getResponseComplete())
            {
                this.restoreMessages(facesContext);
            }
        }
    }

    /*
     * Save messages into the session after every phase.
     */
    public void afterPhase(final PhaseEvent event)
    {
        if (!PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
        {
            FacesContext facesContext = event.getFacesContext();
            this.saveMessages(facesContext);
        }
    }

    @SuppressWarnings("unchecked")
    private int saveMessages(final FacesContext facesContext)
    {
        List&lt;FacesMessage&gt; messages = new ArrayList&lt;FacesMessage&gt;();
        for (Iterator&lt;FacesMessage&gt; iter = facesContext.getMessages(null); iter.hasNext();)
        {
            messages.add(iter.next());
            iter.remove();
        }

        if (messages.size() == 0)
        {
            return 0;
        }

        Map&lt;String, Object&gt; sessionMap = facesContext.getExternalContext().getSessionMap();
        List&lt;FacesMessage&gt; existingMessages = (List&lt;FacesMessage&gt;) sessionMap.get(sessionToken);
        if (existingMessages != null)
        {
            existingMessages.addAll(messages);
        }
        else
        {
            sessionMap.put(sessionToken, messages);
        }
        return messages.size();
    }

    @SuppressWarnings("unchecked")
    private int restoreMessages(final FacesContext facesContext)
    {
        Map&lt;String, Object&gt; sessionMap = facesContext.getExternalContext().getSessionMap();
        List&lt;FacesMessage&gt; messages = (List&lt;FacesMessage&gt;) sessionMap.remove(sessionToken);

        if (messages == null)
        {
            return 0;
        }

        int restoredCount = messages.size();
        for (Object element : messages)
        {
            facesContext.addMessage(null, (FacesMessage) element);
        }
        return restoredCount;
    }
}

Configuration:

This needs to be in your faces-config.xml.

		<phase-listener>
			com.yoursite.jsf.MultiPageMessagesSupport
		</phase-listener>

That’s it. You’re done.

From HERE

Struts2 or JSF2

Struts 2 is an Action Framework whereas JSF is a Component Framework.

An Action Framework is intimately tied to the HTTP request cycle and request format. A Component Framework tends to hide the underly HTTP request and use its own, higher level abstraction.

Action Frameworks tend to work better in stateless environments, Component Framework typically have a lot of session state associated with them.

If you’re going to do a “web site”, where URLs are important, lots of read only, higher loads of simpler traffic, etc. then an Action Framework may be more suitable.

If its a back office application, lots of CRUD screens, not as many users, complicated page and workflows, lots of page component interaction, then a Component Framework will be more suitable.

Both frameworks can do both jobs, just some are easier for the coder than the other for certain tasks.

 

 

 

jsp jsf xhtml faces url-pattern

JSP is an old view technology and widely used in combination with JSF 1.x. Facelets (XHTML) is the successor of JSP and introduced as default view technology of JSF 2.x at end of 2009. When you were seeing JSPs, you were perhaps reading old/outdated books/tutorials/resources targeted on JSF 1.x. You should generally ignore them when developing with JSF 2.x and head to resources targeted on JSF 2.x, otherwise you may end up in confusion because many things are done differently in JSF 2.x on Facelets.

The *.jsf is just one of widely used URL patterns of the FacesServlet mapping in web.xml. Other ones are *.faces and /faces/*. They all do not represent the concrete file extension/path, but just a virtual file extension/path and is to be specified in URLs only like sohttp://localhost:8080/contextname/page.jsf. This way the FacesServlet will be invoked. When using JSPs, this would actually serve page.jsp. When using Facelets, this would actually servepage.xhtml.

Since JSF 2.x you can also use *.xhtml as URL pattern. This way you don’t need to get confused when specifying URLs. Using *.xhtml as URL pattern was not possible in JSF 1.x with Facelets 1.x, because the FacesServlet would then run in an infinite loop calling itself everytime. An additional advantage of using *.xhtml is that the enduser won’t be able to see raw JSF source code whenever the enduser purposefully changes the URL extension in browser address bar from for example .jsf to.xhtml.

 

 

The .jsf extension is where the FacesServlet is often by default mapped on in the web.xml.

<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>

The .xhtml extension is of the actual Facelets file as you’ve physically placed in the webcontent of your webapp, e.g. Webapp/WebContent/page.xhtml.

If you invoke this page with the .jsf extension, e.g. http://localhost:8080/webapp/page.jsf then theFacesServlet will be invoked, locate the page.xhtml file and parse/render its JSF components.

Sometimes a *.faces extension or /faces/* foldermapping is been used. But this was from back in the JSF 1.0/1.1 ages. You’re free to choose and use whatever mapping you’d like to let FacesServletlisten on, even if it’s a nothing-saying *.xyz. The actual page itself should always have the .xhtmlextension, but this is configureable by the following <context-param> in web.xml:

<context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xml</param-value>
</context-param>

This will change the FacesServlet to locate page.xml instad of (default) page.xhtml.

hack css in primefaces

Create a style sheet file:

/resources/css/default.css

You need to ensure that you load the stylesheet by <h:outputStylesheet> the usual way. This will ensure that the stylesheet is loaded after the PrimeFaces’ default styles.

<h:head>     <h:outputStylesheet name="css/default.css" /> </h:head>

You also need to ensure that your CSS selector is at least as specific as the PrimeFaces’ default CSS selector on the particular element. You need to understand cascading, inheritance and override rules. For example, if PrimeFaces declares a style by default as follows

.ui-foo .ui-bar {     color: pink; } 

and you declare it as

.ui-bar {     color: purple; } 

and the particular element with class="ui-bar" happen to have a parent element with class="ui-foo", then the PrimeFaces’ one will still get precedence because that’s the most specific match! True, there’s always the !important workaround, but that’s plain ugly and confuses your style rules and yourself only more. You can use the webbrowser developer tools to find the exact CSS selector.

 

PS: primefeces uses jquery ui Icons: A cheat sheet for all the icon names.

create ajax State-City of U.S selection in Primefaces

Steps:
  1. get all state, city info of U.S from HERE . There are also many other data could be freely download from this site.
  2. dump the dbf file to sql.
  3. create tables in mysql and import all data
  4. create UI and backing beans for the data.

UI:

<h:outputLabel for="state" value="state: *" />

<p:selectOneMenu id="state" value="#{userManager.potentialUser.state}">

<f:selectItem itemLabel="Select State" itemValue="" />

<f:selectItems value="#{stateCityManager.states}" />

<p:ajax<span style="color: #ff0000;"> update="city" </span>listener="#{stateCityManager.handleStateChange}" />

</p:selectOneMenu>

<h:outputLabel for="city" value="city: *" />

<p:selectOneMenu id="city" value="#{userManager.potentialUser.city}">

<f:selectItem itemLabel="Select City" itemValue="" />

<f:selectItems value="#{stateCityManager.cities}" />

</p:selectOneMenu>

Spring Bean:

@Component("stateCityManager")

@Scope("session")

public class StateCityManager {

public StateCityManager() {

}

@Inject

StateCityDao stateCityDao;

private List&lt;String&gt; states;

private List&lt;String&gt; cities;

private UserManager userManager;

public UserManager getUserManager() {

return userManager;

}

@Autowired

public void setUserManager(UserManager userManager) {

this.userManager = userManager;

}

//private String state = userManager.getPotentialUser().getState();    //can not use a private field to connect values between components, otherwise NPE.

@PostConstruct

public void init() {

loadStates();

}

public void loadStates(){

states = stateCityDao.getAllStates();

cities = new ArrayList&lt;String&gt;();

}

<span style="color:#ff0000;">public void handleStateChange() {  </span>

<span style="color:#ff0000;">        if(userManager.getPotentialUser().getState() !=null &amp;&amp; !userManager.getPotentialUser().getState().equals(""))  </span>

<span style="color:#ff0000;">            cities = stateCityDao.getCitiesByState(userManager.getPotentialUser().getState());  </span>

<span style="color:#ff0000;">        else  </span>

<span style="color:#ff0000;">            cities = new ArrayList&lt;String&gt;();  </span>

<span style="color:#ff0000;"> }  </span>}

 </div>
 <div></div>
 <div></div>
 <div>DAO</div>
 <div>
@Repository

@Transactional

public class StateCityDaoImpl extends BaseDaoImpl implements StateCityDao {

@Override

public List&lt;String&gt; getAllStates() throws DataAccessException {

@SuppressWarnings("unchecked")

List&lt;String&gt; results = em.createNamedQuery("StateCity.findAllStates").getResultList();

if (results == null) {

results = new ArrayList&lt;String&gt;();

}

return results;

}

@Override

public List&lt;String&gt; getCitiesByState(String state)

throws DataAccessException {

@SuppressWarnings("unchecked")

List&lt;String&gt; results = em.createNamedQuery("StateCity.findCitiesByState").setParameter("state", state).getResultList();

if (results == null) {

results = new ArrayList&lt;String&gt;();

}

return results;

}

}