views:

95

answers:

3

I'm running into trouble with having multiple class with the same path (i.e. same name, same package!!!). For some reason, gwt-dev comes with its own version of org.apache.xerces.jaxp.DocumentBuilderFactoryImpl and javax.xml.parsers.DocumentBuilderFactory.

At the same time, spring also depends on these classes but from different jar. I don't know what should be, but look like xalan & xml-api are the two dependencies that spring depends on (these dependency are optional)

Funny thing is that eclipse can run the same code (it's a unit test) without problem, but surefire cannot. So I guess the problem is due to the way each runner consider the priority of each jar.

Now come to the question: How can I setup my POM so that I can sure that when ever any code running inside my app, then class from a jar will be selected over class from other jar?

Thanks.

A: 

dependencies within maven projects can be a hassle to troubleshoot. what i normally do is...

  • mvn dependency:tree on your project to see who has a dependency on the classes giving you problems.
  • try excluding the classes you think is giving problem by editing your pom.xml.

hope this helps!

koss
Well, I still need the dependency that introduce the problems. I only want to low-prioritize it.
Phương Nguyễn
A: 

To know which jar is causing you problems: run Maven with -X flag.

To setup your POM to exclude relevant jar(s):

<yourproject.deployment.excludes>
  artifactId1,artifactId2,...
</yourproject.deployment.excludes>

...

 <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>copy-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${your.lib.for.example}</outputDirectory>
          <overWriteSnapshots>true</overWriteSnapshots>
          <overWriteIfNewer>true</overWriteIfNewer>
          <excludeTransitive>false</excludeTransitive>
          <excludeArtifactIds>${yourproject.deployment.excludes}</excludeArtifactIds>
          <includeScope>compile</includeScope>
        </configuration>
      </execution>
    </executions>
  </plugin>
mindas
+1  A: 

Now come to the question: How can I setup my POM so that I can sure that when ever any code running inside my app, then class from a jar will be selected over class from other jar?

Since Maven 2.0.9, Maven uses the order of dependencies in the POM to build the classpath so you can manipulate it. Just declare the "right" jar first and your app will pick the class from it.

From the release notes of maven 2.0.9:

MNG-1412 / MNG-3111 introduced deterministic ordering of dependencies on the classpath. In the past, natural set ordering was used and this lead to odd results. The ordering is now preserved from your pom, with dependencies added by inheritence added last. In builds that had conflicting or duplicate dependencies, this may introduce a change to the output. In short, if you have weird issues with 2.0.9, take a look at the dependencies to see if you have conflicts somewhere.

Pascal Thivent
Thanks for your explanation. I have tried rearranging my pom but it didn't shoot out the problem. Looks like it's not a problem with order of dependency any more. I have asked another question here: http://stackoverflow.com/questions/2619880/unbelievable-cannot-cast-from-class-x-to-its-super-class.
Phương Nguyễn