Thursday, September 8, 2011

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:

Be careful with updating Hibernate Core 3.6 to 4.0 with MySQL as database and strategy GenerationType.AUTO. For me it was an update of JBoss AS 6 (Hibernate 3.6) to AS 7 (Hibernate 4). If you have mapped tables like this:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)

Hibernate 3.6 uses the auto increment functionality to increment the id. But Hibernate 4 creates a sequence table and uses this to increment the id. Even if you say sequences are ok, you will run into exceptions on a given database, since Hibernate tries to save the first object with id 1 which already exists.
Better change the strategy to:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

Now both Hibernate versions will create the table structure in the same way.

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:

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:

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:

Tuesday, September 6, 2011

Today I want to introduce you to JBoss mod_cluster. The Apache-based load balancer works similiar to mod_jk and mod_proxy, but is much more flexible. New application server nodes will introduce theirselves automatically to mod_cluster at runtime. There is no configuration like the worker.properties on mod_jk.

Why should I use mod_cluster?

Clustering was never easier, mod_cluster can balance heavy traffic on registered application server nodes. The web interface allows to enable or disable single applications for each node. If all nodes went down e.g. updating your application mod_cluster will provide a clean error code 503 (service temporary unavailable) page instead of just the default page is not available browser view. Another advantage is mod_cluster 1.1.x and AS 7 fits perfect together and work awesome after minimal amount of configuration.

Prepare Jboss AS 7 for clustering

First, open the configuration file standalone.xml of your Jboss AS 7 instance and add modcluster extension and subsystem on the provided sections:

Keep in mind to set up the http connector port properly. Since mod_cluster handle all requests for us, the port doesn't really matter and should be blocked by firewall anyways. The first application node could be run for example on http port 8085, the next one on 8086 and so on.

Quick Start mod_cluster

The Quick Start Guide provides simple steps to install mod_cluster on Windows and Linux. After some minutes mod_cluster should run on http port 80 and returns It Works page on request to http://localhost/. The upcoming mod_cluster configuration is a bit tricky especially for setting up multiple vhosts.

By default mod_cluster provides the application server cluster in each vhost, means other provided content will disappear as soon as the first application node registered to the mode_cluster manager. If you just want the cluster responding to a specific vhost add this additional parameter to your httpd.conf:

CreateBalancers 1

The manager listener should be pre-configurated by mod_cluster. Maybe you will have to change the ip address here:

The current version of mod_cluster has a bug with mixing ProxyPass and ProxyPassReverse, means double slashes occur on faces redirects. For example redirect to /test resolves in www.mydomain.com//test. Currently the parameter ProxyPreserveHost On could be used as workaround. For more informations about this bug follow MODCLUSTER-250.

In development state most applications need dummy data which should be imported on application initialization. During this phase Seam's TransactionManager is not initialized yet. This means we have to build our UserTransaction manually:

Welcome to the Seam Space. I will be using this blog as a place to hold my knowledge, interests and solutions for common problems.

Who am I?

My name is Sebastian Sachtleben, a software developer with five years experience of web development. My experience includes Struts, Spring, Seam Framework, Richfaces, Primefaces 3, EJB, JSF, Hibernate etc. I love the direction JEE is taking at the moment and I'm delighted to develop applications with it. My current project is ReplicaScene.

Why did I want to start this blog?

I've gained a lot of experience in the past years while developing different projects and I want to share solutions for common problems which may occur in the future.

Final

Well friends. I'm done. I've set up my own blog, and published my first post.

About Me

My name is Sebastian Sachtleben, a software developer with five years experience of web development. My experience includes Struts, Spring, Seam Framework, Richfaces, Primefaces, EJB, JSF, Hibernate etc. I love the direction JEE is taking at the moment and I'm delighted to develop applications with it.