问题
We are migrating JSF 1.1 (MyFaces) project to JSF 2. The idea is to migrate periodically by keeping both JSP and XHTML together for some time. We use many ajax4jsf-1.1.1 tags in JSP pages. We don't use RichFaces. After configuring the system to JSF 2 (with all config changes mentioned in tutorial by Balusc) When tried to access the JSP page with ajax4jsf.jar in classpath, we get an exception:
Caused by: java.lang.IllegalStateException: setViewHandler may not be executed after a lifecycle request has been completed
at org.apache.myfaces.application.ApplicationImpl.setViewHandler(ApplicationImpl.java:853)
at org.ajax4jsf.framework.ajax.InitPhaseListener.beforePhase(InitPhaseListener.java:92)
at org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersBefore(PhaseListenerManager.java:76)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:131)
It looks ajax4jsf.jar is not compatible with JSF 2. Looks some issue with LifeCycle configuration.
Is there any way we can make a4j work with JSF 2 JSPs? I know when we use XHTML we don't need all this.
回答1:
Get rid of Ajax4jsf 1.x altogether. It's indeed not compatible with JSF2. Instead, JSF2 offers a new main ajax tag <f:ajax>
which covers all the core functionality as previously offered by Ajax4jsf 1.x.
If upgrading to RichFaces 4 is not an option (because, as you said yourself, you aren't using RichFaces components anywhere), then just remove Ajax4jsf 1.x and replace all <a4j:xxx>
tags by standard JSF2 equivalents.
<a4j:ajaxListener>
: use<f:ajax listener>
.<a4j:keepAlive>
: just put managed bean in the view scope by@ViewScoped
.<a4j:log>
: usejsf.ajax.addOnEvent()
orjsf.ajax.addOnError()
in JS context.<a4j:commandLink>
: just nest<f:ajax>
inside<h:commandLink>
.<a4j:outputPanel>
: use<h:panelGroup>
and remember to include its ID in<f:ajax render>
or PrimeFaces <p:outputPanel>.<a4j:repeat>
: just use standard<ui:repeat>
.<a4j:form>
: just use<h:form>
, it will autorecognize<f:ajax>
.<a4j:htmlCommandLink>
: just nest<f:ajax>
inside<h:commandLink>
.<a4j:jsFunction>
: no replacement. Consider OmniFaces <o:commandScript> or PrimeFaces <p:remoteCommand>.<a4j:region>
: just use<f:ajax execute>
, you can even wrap<f:ajax>
around a group of components.<a4j:loadBundle>
: just use standard<f:loadBundle>
.<a4j:status>
: usejsf.ajax.addOnEvent()
orjsf.ajax.addOnError()
in JS context.<a4j:actionparam>
: just use standard<f:param>
.<a4j:loadScript>
: just use standard<h:outputScript>
.<a4j:mediaOutput>
: no replacement. Consider PrimeFaces <p:media>.<a4j:poll>
: no replacement. Consider OmniFaces <o:commandScript> or PrimeFaces <p:poll>.<a4j:commandButton>
: just nest<f:ajax>
inside<h:commandButton>
.<a4j:include>
: just use standard<ui:include>
.<a4j:loadStyle>
: just use standard<h:outputStylesheet>
.<a4j:support>
: just use standard<f:ajax>
.
You also need to rename/rewrite JSP files to Facelets files. In simple cases, this is usually just a matter of changing root declarations and file extensions. Facelets makes it easier to replace all duplicated code by a single template. The following answer applies:
- Migrating from JSF 1.2 to JSF 2.0
来源:https://stackoverflow.com/questions/17553033/migrating-jsf-1-1-with-ajax4jsf-1-x-to-jsf-2