Jenkins Maven Plugin: Classloading Feature

633 views Asked by At

Good time!

Our team uses Maven. One of the project modules has a plugin (maven-jibx-plugin) that requires (for our use-case) a dependency on a proprietary jar:

        <plugin>
            <groupId>org.jibx</groupId>
            <artifactId>jibx-maven-plugin</artifactId>
            <version>${jibx.version}</version>
            <executions>
                <execution>
                    <id>main-schemas</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>schema-codegen</goal>
                    </goals>
                    <configuration>
                        <schemaLocation>
                            ...
                        </schemaLocation>
                        <includeSchemas>
                            ...
                        </includeSchemas>
                        <customizations>
                            <customization>${basedir}/src/main/resources/customizations/customization.xml
                            </customization>
                        </customizations>
                        <verbose>true</verbose>
                    </configuration>
                </execution>
                <execution>
                    <id>bind</id>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>bind</goal>
                    </goals>
                    <configuration>
                        <schemaBindingDirectory>
                            ${basedir}/src/main/resources/bindings
                        </schemaBindingDirectory>
                        <includeSchemaBindings>
                            <includeSchemaBinding>*.xml</includeSchemaBinding>
                        </includeSchemaBindings>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>${project.parent.groupId}</groupId>
                    <artifactId>proprietary-jar</artifactId>
                    <version>${project.parent.version}</version>
                </dependency>
            </dependencies>
        </plugin>

The problem is when we build the project locally (and even from a command line on the remote machine where jenkins is istalled), everything builds successfully, but when our jenkins instance tries to build it - the build fails with such a message: "Unable to find class 'class-name-from-the-proprietary-jar'". This problem occurred loccally before we added the plugin dependency..

Seems like there is some feature of jenkins maven plugin that do no resolve the plugin dependencies or may be there are some well-known feature of the jenkins maven plugin classloading (JiBX loads proprietary classes with such a construct: SchemaRootBase.class.getClassLoader().loadClass(cname) So that specifing the dependency for the plugin should provide a knowledge for it about the required classes)... Can somebody, please, suggest the workaround?

UPDATE: it turned out that the jenkins instance's JAVA_HOME variable is set to /usr/java/jdk1.7.0_25, but in my maven-compiler-plugin I have <target>1.6</target>. Could it be that the problem is in the 1.7 java version?

2

There are 2 answers

0
Dmitry On BEST ANSWER

Well, finally I've found an answer! The problem is not actually in Jenkins, but rather in Maven itself.

ATTENTION: the undergoing information is tested only for Maven 2.

It turned out that when you have a multimodule project and several modules use the same plugin (with different dependencies), Maven would get dependencies set for the first plugin (I mean that the plugin is located in the first module, that Maven builds, with this plugin) and use them for other plugins not overriding the dependencies by the local values.

To clarify this lets have an example. Say there are two modules in the maven build - A and B:

<modules>
   <module>A</module>
   <module>B</module>
</modules>

and the module A has such the code in the pom file:

<plugin>
   <dependencies>
     <dependency>
        <groupId>com.c</groupId>
        <artifactId>D-module</artifactId>
        <version>1</version>
     </dependency>
   </dependencies>
   <groupId>org.jibx</groupId>
   <artifactId>jibx-maven-plugin</artifactId>
   <version>${jibx.version}</version>
</plugin>

and the module B has such the code in the pom file:

    <plugin>
       <dependencies>
         <dependency>
            <groupId>com.c</groupId>
            <artifactId>F-module</artifactId>
            <version>1</version>
         </dependency>
       </dependencies>
       <groupId>org.jibx</groupId>
       <artifactId>jibx-maven-plugin</artifactId>
       <version>${jibx.version}</version>
    </plugin>

It turns out that when Maven builds the module B it will use the D-module dependency even though you have specified the F-module dependency.

In our project we made such a workaround: we moved the plugin declaration to the parent pom in a pluginManagement section and declared the D-module and F-module dependencies for the plugin (also removed these dependencies from the local modules). Ok, the code is rather ugly (having child dependencies in the parent pom file), but this works!

If somebody shared this issue and managed to overcome it, please, advice the solution.

3
Archit Khosla On

Try mvn clean install in your workspace

Then you should have the same error every where. Also try and use the same command line Jenkins is using (if any)