1 2 Previous Next 15 Replies Latest reply on Sep 18, 2012 1:26 PM by alrubinger

    How do I add a JAR to the @Deployment archive?

    dan.j.allen

      This might be a ShrinkWrap question, in which case just point me there. But I have a feeling it ties into the setup for Arquillian.

       

      How do I add a JAR to the test.jar defined by the @Deployment archive?

       

      Let's assume I have the following @Deployment method defined in my Arquillian test class:

       

      @Deployment
      public static Archive<?> createDeployment() {
         return Archives.create("test.jar", JavaArchive.class)
            .addPackage(ClassUnderTest.class.getPackage())
            .addManifestResource("test-beans.xml", ArchivePaths.create("beans.xml"))
            .addManifestResource("test-persistence.xml", ArchivePaths.create("persistence.xml"));
      }

       

      I need to add a JAR to the EAR archive that Arquillian creates and deploys for me. Where do I stick it?

        • 1. Re: How do I add a JAR to the @Deployment archive?
          aslak

          Yeah, that's not possible..

           

          A JavaArchive does not supported nested JavaArchives, so you need to return a JavaArchive 'container', e.g. EnterpriseArchive or WebArchive. But those are not very supported by the current DeploymentPackager.

           

          You can use the Archive.merge to make one JavaArchive out of them:

          {code:java}

          JavaArchive deployment = Archives.create("test.jar", JavaArchive.class):

           

          JavaArchive imported = Archives.create("test2.jar", ZipImporter.class).importZip(..).as(JavaArchive.class);

           

          deployment.merge(imported);

          {code}

           

          If it's a project wide dependency, you can use the DeploymentAppender SPI.

           

           

          But I do see your point and have been wondering the same my self.

           

          We might need to update the @Deployment signature to support:

          {code:java}

          @Deployment

          static Set<Archive<?>> x();

          {code}

           

          Or maybe a seperate @DeploymentDependencies (this could be defined in e.g. a super class)

          {code:java}

          @DeploymentDependencies

          static Set<Archive<?>> x();

          {code}

          • 2. Re: How do I add a JAR to the @Deployment archive?
            dan.j.allen

            The requirement to add extra JARs into the deployment is going to surface fairly early on in the adoption of Arquillian. In our examples, we are sticking to APIs in Java EE, but most projects have third-party JARs on which the application depends. Common examples are a logging framework or the Apache Commons libraries (or Google Collections if you aren't a fan of the Apache stuff).

            A JavaArchive does not supported nested JavaArchives, so you need to return a JavaArchive 'container', e.g. EnterpriseArchive or WebArchive. But those are not very supported by the current DeploymentPackager.

            That's exactly what I figured. We are getting bitten by the fact that the EAR is being created downstream, and that all we are able to contribute is a single JAR made up of application classes and resoruces.

             

            The merging technique would certainly work, but since this is likely to be a common need, not the most elegant approach.

            If it's a project wide dependency, you can use the DeploymentAppender SPI.

            It would work, yes, but I doubt developers are going to want to resort to that for adding library dependencies.

            We might need to update the @Deployment signature to support:

            @Deployment
            static Set<Archive<?>> x();

            Or maybe a seperate @DeploymentDependencies (this could be defined in e.g. a super class)

            @DeploymentDependencies
            static Set<Archive<?>> x();

            This ties into a conversation we were having in the threads Deployment specification: and Arquillian Design Questions: about including Maven artifacts in the deployment. As soon as you consider adding a JAR to a deployment, you have to ask yourself, "where does the JAR come from?" Increasingly, people are using local repositories like Maven or Ivy, so they are going to want to declare the artifact id and have it pulled in just like the build tool pulls it in.

             

            I like the idea of having the @DeploymentDependencies (or @DeploymentLibraries to be consistent with what they are called in an EAR). Then perhaps we could have some sort of API to allow the developer to reference the entire test dependency closure in Maven. Or, they can simply refer to libraries by groupId, artifactId and version (or resolve the version from Maven).

             

            This is a pretty high priority task because people simply aren't going to be able to begin writing tests until they can easily add dependent libraries. JIRA: ARQ-66

            • 3. Re: How do I add a JAR to the @Deployment archive?
              pmuir
              Neither of these feels right to me - from a user perspecitve they are returning what they are deploying from that method. So also returning libraries to go in the deployment feels weird. I'll sleep on it
              • 4. Re: How do I add a JAR to the @Deployment archive?
                iapazmino

                Hi, I'm not sure how late I'm for this discussion but I've just bumpped into this issue since trying to test a real project with arquillian. I need to add a few jars from my maven dependencies into the test deployment, but since I've already configured them into the pom it felt they should be available to the running test. One way to go, I think, could be stating some defaults. So, at least the compile scoped dependencies should be added by default to the jar/war/ear and the other explicitly added, or removed if needed with @DeploymentDependencies.

                 

                Another way could be, since there's already a nicely configured pom holding all references the project needs with the right scopes, you could define another dependency-manager-descriptor within the test's resources where added libraries could be defined, meanning all libraries defaulted to not added. This file  could be read as easy as a config file instead of interpreted with a maven embedder.

                • 5. How do I add a JAR to the @Deployment archive?
                  thohawk

                  Hi, stumbled upon this discussion after trying to use arquillian with a real project too. I think @DeploymentLibraries would be an elegant as well as simple solution to add external jars used by ejbs in the ear file. The Maven integration solution using MavenArtifactResolver (sorry can't remember the page mentioning this) works fine for me when trying to resolve external jars in my maven repo. With the possibility to add external jar dependencies, i would be able to use this fantastic framework in my real life project.

                  • 6. How do I add a JAR to the @Deployment archive?
                    willks

                    So then the clear solution is to use EnterpriseArchive instead of JarArchive? I'm going to convert my tests then. I'm having a very hard time testing a real world EJB with multiple dependencies (think 50) and datasources (e.g. manage snapshots of certain data to separate datastores for audit purposes).

                    • 7. How do I add a JAR to the @Deployment archive?
                      marx3

                      I also need to add jar to my tests. How should it be done? I see Arquillian beta is out, maybe this version has better support for it?

                      • 8. How do I add a JAR to the @Deployment archive?
                        aslak

                        To get the Libraries you can use the new MavenDependencyResolver, example: https://github.com/shrinkwrap/shrinkwrap/blob/master/extension-resolver/impl-maven/src/test/java/org/jboss/shrinkwrap/resolver/impl/maven/DependenciesUnitTestCase.java

                         

                        As to how to add them to the Archive, you need to use a Archive type that supports it, e.g. WebArchive, EnterpriseArchve or ResourceAdaptor depending on what you are trying to do.

                        • 9. How do I add a JAR to the @Deployment archive?
                          ceefour

                          You almost got me at " I see Arquillian beta is out " (I still see 1.0.0.Alpha5 now).

                           

                          Anyway... I think you can use .addAsResource(...) and refer a physical JAR file your project.

                          • 10. How do I add a JAR to the @Deployment archive?
                            marx3

                            I have

                                    <!-- Arquillian version -->

                                    <arquillian.version>1.0.0.Beta1</arquillian.version>

                             

                            in my pom.xml and it works from a few days... So...

                            • 11. How do I add a JAR to the @Deployment archive?
                              jaikiran

                              Marek Nazarko wrote:

                               

                              I have

                                      <!-- Arquillian version -->

                                      <arquillian.version>1.0.0.Beta1</arquillian.version>

                               

                              in my pom.xml and it works from a few days... So...

                              Does that property ever get used later in the pom? What does the dependency look like?

                              • 12. How do I add a JAR to the @Deployment archive?
                                marx3

                                ok, my mistake in POM, sorry.... no beta...

                                • 13. Re: How do I add a JAR to the @Deployment archive?
                                  donmcronald

                                  I can think of a few ways using the MavenDependencyResolver could cause problems.  I'm speaking from the perspective of someone that is using Maven as their primary build system.  Personally I've found it easiest to build a .war or .ear with Maven and use..

                                   

                                  ShrinkWrap#createFromZipFile
                                  

                                   

                                  I already have a lot of dependency management set up in Maven and duplicating version info, etc. to create a deployment with ShrinkWrap seems like it could cause problems for any deployment that isn't trivial.

                                   

                                  I think you'll also find problems with people using aggregator modules.  The MavenDependencyResolver looks like it's making the assumption that all artifacts are installed in the local repository (am I correct?), but a full reactor build from an aggregator module can build all dependent modules without installing anything to the local repository.  I'll give an example of something I set up this morning and hopefully it will clarify what I mean.

                                   

                                  To start with, I had 3 normal modules in my project:

                                   

                                  itma-domain                  (domain module)
                                  itma-mybatis-api             (MyBATIS mapper interfaces)
                                  itma-mybatis-impl-postgresql (implements itma-mybatis-api for postgresql db)
                                  

                                   

                                  Those three modules are part of a larger software stack and, since I don't want to constantly rebuild the full stack during development, I use an aggregator module that allows me to build only those modules.

                                   

                                  itma-group-stack-mybatis
                                  
                                  relevant portion of POM is:
                                  
                                  <modules>
                                      <module>itma-java-domain</module>
                                      <module>itma-mybatis-api</module>
                                      <module>itma-mybatis-impl-postgresql</module>
                                  </modules>
                                  
                                  

                                   

                                  Now, I want to do integration testing (against the API module) using Arquillian (for the CDI container and a container managed JNDI data source), so I add another module specifically for integration tests:

                                   

                                  itma-integration-mybatis
                                  

                                   

                                  This is where things start to become a bit more difficult using ShrinkWrap.  The module that implements the API in 'itma-mybatis-api' is selected at build time using Maven profiles.  I don't know which DB I want to use yet and there's a good chance I'll drop the PostgreSQL implementation in favor of using an embedded DB like Apache Derby.

                                   

                                  To make things easier, assume I don't have any profiles and can add 'itma-mybatis-impl-postgresql' as a dependency for my ShrinkWrap archives in the integration module.  The other two modules will also get picked up as transitive dependencies.  I think most people would try something like this in the integration tests:

                                   

                                  WebArchive war = ShrinkWrap.create(WebArchive.class, "itma-integration-mybatis.war").addAsLibraries(
                                      DependencyResolvers.use(MavenDependencyResolver.class)
                                      .artifact("com.mydomain:itma-mybatis-impl-postgresql:1.0-SNAPSHOT").resolveAs(GenericArchive.class));
                                  
                                  

                                   

                                  As I understand the MavenDependencyResolver plugin, the above will pull in all the necessary (transitive) dependencies and add them to the archive.  However, it's going to pull the dependencies from the local repository whereas anyone using aggregator modules is going to be used to getting (project) dependencies that were build as part of the current reactor execution.  To clarify, assume I update my aggregator module:

                                   

                                  itma-group-stack-mybatis
                                  
                                  relevant portion of POM is:
                                  
                                  <modules>
                                      <module>itma-java-domain</module>
                                      <module>itma-mybatis-api</module>
                                      <module>itma-mybatis-impl-postgresql</module>
                                      <module>itma-integration-mybatis</module>
                                  </modules>
                                  

                                   

                                  Now, assume I run:

                                   

                                  mvn clean verify
                                  

                                   

                                  The aggregator module will build and package my child modules based on my current source, but the integration module is going run against whatever revision of my modules happen to be installed in the local repository.  I don't think this is avoidable, but the behavior could be confusing to people that alternate between 'mvn clean verify' and 'mvn clean install' since the results won't be consistent.

                                   

                                  After a bit of trial and error I, as mentioned above, still prefer to build my archive using Maven.  Of note, my integration module contains only test sources for the purpose of integration testing.  The following worked well for me:

                                   

                                  • set the itma-integration-mybatis packaging to WAR
                                  • declare 'itma-mybatis-impl-postgresql' as a dependency of the integration module (via profiles if desired)
                                  • use a final name of 'itma-integration-mybatis' in the integration module
                                  • bind all tests to the 'integration-test' phase (this will NOT work using the 'test' phase since it comes before 'package')
                                  • use the following to create an archive with ShrinkWrap

                                   

                                  @Deployment
                                  public static Archive<?> createArchive() {
                                      return(ShrinkWrap.createFromZipFile(WebArchive.class, new File("target/itma-integration-mybatis.war")));
                                  }
                                  
                                  

                                   

                                  Now when I run 'mvn verify' on my 'itma-group-stack-mybatis' module, the project modules that are built as part of the current reactor execution are the ones that get included in my deployment archive.  Of course, the option of building modules independently and installing them to the local repository is still there too.

                                   

                                  I also shouldn't have to worry about updating my ShrinkWrap configurations when I swap out the 'itma-mybatis-impl-postgresql' module for something like 'itma-mybatis-impl-derby' or when I update dependency versions, etc.  Everything should follow along auto-magically once my Maven POMs get the appropriate updates.

                                   

                                  Hopefully this info ends up being useful since, so far, I haven't seen too many examples of testing moderately complex archives.

                                  • 14. Re: How do I add a JAR to the @Deployment archive?
                                    atiyou

                                    hello Aslak,

                                     

                                    The link you posted is no longer available, and it's posted in severals forums & sites

                                    Can you poste some codes to use MavenDependencyResolver with JavaArchive ?

                                     

                                    thank's for feedback

                                     

                                     

                                     

                                    Youssef

                                    1 2 Previous Next