Multi-WAR EAR Seam 2.2.2.Final fails deployment (race condition?)
tdsproule Nov 6, 2011 7:33 AMI asked this question on the AS7 forum, but got not response.. so I'm trying here.
I am not sure if this is a Seam 2 problem or AS7.
I am migrating a legacy Seam 2.2.2.Final multi-war/ejb EAR app to AS7 - with some success thus far. I'm really liking AS7.
However, our multi-WAR EAR deployment was failing whenever I included both WARs in the EAR. If I packaged the EAR with just one WAR or the other, then the deployment would succeed. With both WARs Seam would always complain about a (seemingly random) duplicate component definition for one of WARs.
In the process of trying to debug this, I noticed that if I introduced a 'hack' delay (Thread.sleep) within the Seam listener, then the deployment would succeed.
I have managed to replicate the problem with a simple bare-bones Seam 2.2.2.Final 'hello world' EAR mavenized app migrated to AS7. (Thanks to Kasper for the genesis of the example)
- Unpack the attached zip
- mvn clean install
- deploy seam-hello-multiwarfail.ear within ear/target to vanilla AS7 7.0.1.Final (or jboss-as-7.1.0.Alpha2-SNAPSHOT (-1852)) and you'll get output similar to the following showing deployment descriptor failed for the war (ore or the other localhost:8080/seam-hello1 or localhost:8080/seam-hello2 may work). See the log output for the deployment failure below.
- to apply the hack workaround, run mvn clean install -P workaround and deploy seam-hello-multiwarfail-workaround.ear and it will deploy successfully (goto localhost:8080/seam-hello1) - this installs a hacked SeamListener class that simply introduces a 10 second delay to the deployment of the second war. You'll see that both localhost:8080/seam-hello1 and localhost:8080/seam-hello2 work as expected.
public class ServletDelayedInit extends SeamListener { private static final LogProvider log = Logging.getLogProvider(ServletContextListener.class); @SuppressWarnings("static-access") @Override public void contextInitialized(ServletContextEvent event) { log.info( "Welcome to Overrided Seam Startup"); log.info( "Waiting for 10 seconds..."); try { Thread.currentThread().sleep(10000); } catch (Exception e) { log.error( "Exception caught waiting",e); } super.contextInitialized(event); } }
This really does look like a race condition within Seam since AS7 does both WAR deployments in concurrently. But surely Seam should be able to handle this? Or do I have some type of isolation problem?
This is the part of the failed deployment log....
type: JAVA_BEAN, class: org.jboss.seam.persistence.ManagedPersistenceContext 16:19:13,594 INFO [org.jboss.seam.Component] (MSC service thread 1-4) Component: simpleEntity, scope: CONVERSATION, type: ENTITY_BEAN, class: dk.lundogbendsen.seam.SimpleEntity 16:19:13,597 INFO [org.jboss.seam.Component] (MSC service thread 1-3) Component: seamHelloDatabase, scope: CONVERSATION, type: JAVA_BEAN, class: org.jboss.seam.persistence.ManagedPersistenceContext 16:19:13,602 WARNING [org.jboss.seam.security.permission.PersistentPermissionResolver] (MSC service thread 1-4) no permission store available - please install a PermissionStore with the name 'org.jboss.seam.security.jpaPermissionStore' if persistent permissions are required. 16:19:13,605 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/seam-hello1]] (MSC service thread 1-3) Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener: java.lang.IllegalStateException: duplicate factory for: org.jboss.seam.web.webSession (duplicate is specified in components.xml) at org.jboss.seam.core.Init.checkDuplicateFactoryExpressions(Init.java:227) [jboss-seam-2.2.2.Final.jar:] at org.jboss.seam.core.Init.checkDuplicateFactory(Init.java:220) [jboss-seam-2.2.2.Final.jar:] at org.jboss.seam.core.Init.addFactoryValueExpression(Init.java:283) [jboss-seam-2.2.2.Final.jar:] at org.jboss.seam.init.Initialization.installComponents(Initialization.java:1152) [jboss-seam-2.2.2.Final.jar:] at org.jboss.seam.init.Initialization.init(Initialization.java:737) [jboss-seam-2.2.2.Final.jar:] at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:36) [jboss-seam-2.2.2.Final.jar:] at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3368) [jbossweb-7.0.1.Final.jar:7.0.1.Final] at org.apache.catalina.core.StandardContext.start(StandardContext.java:3821) [jbossweb-7.0.1.Final.jar:7.0.1.Final] at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:70) [jboss-as-web-7.0.1.Final.jar:7.0.1.Final] at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1765) at org.jboss.msc.service.ServiceControllerImpl$ClearTCCLTask.run(ServiceControllerImpl.java:2291) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_26] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_26] at java.lang.Thread.run(Thread.java:662) [:1.6.0_26] 16:19:13,688 INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-4) Initializing Mojarra (1.2_13-b01-FCS) for context '/seam-hello2' 16:19:13,693 INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-3) Initializing Mojarra (1.2_13-b01-FCS) for context '/seam-hello1' 16:19:14,702 WARNING [org.jboss.seam.jsf.SeamPhaseListener] (MSC service thread 1-4) There should only be one Seam phase listener per application