3 Replies Latest reply on Aug 12, 2011 1:37 PM by John Franey

    Seam Phase Listener in bundled arquillian-jsfunit.jar/META-INF/faces-config.xml

    John Franey Novice

      JSFUnit always passes null for the values of JSFServerSession into my unit test method:

       

       

      {code}

              @Test

              @InitialPage("/test/home.seam")

              public void testContact(JSFServerSession server, JSFClientSession client) throws Exception {

       

                     Object o = server.getManagedBeanValue("#{enterpriseTypes}");

                     System.out.println(o);

              }

      {code}

       

       

      I've seen this message in server.log:

       

      {quote}15:08:12,093 WARN  [org.jboss.seam.jsf.SeamPhaseListener] There should only be one Seam phase listener per application{quote}

       

      No other suspicious messages.  Decided to captuure the deploy archive to inspect and deploy as a regular project.  I used the debugger to stop the test while the deployable was still in the app server's deploy directory.  When I deployed and visited /test/home.seam, I see this in the seam debug page in my browser (sure do wish this showed in the server.log):

       

       

      {quote}Caused by java.lang.IllegalStateException with message: "No phase id bound to current thread (make sure you do not have two SeamPhaseListener instances installed)"{quote}

      On phase listener is defined in jboss-seam.jar's faces-config.xml.  Took me a while to root around in the test archive and find another one in arquillian-jsfunit's.
      The jar file: arquillian-jsfunit.jar is bundled into the test archive.  There does not seem to be an option to prevent the inclusion of a faces-config.xml file in this archive.  I am perplexed by how jsfunit, arquillian and seam would have worked at all.  So, assuming it does work for someone, can you tell me how you worked around this?
      Here is versions:
      Jboss AS 6.0.0.Final
      Jboss seam 2.2.2.Final
      JSFUnit, and jsfunit-arquillian:  2.0.0.Beta1
      arquillian 1.0.0.Alpha4
      The create deployment code is available, but the formatting for this post was horrible... Let me know if you need to see it (and if you have wiki-format help available, please share).
        • 1. Re: Seam Phase Listener in bundled arquillian-jsfunit.jar/META-INF/faces-config.xml
          John Franey Novice

          Well, I discovered that the faces-config.xml which jsfunit puts into its auxillary jsfunit-arquillian.jar comes from the jboss-seam-2.2.2.jar file on my build classpath.  See: org.jboss.jsfunit.arquillian.JSFUnitArchiveAppender.

           

          Well, I have to put jboss-seam jar into my deploy archive.  And, I can't avoid JSFUnitArchiveAppender from bringing in a copy of that same file.  So, I think I am officially stuck.

          • 2. Re: Seam Phase Listener in bundled arquillian-jsfunit.jar/META-INF/faces-config.xml
            John Franey Novice

            I discovered I can do this to create a deployable archive including a jboss-seam jar with faces-config.xml stripped out.  This is a hack needed for as long as jsfunit copies the faces-config.xml from the jboss-seam jar file I have to include in my deployable.  ShrinkWrap is cool.

             

             

            {code}

                    private static void addSeamJar(final WebArchive war) {

                            JavaArchive originalSeamjar =   ShrinkWrap.createFromZipFile(JavaArchive.class,

                                            MavenArtifactResolver.resolve("org.jboss.seam:jboss-seam:2.2.2.Final"));

             

                            final JavaArchive seamjar = stripFacesConfig(originalSeamjar);

             

                            war.addLibraries(seamjar);

                    }

             

             

                    private static JavaArchive stripFacesConfig(JavaArchive originalSeamjar) {

                            final ArchivePath facesConfigPath = ArchivePaths.create("/META-INF/faces-config.xml");

                            final JavaArchive seamjar = ShrinkWrap.create(JavaArchive.class, "jboss-seam.jar");

                            seamjar.merge(originalSeamjar, new Filter<ArchivePath>() {

                                    @Override

                                    public boolean include(ArchivePath arg0) {

                                            if(arg0.compareTo(facesConfigPath) == 0) {

                                                    System.out.println("rejecting: " + arg0.toString());

                                            }

                                            return arg0.compareTo(facesConfigPath) != 0;

                                    }

                            });

                            return seamjar;

                    }

             

            {code}

            • 3. Re: Seam Phase Listener in bundled arquillian-jsfunit.jar/META-INF/faces-config.xml
              John Franey Novice

              Ok.  That worked, but then I found the answer to the question: What faces-config.xml did jsfunit want to add if not seam's?

               

              There is a faces-config in the source code of jsfunit 2.0.0.Beta1.  It defines a factory.  The factory can create a jsfunit's specific faces context object.  This is needed to retain the faces context after the request ends (I read that usually the faces context is desroyed at the end of jsf request and all the asserts in a jsfunit test are performed after the jsf request ends).

               

              To work around, I create a src/test/webapp/WEB-INF/faces-config.xml which is a merge of my application's faces-config.xml and the definition in 2.0.0.Beta1's faces-config.xml.  Then, I added this cooked faces-config.xml (not the my application's) into my test war.  Now, a call to server.getFacesContext() does not return null.