Arquillian, TomEE and big applications: avoid N times the same dump


TomEE arquillian adapters try to make test as isolated as possible but it means if you test a single application in N tests you’ll dump the application N times. For small apps no issue but for big ones it takes time.

To solve it several solutions exist.

The most obvious one is to use the built war and not a shrinkwrap memory archive but then you have to build your war before testing your code which can lead to install broken artifacts! You can also use one of the arquillian suite extensions but you can get issues with the container adapter (IIRC you need TomEE trunk/1.7.2 at least) or with other arquillian extensions because of the lifecycle which is not common.

To get an intermediate solution TomEE adapters have now the singleDumpByArchiveName property (you can set it to “true” in arquillian.xml in tomee container properties). This property means: when I have an archive “foo.war” it will always be the same content. In this case TomEE adapter will dump it only the first time. You can of course have several different archives but just ensure to name them differently.

This is a not a rare pattern when you use an “Applications” utility class and just call “Applications.myApp()” in @Deployment method of your arquillian test. Note also that setting “preloadClasses” property of tomee adapter to the fully qualified name of your “Applications” class and initializing your app (war) in a static block to just return a field in “myApp()” can save few seconds as well.

Finally here what it looks like:

public class Applications {
    private static final Archive<?> WAR = ShrinkWrap.create(WebArchive.class, "myapp.war")
              // ... add your classes/resources/...
               ;

   public static Archive<?> myApp() {
       // Note: if you don't use singleDumpByArchiveName then you need to copy WAR here
       // using ShrinkWrap ExplodedImporter for instance and archive.merge(...)
       return WAR;
   }
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<arquillian 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="
         http://jboss.org/schema/arquillian
         http://jboss.org/schema/arquillian/arquillian_1_0.xsd">	
       <container qualifier="tomee" default="true">
           <configuration>
               <property name="singleDumpByArchiveName">true</property>
               <property name="httpPort">-1</property>
               <property name="stopPort">-1</property>
               <property name="ajpPort">-1</property>
               <property name="dir">target/apache-tomee-remote</property>
               <property name="appWorkingDir">target/arquillian-test-working-dir</property>
           </configuration>
       </container>
</arquillian>
Advertisement

16 thoughts on “Arquillian, TomEE and big applications: avoid N times the same dump

  1. Bart J

    Hi,

    I just tried to use your approach but I can see that my ear is redeployed for every Test class.

    Each of my test extends an abstract class that generate the same ear.

    @RunWith(Arquillian.class)
    public abstract class BaseTestCase {

    @Deployment
    @TargetsContainer(“tomee”)
    public static Archive createArchive() {
    return new TomeeDeployment().build();
    }

    }

    TomeeDeployment.build() – always create ear with a name: “test.ear”

    Do you know what may be wrong? How can I validate that ‘singleDumpByArchiveName’ is working?

    Reply
  2. emmanuel

    This is EXTREMELY exciting. our AQ tests running times are growing out of control and we’ve had to prevent JMS to get turned on because it makes it even worse due to the (we assume) on-time JMS initialization which we could pay for only once without redeploys. I can’t wait to test that for us! I hope you publish 2.0milestone1 tomee embedded jars on maven central, or 1.7.2 soon or maybe even 1.7-snapshot..

    Reply
  3. Darjan Oblak

    I tested Emmanuel’s reproduce project with 1.7.2-SNAPSHOT and found out that the problem stil exists.

    This fix:
    https://issues.apache.org/jira/browse/TOMEE-1333

    Was only commited to trunk, but not to 1.7.x branch. It is however better that it was a few months ago. Back there even individual tests were failing for some reasons, now individual tests normally execute and pass as they should, but the suite fails (‘Could not run @AfterSuite’).

    According to my testing, porting the fix to 1.7.x branch would fix that last issue.

    Reply
    1. rmannibucau Post author

      Fixed even if it stays a workaround. For memories TOMEE-1440 makes the need of arquillian-suite-extension not that mandatory since it supports single deployment by archive.

      Reply
      1. emmanuel

        FYI we (we are coworkers with Darjan) took advantage of single deployment by archive (TOMEE-1440) on 1.7.2-SNAPSHOT and got a 3x speedup on our tests 🙂
        So thanks a lot, this makes a VERY big difference!

        I have maybe just one last question… What is the difference between “single dump” and “single deploy”?

      2. rmannibucau Post author

        Yeah I know it is not that obvious but both are as you suspect linked. If you “single deploy” then you “sigle dump” but the opposite is not true. Suppose you want to clear the app state between all state (cause you use a static variable to store something and you don’t clean it) then you’ll single dump if your app is big but you’ll not single deploy.

        Side note: openejb embedded adapter supports single deployment but snice it doesn’t dump anything it doesn’t support single dump config.

      3. emmanuel

        Aha I think I understand.

        So if I’m right, deploy=dump+app startup.

        “dump” would be TomEE parsing the WAR file, exploring its classpath, annotations, and so on. That’s my understanding. In that case “single dump” makes for a simpler arrangement yes. With single deploy you can even optimize further if you know what to reset and what not (which is our situation).

  4. Simimmo

    Hi,

    Using

    org.apache.openejb
    arquillian-tomee-embedded
    1.7.2
    test

    is not making any difference in terms of execution time. I had to change all the annotations in my test classes from @EJB to @Inject to make it work with

    true

    but execution time is not changing. Do you have any tip to make the tests execution faster?

    Thanks

    Reply
    1. rmannibucau Post author

      depends the archive size, if very small you’ll not see the difference, if big (some dozens of mega) you will. Setting singleDeploymentByArchiveName=myapp.war (the name of the ShrinkWrap war) will also boost it a lot but enforce client tests (app is deployed a single time and enriched a single time). Used it on a few builds and got between x3 and x10 for fully client surefire executions)

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s