10 Replies Latest reply on Aug 13, 2014 10:55 AM by srinivas.akula

    ShrinkWrap load libraries from POM for JavaArchive

    srinivas.akula

      Hallo,

      I am new to this community.

      I am working on multi maven module project. And I am writing unit tests using Arquillian.

      Till now every thing is fine, as I am adding dependencies in my test class from my module and other dependent module as well.

      Example:

      .addPackages(true, "com.test.pk2")

      .addPackages(true, "com.test.pk1")

      like so.

      In order to simplify the unit tests, I am using Shrink Wrap Maven dependency resolver.

      File[] crLibs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeAndTestDependencies().asFile();

      But I ran into some of the issues.

      1) I could not able to merge Java Archives to my final archive, and the final archive is not unable to deploy.

      2) I do not find much support for Java Archives.

      3) If I try to add jar files to final archive, I ran into java.lang.IncompatibleClassChangeError.


      Am I missing any thing or what is wrong with this.

      Can any one help with this?

       

      More Info on Technologies:

      ShrinkWrap 2.0.0

      Glassfish 3.1.2.2

      Maven2.2.1

       


        • 1. Re: ShrinkWrap load libraries from POM for JavaArchive
          kpiwko

          Hi Srinivas,

           

          usually, you want to put resolved JARs into a WAR or EAR archive.

          If you indeed want to include classes in another JAR into your JAR file, you'd need to merge JAR archives together. It's the same concept as uberjar or fatjar.

           

          You can do that following way:

           

          JavaArchive yours = ShrinkWrap.create(JavaArchive.class).addClass(Class.class);
          JavaArchive[] libs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeAndTestDependencies().as(JavaArchive.class);       
          
          for(JavaArchive lib: libs) {
             yours = yours.merge(lib);
          }
          
          
          

           

          I guess this answers your issue 1) and 2). I'm not sure what you exactly meant by 3), please provide a code how exactly are you adding jar files to archive.

           

          Thanks,

           

          Karel

          • 2. Re: Re: ShrinkWrap load libraries from POM for JavaArchive
            srinivas.akula

            Hi Karel,
            Thank you for the reply.

            But, it did not worked for me. I am facing two problem with it.

             

            Case 1: 

            JavaArchive test= ShrinkWrap.create(JavaArchive.class).addClass(Class.class); 

            JavaArchive[] libs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeAndTestDependencies().as(JavaArchive.class);         

            for(JavaArchive lib: libs) { 

              test= test.merge(lib); 

            If, I do not give any name to test archive, then I ran into java.lang.SecurityException. Please see case1.log file.


            Case 2: 

            JavaArchive test= ShrinkWrap.create(JavaArchive.class, "test").addClass(Class.class);

            JavaArchive[] libs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeAndTestDependencies().as(JavaArchive.class);       

            for(JavaArchive lib: libs) {

              test= test.merge(lib);

            }

            If I give name to the archive, say "test",  please see case2.log


            And for 3)

            File[] crLibs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeAndTestDependencies().asFile();

            addPackages(crLibs, archive);

             

            private static void addPackages(File[] libs, JavaArchive archive) throws IllegalArgumentException, ArchiveImportException {

                    for (File lib : libs) {

                        //for each lib, create JavaArchive.

                        JavaArchive jarArchive = ShrinkWrap.createFromZipFile(JavaArchive.class, lib);

                        //Read the archive for class files and extract the package information from it.

                        for (Map.Entry<ArchivePath, Node> entry : jarArchive.getContent().entrySet()) {

                            String path = entry.getValue().toString();

                            if (path.endsWith(".class")) {

                                int lastIdx = path.lastIndexOf("/");

                                path = path.replaceFirst("/", "").replaceAll("/", ".");

                                archive.addPackages(true, path.substring(0, lastIdx));

                            }

                        }

                    }

                }

            After deploying the final archive it gives, java.lang.IncompatibleClassChangeError


            If you need further more info, please let me know.

            Thank you.

            • 3. Re: Re: ShrinkWrap load libraries from POM for JavaArchive
              kpiwko

              As for Case 1, I believe that the problem is that some of the dependencies your fetch are signed jar(s). You can either pass a Filter object while merging to reject all signature related bits from merged archive or you can call archive.delete() and remove them in the end.

               

              As for Case 2, definitely don't forget to add ".jar" to archive name. Otherwise your application server might have problems loading it. The bug itself says that com.converis.rrr.test.RRRDataNGTest is not in the deployment. Can you verify that?

               

              The best way is to allow export in arquillian.xml, that way you'll be able to browse what arquillian will deploy and you can also deploy manually to check - see export the deployment section here - http://arquillian.org/guides/getting_started_rinse_and_repeat/

               

              Karel

              • 4. Re: Re: ShrinkWrap load libraries from POM for JavaArchive
                srinivas.akula

                Hi,
                can you give me an example on
                how to pass a Filter object while merging to reject all signature related bits from merged archive or you can call archive.delete() and remove them in the end?

                • 5. Re: Re: ShrinkWrap load libraries from POM for JavaArchive
                  kpiwko

                  For deleting stuff: Just call archive.delete("/path/you/want/to/delete"), such as war.delete("/WEB-INF/classes/META-INF/persistence.xml");

                   

                  For filtering stuff: archive.merge(jarYouWantToMerge, Filters.exclude("regex"), such as war.merge(jar2, Filters.exclude("(.*META-INF.*)|(/MANIFEST.MF)"). You can also construct your own filter programatically by implementing Filter interface.

                  • 6. Re: Re: Re: ShrinkWrap load libraries from POM for JavaArchive
                    srinivas.akula

                    Hi,

                    I added some filter to exclude these files. But I ran into java.lang.IncompatibleClassChangeError.
                    here is my code snippet

                     

                    JavaArchive archive = ShrinkWrap.create(JavaArchive.class, "test.jar").addClass(Class.class);

                    JavaArchive[] libs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeAndTestDependencies().as(JavaArchive.class);

                            for (JavaArchive lib : libs) {

                                archive = archive.merge(lib, Filters.exclude("([^\\s]+(\\.(?i)(MF|SF|RSA|LIST))$)"));

                            }

                            archive.addAsManifestResource("persistence-template.xml", "persistence.xml")

                                    .addAsResource("rsl-test.xml")

                                    .addAsResource("log4j.properties")

                                    .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");

                     

                            return archive;

                     

                    I am doing some thing wrong in this?

                    • 7. Re: ShrinkWrap load libraries from POM for JavaArchive
                      kpiwko

                      Hey Srinivas,

                       

                      I believe this has nothing to do with ShrinkWrap or Arquillian. I suggest to:

                       

                      1/ Enable deployment export in arquillian.xml - see Export the Deployment in http://arquillian.org/guides/getting_started_rinse_and_repeat/

                      2/ Compare deployed archive with one that represents your application you get via your build tool.

                       

                      I expect you deploy more artifacts than you need to and some of them (Eclipse JAXP) collides with classpath provided by GlassFish.

                       

                      Karel

                      • 8. Re: ShrinkWrap load libraries from POM for JavaArchive
                        srinivas.akula

                        Hi Karel,

                        Yes you are right. When I compare the two archives, there are lot of differences.
                        But I want to control them not to add to my archive.

                        Here is my case:

                        Previously, I added packages manually to my final archive  like this

                                         .addPackages(true, "org.apache.log4j")

                                        .addPackages(true, "org.apache.commons")

                                        .addPackages(true, "org.slf4j")

                        and this makes sense, when I know the dependencies in my module. But, it is not possible to know all the packages from other maven modules, where my module is dependent on them.
                        For now, I am checking all the modules, where my module is dependent on and adding them in the above fashion.

                         

                        Later, I used Maven Dependency resolver from ShrinkWrap and I've given my pom.xml, so that it will add all the dependencies. But, it is adding them transitively.  So, all other jars also added which I do not use them directly in my module. Finally my tests are not running.
                        So, is there any way to select only the dependencies which I need or to restrict the artifacts which I do not need?

                        Thank you.

                        • 9. Re: ShrinkWrap load libraries from POM for JavaArchive
                          kpiwko

                          Srinivas,

                           

                          Sorry for the late reply. Definitely, this is possible. The best thing you can do is to follow official resolver documentation at resolver/README.asciidoc at master · shrinkwrap/resolver · GitHub .

                          I think that bunch of the artifacts are coming from <scope>test</scope> you include by calling importRuntimeAndTestDependencies(). I believe you want just importRuntimeDependencies(). See also section about strategies to get more details how to exclude even more stuff.

                           

                          Karel

                          • 10. Re: ShrinkWrap load libraries from POM for JavaArchive
                            srinivas.akula

                            Thank you. This is working now.