Tuesday, February 07, 2012

Dependency Lock-in

Update 16/2/2012: I read Apache Camel 2.9 - Reduced dependency on Spring JARs after I wrote following post and wish you to have a read at it as well.

Like version lock-in, dependency lock-in is another thing developers should pay attention to. It happens both when you are developing your own product, and when you are using 3rd party products.

When you're planning your product, it's better not to make any assumption of how it'll be used. Even it IS a web application, you will focus on the core functions first, and later make these core functions accessible via a browser. By thinking and doing this way, you will never make one of your function depending on an HttpServletRequest. The request from web is just one of the many ways to your product.

On the other hand, things become a bit tricky when you include a 3rd party component, especially when including a new dependency in Maven. What you can control is groupId, artifactId and latest version. What does that component depend on is usually out of your control. However it's your responsibility to make sure all the dependencies (and their recursive dependencies) work together happily.

In one of my hobby projects, I want to use Apache CXF to expose core functions to RESTful web services and JSON format, so I include the latest version of Apache CXF Runtime JAX-RS Frontend, org.apache.cxf:cxf-rt-frontend-jaxrs:jar:2.5.2. After running mvn eclipse:eclipse, I found my project is locked in to Spring Framework 3.0.6. org.springframework:spring-core:jar:3.0.6.RELEASE is directly included, and org.springframework:spring-web:jar:3.0.6.RELEASE is indirectly included by org.apache.cxf:cxf-rt-frontend-jaxrs:jar:2.5.2. Please look at the follow dependency tree.

+- org.apache.cxf:cxf-rt-frontend-jaxrs:jar:2.5.2:compile
|  +- org.springframework:spring-core:jar:3.0.6.RELEASE:compile
|  |  +- org.springframework:spring-asm:jar:3.0.6.RELEASE:compile

|  +- org.apache.cxf:cxf-rt-transports-http:jar:2.5.2:compile
|  |  +- org.apache.cxf:cxf-rt-transports-common:jar:2.5.2:compile
|  |  \- org.springframework:spring-web:jar:3.0.6.RELEASE:compile
|  |     +- org.springframework:spring-beans:jar:3.0.6.RELEASE:compile
|  |     \- org.springframework:spring-context:jar:3.0.6.RELEASE:compile
|  |        +- org.springframework:spring-aop:jar:3.0.6.RELEASE:compile
|  |        \- org.springframework:spring-expression:jar:3.0.6.RELEASE:compile

I do decide to use Spring, but don't want to be decided by Apache CXF. Moreover, I'd like to use Spring 3.1.0. It's not hard to solve this problem by modifying pom.xml.

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.5.2</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.0.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

Don't dependency lock-in yourself, and don't dependency lock-in the users of your products.

Happy coding!

No comments:

Post a Comment