Untangling Maven dependencies

Standard

The Maven Project Object Model (POM) of a Java project contains references to all the libraries that are used in that particular project. These libraries are called dependencies in Maven and Maven handles for you the dirty work of downloading and managing the packages of the dependencies and including them in your project. It is a formidable tool but it can confront you with tricky puzzles from time to time.

In many Java test automation projects you’ll find references to Selenium libraries because Selenium is a popular tool for GUI test automation. In the project that I worked on as a test automation engineer some Selenium libraries were used. My Maven dependency challenge began when I wanted to start using Headless Chrome for UI automation. Headless Chrome is a handy browser because it does not require the actual Chrome browser so it is possible to run UI tests without the actual UI. It takes away some of the problems of using normal browsers for GUI automation, such as sluggishness and the need to be precise about the browser window size.

The starting point

I join the test automation project when it is already in full swing. As such, there is an existing Maven POM file which contains references to some Selenium libraries. There is, for example, a reference to the Selenium Chrome Driver library. This is the client library that is used in the Java code. The dependency is included in the Maven POM as below.

<dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-chrome-driver</artifactId>
   <version>3.0.1</version>
</dependency>

As you can see the version of the library is 3.0.1 which is a version that was released in October 2016.

In order to run Headless Chrome, it appears that at least version 59 of the Chrome browser is needed. This version of Chrome was released in May 2017, so in order to avoid compatibility conflicts I think it best to upgrade the version of the Selenium Chrome driver library. In retrospect I cannot find evidence that Chrome version 59 depends on a later version of the Selenium Chrome driver library, but this does not occur to me at that moment.

Making a mess

As we saw above the Selenium Chrome driver library can be included as a separate dependency in the Maven POM. But it is not necessary to include this driver library and other driver libraries (such as those for FireFox and Internet Explorer) separately since they are also a compile dependency of the encompassing Selenium Java library. So by including the Selenium Java library as a dependency I would be able to get rid of all the separate Selenium dependencies, which makes the POM a whole lot simpler. I decide to try this approach and copy the dependency from the POM of another test automation project. Here is the code that I copied.

<dependency>
   <groupId>org.seleniumhq.selenium</groupId>
   <artifactId>selenium-java</artifactId>
   <version>3.4.0</version>
</dependency>

As you notice, the version of the library is 3.4.0. This is by no means the latest version, but at the time I forget to look up what the latest version is. I am really satisfied having reduced the number of Selenium dependencies from five to one and hit the ‘maven clean install’ command to build the code. To my amazement, the code does not compile!

Untangling the web of dependencies

The compiler tells me that there is a certain method that is used in the Java code that cannot be recognized anymore. The method is JsonObject.keySet(), which is used in some part of the code that processes JSON files. The only thing I changed in the project was the Selenium dependencies, so I am flabbergasted by the fact that suddenly the compiler is tripped up by a JSON error. The two are entirely unrelated. In the import statement of the class in which the keySet() method is used it appears that the Google Gson library is somehow imported. This means that the Google Gson library should be mentioned in the Maven POM file. I look at the POM file. There is no Google Gson dependency! I roll back the changes that I made to the POM file. Still no Google Gson dependency! Where does this dependency come from??

Then I remember that Maven does a lot of the heavy lifting for you. Libraries can have compile dependencies and Maven manages the compile dependencies for you. We saw that the Selenium Java library has all the Selenium drivers as compile dependencies and that creating a dependency for the Selenium Java library dismisses us from having to import these driver libraries separately. So the Google Gson library must be a compile dependency of a library that is actually mentioned in the POM file!

I use IntelliJ as an IDE and IntelliJ has a useful array of plugins. One the plugins is the Maven Helper. This plugin allows you to dig deeper into the web of dependencies that is set up in the POM. It has a handy little search box that allows you to search through the dependencies and their compile time dependencies. Using this tool I find that the Google Gson library is actually a compile time dependency of the FireFox driver library. It is a bonus—so to say—that come with the Firefox driver package. See the screen shot below for the search using the Maven Helper plugin.

Furthermore, I notice that the version of the FireFox driver library that I use needs version 2.8.2 of the Google Gson library. Then I roll forward to the changes that I made in the POM file and see that version 3.4.0 of the Selenium Java library that I introduced only has version 2.8.0 of the Google Gson library as a compile dependency. Could it be that the keySet() method that was not recognized after I made the changes to the POM was introduced in version 2.8.1 or version 2.8.2 of the Google Gson library? Luckily the Google Gson Change Log provides the answer: the keySet method was introduced in version 2.8.1. So I cannot use version 3.4.0 of the Selenium Java library, unless I create a separate dependency for the Google Gson library in the POM. But that would lead to a dependency conflict.

Fixing it

Then I look again at the version of the Selenium Java library. Is 3.4.0 really the latest version or is there a later version that includes version 2.8.2 of the Google Gson library as a compile dependency? A quick search in the Maven repository tells me that version 3.11.0 is actually the latest version and that this version has version 2.8.2 of the Google Gson library as a compile dependency. I change the version of the Selenium Java library in the POM and hit ‘maven clean install’ again. This time the code builds successfully.

Used tools

  • IntelliJ
  • IntelliJ Maven Helper plugin
  • Maven repository browser
  • Google Search
Advertisements

One thought on “Untangling Maven dependencies

  1. I’ll have to try out this Maven Helper Plugin, looks very useful. In the past i’ve usually resorted to commands such as mvn dependency:tree and mvn help:effective-pom to resolve these kind of issues.

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 )

Google+ photo

You are commenting using your Google+ 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