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)

Advertisements

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

p:commandButton needs two clicks to fire action primefaces

I need to click my button twice to fire an action.

There seems to be a depency on the navigation of the site that’s calling this page.
If the previous navigation is done by a <p:button outcome=”next_page”> the button on “next_page” reacts on the first click.
Using <p:commandButton action=”next_page”> i need two clicks on “next_pages”‘s button…….

 

So the problem is the previous page. put “pageName?faces-redirect=true” in previous navigation would solve the problem.

JSF 2.0: actionListener action in primefaces with setPropertyActionListener

Today I had a problem with a PrimeFaces-CommandButton which has a setPropertyActionListener and an actionListener attached to it.

The problem was that the actionListener is called before the setPropertyActionListener, which resulted in the behavior that the Method could only access the set property the second time it got executed.

Replacing the actionListener with an action did the trick (while the action-Method returns null, so there’s no page-transition).

I still don’t know if this is an expected behavior, but it does work, so I’ll stick with this for now.

JSF Implementation is Mojarra 2.0.4-b09 with PrimeFaces 3

 

Finally got the answer:

The actionListener runs always before theaction. If there are multiple action listeners, then they run in the same order as they have been registered.

 <f:setPropertyActionListener> is one kind of actionListener . In general,actionListener always get fired before action. That’s why it always work with action.

In my case

<p:commandButton id=”selectButton” actionListener=”#{gameManager.onRowSelect}”  title=”Join” value=”Join”>

<f:setPropertyActionListener value=”#{game}” target=”#{gameManager.currentGame}” />

</p:commandButton>

The onRowSelect will always be executed before the currentGame value being set. Therefore, change it to action would work.

primemobile view navigate data not updated

if you have 2 view in a xhtml, 1st view do the calculation and 2nd view display the result of the calculation.

Then the 2nd view would not updated because the page is pre-generated .

For now I have to use two different page for this, have not found a way using “update” for another view. update in commandButton is good for update component within the same view though.

2012/6/24

Got the solution just now. Actually very easy, just add the red part.

<p:commandButton value=”Submit” action=”#{surveyManager.calculate}” update=”:resultDisplay”/>   //if in the same view, just add the id to update

//This is in another view

<h:outputText id=”resultDisplay” value=”#{surveyManager.finalScore}” />