12 Replies Latest reply on Jul 31, 2012 5:01 PM by robert.panzer

    Servlet Protocol for EAR Deployments with multiple WARs

    robert.panzer

      Hi,

       

      we are using Arquillian heavily for integration testing on JBoss 7.1.1 and are very pleased with it!

       

      One disturbing detail is that currently it is not possible to use the Servlet protocol with ears that contain more than one war.

      When the app contains 2 or more wars the test is aborted with an UnsupportedOperationException.

       

      Unfortunately the tests seem to behave differently when started using the JMX protocol. The test seems not to be running in the context of the application (e.g. lookups to java:app/AppName fail).

       

      Now I commented out this check from the org.jboss.arquillian.protocol.servlet.v_3.ServletProtocolDeploymentPackager so that it looks like this (based on 1.0.0.Final):

            }

      //      else if(applicationArchiveWars.size() > 1)

      //      {

      //         // TODO: fetch the TestDeployment.getArchiveForEnrichment

      //         throw new UnsupportedOperationException("Multiple WebArchives found in " + applicationArchive.getName() + ". Can not determine which to enrich");

      //      }

            else

            {

               // reuse handle(JavaArchive, ..) logic

       

      Now an ear with more than one war is treated like having no war at all.

       

      And this seems to work fine in our scenario!

       

      Arquillian seems to add a new war called "test.war" the contains an arquillian web fragment.

       

      Are there any objections why this should not be done like this?

       

      Thanks and kind regards,

      Robert

        • 1. Re: Servlet Protocol for EAR Deployments with multiple WARs
          aslak

          The Servlet Protocol rely on there being a War in the deployment somewhere. If non exist, one will be created.

           

          The initial thought here was that the Servlet should be 'inside' the War under test so you would be in the same context, but when you have multiple Wars we don't know which to select. There was a plan to add some sort of Marker on which War should be used, but that never made it to the 1.0 code base.

           

          Adding a 3. WAR as you do in this case, the test.war will work in some cases. You are inside your EAR, but not inside any of your WARs. It depends on what you are trying to test/reach.

           

          Any thoughts around this are highly apprichiated..

          • 2. Re: Servlet Protocol for EAR Deployments with multiple WARs
            robert.panzer

            OK, I see the point.

             

            The advantage of executing the test in the only existing war is that it is the "deepest" nested context in the ear and it has access to everything else in the application.

             

            But wouldn't it be a nice idea to let the tester decide in which context to run when creating the deployment?

            I am thinking about something like a new member "moduleUnderTest" of the @Deployment annotation:

             

                @Deployment(name="deployment-1", moduleUnderTest="MyOwnWar.war")

                public static Archive<EnterpriseArchive> getCacheServer() throws Exception {

                      // Create a deployment that has more than one war, one of which is named "MyOwnWar.war"

                      // Test will be running in the context of "MyOwnWar.war"

                 }

             

                @Deployment(name="deployment-1")

                public static Archive<EnterpriseArchive> getCacheServer() throws Exception {

                      // Create a deployment that has exactly one war, one of which is named "MyOwnWar.war"

                      // Test will be running in the context of "MyOwnWar.war" so that the behaviour is still the same

                 }

             

                @Deployment(name="deployment-1")

                public static Archive<EnterpriseArchive> getCacheServer() throws Exception {

                      // Create a deployment that has more than one war, one of which is named "MyOwnWar.war"

                      // Test will be running in the context of the new war "test.war" just like no war exists

                      // Behaviour changes only in so far as the test would have been aborted before due to multiple wars.

             

                      // Or maybe even still abort with an exception and the moduleUnderTest member must be set because there is no longer a default!

                 }

             

            What do you think about this?

             

            Kind regards,

            Robert

            • 3. Re: Servlet Protocol for EAR Deployments with multiple WARs
              robert.panzer

              Hi Aslak,

               

              I played around a bit and finally got a small patch that adds a field "archiveForEnrichment" to @Deployment that allows to specify the archive to be enriched.

               

              I've tested it with an ear and it seems to work for me, i.e. the test is aborted when the value is not set with the current UnsupportedOperationException but works if an archive to be enriched is defined.

              So the deployment method would look like this:

               

                  @Deployment(name="deployment-1", archiveForEnrichment="MyOwnWar.war")

                  public static Archive<EnterpriseArchive> getCacheServer() throws Exception {

                        ...

                        return myEar;

                   }

               

              If you think that this could be an option I could post a pull request via github.

               

              The patch changes these files:

              #       modified:   container/spi/src/main/java/org/jboss/arquillian/container/spi/client/deployment/DeploymentDescription.java

              #       modified:   container/test-api/src/main/java/org/jboss/arquillian/container/test/api/Deployment.java

              #       modified:   container/test-impl-base/src/main/java/org/jboss/arquillian/container/test/impl/client/deployment/AnnotationDeploymentScenarioGenerator.java

              #       modified:   container/test-spi/src/main/java/org/jboss/arquillian/container/test/spi/TestDeployment.java

              #       modified:   protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/v_3/ServletProtocolDeploymentPackager.java

               

              Kind regards,

              Robert

              • 4. Re: Servlet Protocol for EAR Deployments with multiple WARs
                aslak

                Cool!

                 

                one downside with this approach tho is that by default, ShrinkWrap will generate a name for the archive.

                 

                ShrinkWrap.create(WebArchive.class) will generate a UUID based archivename [UUID].war

                 

                using the archive name in archiveForEnrichment will force the user to use the alternative ShrinkWrap creation method:

                 

                ShrinkWrap.create(WebArchive.class, "name.war")

                 

                It's not the end of the world, but it is another 'manual' link, that if possible should be avoided.

                 

                The first though was to use some kind of 'marker' on the archive creation level, e.g.

                 

                ShrinkWrap.create(EnterpriseArchive.class)

                    .addAsModule(

                        Testable.archiveToTest(

                           ShrinkWrap.create(WebArchive.class)

                               .add.....

                       )

                   )

                 

                Never quite managed to nail the API for it..

                • 5. Re: Servlet Protocol for EAR Deployments with multiple WARs
                  robert.panzer

                  Ah, ok.

                  I did not think about this case as we assemble our ears using our own build process and create the Deployments using ShrinkWrap.createFromZipFile() so that there are no UUIDs in the archive names.

                  (Additionally we add some fragments to do the database setup when the application is launched much the same way arquillian adds its web fragment;-) )

                   

                  But you are perfectly right and I no longer think that my proposal is a good idea:-)

                  I you still like to take a short look at it, you can check https://github.com/robertpanzer/arquillian-core/commit/a39a45c73bd4daedfcf4cd2e8f5fe120fd689d8a

                   

                  As I am still interested in getting this scenario to work maybe I can do some work for it.

                  Did you think of adding something like a marker file to the archive in "Testable.archiveToTest()"?

                  I guess that should be placed into the arquillian-test-api into the same package as @ArquillianResource?

                  • 6. Re: Servlet Protocol for EAR Deployments with multiple WARs
                    aslak

                    Not quite sure how yet..

                     

                    A Marker file is one option, it could be removed by the packaging API that acts on it.

                    e.g. /META-INF/arquillian.ArchiveUnderTest

                     

                    Another option could be to fiddle with some statics or similar, but a file is probably a better idea.

                     

                    This could be related to Testing and Containers only as far as I can see, so it would belong in the integration module between the Test Extension and Container Extension, container-test-api

                    https://github.com/arquillian/arquillian-core/tree/master/container/test-api/src/main/java/org/jboss/arquillian/container/test/api

                    • 7. Re: Servlet Protocol for EAR Deployments with multiple WARs
                      robert.panzer

                      Hi Aslak,

                       

                      using your proposed approach it was even simpler to realize that in the arquillian code.

                      I used your proposed API with Testable.archiveToTest() as it really seems to be a good way to me.

                       

                      Could you take a look at https://github.com/robertpanzer/arquillian-core/commit/010e04682a78a71736f32996c816dfc9f2c3378f ?

                      Or do you prefer that I directly provide a pull request?

                       

                      Thanks and kind regards,

                      Robert

                      • 8. Re: Servlet Protocol for EAR Deployments with multiple WARs
                        aslak

                        Sorry for the delay, been busy preparing for some talks

                         

                        Nice Work! I've added a few comments to the commit on github.

                        • 9. Re: Servlet Protocol for EAR Deployments with multiple WARs
                          robert.panzer

                          No problem, I got enough to do as well.

                           

                          I've taken a look at the code again and I think it would be best to have a org.jboss.arquillian.container.test.spi.client.deployment.ProtocolArchiveProcessor that scans the archives for the marker file and sets the archive on the TestDeployment.

                          So this processor should probably go into arquillian-protocol-servlet artefact as well, right?

                          • 10. Re: Servlet Protocol for EAR Deployments with multiple WARs
                            robert.panzer

                            Hi Aslak,

                             

                            I know, the processor stuff was the wrong way.

                             

                            I added a new commit, where the whole marker stuff is concentrated in Testable and identification of the archive to test is moved to TestDeployment.

                             

                            Could you please take a look at it?

                            https://github.com/robertpanzer/arquillian-core/compare/MulitpleWarsWithMarker

                             

                            Kind regards,

                            Robert

                            • 11. Re: Servlet Protocol for EAR Deployments with multiple WARs
                              robert.panzer

                              Hi Aslak,

                               

                              I just posted a pull request for this:

                              https://github.com/arquillian/arquillian-core/pull/36

                               

                              Kind regards,

                              Robert

                              • 12. Re: Servlet Protocol for EAR Deployments with multiple WARs
                                robert.panzer

                                Just in case someone has the same problem and found this thread:

                                Pull Request has been merged and is part of arquillian-core 1.0.2.Final.