Category: Java

Managing Transitive Dependencies in Maven

Have you ever got a ClassNotFoundException when running tests and yet the dependency that contains the jar is clearly in your pom file? This is most commonly due to collations in transitive dependencies. If Maven cannot decide which version of a dependency to use it will not import it. It will expect you to sort the problem out first.

Handling transitive dependencies should always be done pro-actively. And there is some really good tooling for it. Being a IntelliJ/IDEA developer my self it saddens me to say that in this instance my favourite IDE is outdone by NetBeans. NetBeans uses Maven pom files as it’s project descriptors which makes it very easy to open the project.

When the project is opened in NetBeans you will find the pom.xml file located under project files in the project navigator. Once opened you will find an item named “Show Dependency Graph” in the context menu. This will render a graphical representation of all the projects transitive dependencies.

If any of the dependencies has a red top left corner there is a version conflict. Resolving it is done quickest by opening the context menu for the dependency and selecting “Fix Version Conflict”. Unless you have a specific preference that differs from the default suggestion in the dialogue it is usually fine to got with the default solution.

If any of the dependencies has a yellow top left corner there are more then one version of the dependency requested. Maven will always choose the latest version in the list. This can, and should, however be overridden using the exclusions tag. I tend to take control over all such dependencies buy making sure I clearly choose which one should be included. You have to do this manually by excluding the dependency from each of the dependencies where the version you do not want is included and then ensure that the dependency requiring the correct version is the only one still including it. Sometimes it’s better to exclude it as a transitive dependency altogether and add it as a direct dependency.

Whenever a new dependency is added to the project I make sure to perform the same procedure to ensure that I have full control of the dependencies in my project.

I would be very pleased to find such a great tool in IDEA as well, then I wouldn’t have to run two IDEs at the same time, they do require a lot of resources.

Making Jersey and Spring play together

I am currently working with a REST application that uses JSON as it’s data format. The Jersey framework offers this very nicely out of the box using annotations. The application is a front end that will have several different back ends depending on deployment. To simplify this I have chosen to use JSR-330, dependency injection from Java. The implementation is the Spring Framework.

It took me some time however to find out how to get Spring and Jersey to play together. I had to follow the following steps to get it all to run. I am using Maven 3 as the build and dependency manager.

To instantiate the Spring application context a specific servlet provided by Jersey is needed. To get the jar file we need to add the following dependency to our pom file.

...
  
    com.sun.jersey.contribs
    jersey-spring
    ${jersey-version}
  
...

Now we can replace the traditional Jersey servlet, com.sun.jersey.spi.container.servlet.ServletContainer, with one that also creates an application context, com.sun.jersey.spi.spring.container.servlet.SpringServlet in web.xml. Now the standard web.xml context configuration will be picked up:

...
  
contextConfigLocation
WEB-INF/spring/applicationContext.xml
  
...

With these changes done the Spring framework works as it always does.

Make maven print test output to the terminal

Ever wanted Maven to print the test output to the terminal to save yourself from digging around in the surefire report directory to find out what happened with the failing tests? I have many times but have never invested the time to find out how until now.

It’s pretty straightforward. Set the useFile flag to false in the surefire plug-in. To also skip the xml report output you can set the disableXmlReport to true. Then there will be no reports created when running the tests. Use the profile below to enable this in your pom.


  dev
  


        org.apache.maven.plugins
        maven-surefire-plugin
        
          true
          false
        
      
    
  

Please note that for some odd reason my syntax highlighter lower case all tags. It should be groupId, artifactId, disableXmlReport and useFile in camel case.

To activate this profile you need to add -Pdev. You could have it active by default but then your CI server will not have any test reports. And whilst no reports are fine on the developer machine it’s not very practical on the CI server.

Using getResourceAsStream()

I don’t seem capable to remember some of the most basic things in Java at times. I guess it’s because I do them so rarely that I have time to forget until next time.The other day it was how to define the path for the getResourceAsStream() method. This time I’m going to blog it so I can find the instructions next time I end up not remembering.

I need to read the image named image.jpg located at the absolute build path /Users/tomasmalmsten/code/myproject/src/main/resources/image.jpg. I am using Maven2 so the final location before packaging is /Users/tomasmalmsten/code/myproject/target/classes/image.jpg. And when it’s been packaged it will be in the classes/image.jpg location of the jar file. What I can’t remember is how to create the path so that it can be found by the class loader when using getResourceAsStream().

The trick is to use a / in the beginning of the search path. This denotes that the class loader should start looking at the root, which in the case with image.jpg is where it is. So the path for image.jpg is /image.jpg.

The value of Javadoc

I am currently working with an application I don’t know very well, written for a domain I’m not overly familiar with. This is not an uncommon situation for developers but it can be eased considerably with good documentation. I find that especially well written Javadoc are invaluable since they will show up in the IDE where I need it the most.

So what are the key things to think about when trying to write good documentation that other developers will read? I think the following points are important to think about that will make the documentation valuable.

  • Document what the class/method/field is/should do, not how it does it. The intent of a class/method/field is not always evident from its name but a line or two of Javadoc will make it so.
  • Use a language that is understandable by the client as well as the developers. I tend to find documentation written in the language of the domain the application is solving, with specific words explained, easier to understand since it’s easy to relate to the real world problem then. If the documentation is overly technical it’s difficult to relate it back to the clients requirements and needs.
  • Remember who you are writing for. Generally Javadoc are written for other developers. Developers tend to understand and know technology so there is no need to tell them how something was solved. That should be obvious from reading the code and any in line comments. What needs to be described is how the code solves the real world problem and what part of the domain it relates to.
  • Javadocs are the contract. In my opinion Javadoc are used to detail what is the outcome of running a method or using a class/field. Like a contract. With some detail on how to use it if it’s a public API method. It should not give me any detail on how it arrives to the result. This information is encapsulated in the code and the tests for the code.


If this documentation was readily available in the code base I am currently working my life would have been simpler. But then again perhaps it’s a good thing that I start writing it since I now know what is missing. And perhaps the developer coming next will continue on this work since s/he will find other areas where documentation should have been added.