Showing posts with label JSF. Show all posts
Showing posts with label JSF. Show all posts

Thursday, September 8, 2011

Problems with Mojarra

In recent Mojarra versions, there was always a problem. JBoss AS 7 comes with Mojarra version 2.0.4-b09. Once the tag a4j:ajax will be used on JSF components you receive the following error message:
javax.faces.FacesException: Unexpected error restoring state for component with id form:inputComponent:input.  Cause: java.lang.ClassCastException: javax.faces.component.StateHolderSaver cannot be cast to [Ljava.lang.Object;.
    at com.sun.faces.application.view.StateManagementStrategyImpl$1.visit(StateManagementStrategyImpl.java:273)
    at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1485)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)
    at javax.faces.component.UIForm.visitTree(UIForm.java:335)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)
    at com.sun.faces.component.visit.VisitUtils.doFullNonIteratingVisit(VisitUtils.java:75)
    at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:257)
    at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:181)
    at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:448)
    at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:148)
    at com.ocpsoft.pretty.faces.application.PrettyViewHandler.restoreView(PrettyViewHandler.java:109)
    at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:288)
    at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:288)
    at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:288)
    at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:187)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:111)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:118)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.jboss.seam.servlet.exception.CatchExceptionFilter.doFilter(CatchExceptionFilter.java:65)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.jboss.seam.servlet.event.ServletEventBridgeFilter.doFilter(ServletEventBridgeFilter.java:72)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:139)
    at org.jboss.as.web.NamingValve.invoke(NamingValve.java:57)
    at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:49)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:154)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:667)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:952)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassCastException: javax.faces.component.StateHolderSaver cannot be cast to [Ljava.lang.Object;
    at org.ajax4jsf.component.behavior.AjaxBehavior.restoreState(AjaxBehavior.java:343)
    at javax.faces.component.UIComponentBase.restoreBehaviors(UIComponentBase.java:2056)
    at javax.faces.component.UIComponentBase.restoreBehaviorsState(UIComponentBase.java:2023)
    at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1443)
    at javax.faces.component.UIOutput.restoreState(UIOutput.java:256)
    at javax.faces.component.UIInput.restoreState(UIInput.java:1379)
    at com.sun.faces.application.view.StateManagementStrategyImpl$1.visit(StateManagementStrategyImpl.java:265)
    ... 51 more

The workaround
The best way to solve this problem, is to switch Mojarra version back to 2.0.2-b10. Download the package from the Mojarra repository. Extract zip file and drop the jsf-impl-2.0.2-b10.jar into:
/your/path/jboss-as-web-7.0.1.Final/modules/com/sun/jsf-impl/main 
Change the module.xml in the same directory to:
<module xmlns="urn:jboss:module:1.0" name="com.sun.jsf-impl">
    <dependencies>
        <module name="javax.faces.api"/>
        <module name="javaee.api"/>
        <module name="javax.servlet.jstl.api"/>
        <module name="org.apache.xerces" services="import"/>
        <module name="org.apache.xalan" services="import"/>
    </dependencies>

    <resources>
        <resource-root path="jsf-impl-2.0.2-b10.jar"/>
    </resources>
</module>

Why not the lastest version?
Currently the latest Mojarra version doesn't invoke Seam Faces s:viewAction methods. Lets cross fingers and hope this issue will be fixed with the upcoming 2.2.0 version.

Important Links:

PrettyFaces for SEO-friendly URLs

We all know JSF2 out of the box has still disadvantages with RESTFUL URLs. This problem can easily be solved by PrettyFaces, which allows SEO-friendly URLs with a simple on annotation based configuration.

1) Configuration

Download PrettyFaces binaries and add them to the classpath. If you use Apache Maven, you only need to add PrettyFaces as dependency to your project:
<dependency>
    <groupId>com.ocpsoft</groupId>
    <artifactId>prettyfaces-jsf2</artifactId>
    <version>3.3.0</version>
</dependency>

To ensure maximum flexibility, we configure PrettyFaces on anntotations. The web.xml parameter com.ocpsoft.pretty.BASE_PACKAGE tells PrettyFaces which package have to be scanned recursively for beans with @URLMapping annotation:
<context-param>
    <param-name>com.ocpsoft.pretty.BASE_PACKAGES</param-name>
    <param-value>your.package.structure</param-value>
</context-param>

Congratulations, you have added PrettyFaces to your project successfully.

2) Basic Pages

Now just add @URLMapping's to your action beans like:
@Named
@RequestScoped
@URLMapping(id = "startpage", pattern = "/", viewId = "/pages/startpage.seam")
public class StartpageAction implements Serializable 
{
...
}

The annotation based configuration of PrettyFaces keeps the amount of navigation rules in faces-config.xml small. The new prefix pretty:, could be used as return string on methods of managed beans or as outcome from h:button and h:link components. For a simple reload of the current page just return pretty:. In case of return pretty:startpage PrettyFaces search for the annotation based bean with @URLMapping(id = "startpage", ... and redirect to this page.

On the JSF side you just need to put the id of the @URLMapping as outcome:
<h:link outcome="pretty:startpage" value="Startpage" />

3) Pages With URL Parameters

Pass additional parameters as URL value isn't much harder. Just setup the bean:
@Named
@RequestScoped
@URLMapping(id = "category", pattern = "/cat/#{catId : boardCategoryAction.catId}.html", viewId = "/pages/category.seam")
public class CategoryAction implements Serializable
{
...
    private String catId;
...
    public String getCatId() {
        return catId;
    }

    public void setCatId(String catId) {
        this.catId = catId;
    }
}

And parse the parameter in the "h:link":
<h:link outcome="pretty:category" value="Category">
    <f:param name="catId" value="123" />
</h:link>

Was it ever easier to set up pretty URLs? I don't think so :)
Thanks to Lincoln and the whole OCPSoft Team.

Wednesday, September 7, 2011

Monday, September 5, 2011

PrimeFaces 3.0.M3 UTF-8 encoding issues

Once PrimeFaces 3.0.M3 is added as dependency to the project, utf-8 encoding problems occur on form submits. To avoid these problems you will have to add a custom filter:
public class CharacterEncodingFilter implements Filter, Serializable 
{
    private static final long serialVersionUID = -4246457499875267088L;

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        chain.doFilter(req, resp);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

Add this part to your web.xml:
<filter>
    <filter-name>Character Encoding Filter</filter-name>
    <filter-class>com.your.package.to.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>Character Encoding Filter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

After these changes are made, the utf-8 encoding problems won't occur anymore.