Shading Google Guava in Dropwizard

479 views
Skip to first unread message

"Ionuț G. Stan"

unread,
Jun 22, 2012, 1:15:06 PM6/22/12
to dropwiz...@googlegroups.com
I've got a classpath conflict because of Guava. Dropwizard 0.4.0 already
comes with two Guava versions. 12.0 on which Dropwizard depends
directly, and r07 through jackson-datatype-guava. Now, in order to have
a useful app I need to bring in my code from other projects, which
apparently includes transitively yet another two different Guava
versions. The end result is that I have four Guava versions on classpath
and I can't run the app because they're incompatible.

I've tried upgrading libraries in my own code hoping the problem will go
away. Unfortunately my app will simply break with too much upgrade work
needed in order to fix it.

I was thinking that maybe I can maintain a forked version of Dropwizard
in which I would relocate "com.google.common" to some other package
using the maven-shade-plugin. This is what elasticsearch is doing and
where I got the idea from.

As I don't have experience with the maven-shade-plugin, is it possible
to do this for Dropwizard? If yes, how?

I've tried adding this snippet[0] at the end of dropwizard-core/pom.xml
but it dies with an error in dropwizard-db. I've added the same snippet
in dropwizard-db/poml.xml too, but then it dies with some "invalid
signature" error. Adding it to the parent POM won't work either.

Any help, including an alternative solution to the classpath problem,
would be greatly appreciated. I'm kind of losing my minds with this.

[0]: https://gist.github.com/2974019

--
Ionuț G. Stan | http://igstan.ro

Christopher Elkins

unread,
Jun 22, 2012, 1:41:22 PM6/22/12
to dropwiz...@googlegroups.com
On Jun 22, 2012, at 10:15 AM, Ionuț G. Stan wrote:

> I've got a classpath conflict because of Guava. Dropwizard 0.4.0 already comes with two Guava versions. 12.0 on which Dropwizard depends directly, and r07 through jackson-datatype-guava.

This is arguably a bug.

> Now, in order to have a useful app I need to bring in my code from other projects, which apparently includes transitively yet another two different Guava versions. The end result is that I have four Guava versions on classpath and I can't run the app because they're incompatible.
>
> I've tried upgrading libraries in my own code hoping the problem will go away. Unfortunately my app will simply break with too much upgrade work needed in order to fix it.

Do you have an explicit Guava dependency in your app? If not, it might be as simple as adding one.

> I was thinking that maybe I can maintain a forked version of Dropwizard in which I would relocate "com.google.common" to some other package using the maven-shade-plugin. This is what elasticsearch is doing and where I got the idea from.
>
> As I don't have experience with the maven-shade-plugin, is it possible to do this for Dropwizard? If yes, how?
>
> I've tried adding this snippet[0] at the end of dropwizard-core/pom.xml but it dies with an error in dropwizard-db. I've added the same snippet in dropwizard-db/poml.xml too, but then it dies with some "invalid signature" error. Adding it to the parent POM won't work either.
>
> Any help, including an alternative solution to the classpath problem, would be greatly appreciated. I'm kind of losing my minds with this.
>
> [0]: https://gist.github.com/2974019


I don't think there's any need to mess around with shading to solve this. It can probably be done by explicitly declaring transitive dependencies and excluding the unwanted version(s), but narrowing that down can be a lot of work for little gain. The brute-force way to solve it is by adding a dependency management[1] block to your POM:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>12.0</version>
</dependency>
</dependencies>
</dependencyManagement>

That would effectively pin transitive dependencies to Guava 12.0, regardless of declared version.


1. http://maven.apache.org/pom.html#Dependency_Management

--
Christopher Elkins

Coda Hale

unread,
Jun 22, 2012, 3:09:43 PM6/22/12
to dropwiz...@googlegroups.com
You do not have four versions of Guava on your classpath. Dropwizard
depends on Guava 12.0, Jackson's Guava support depends on 11.0.2.
Maven resolves this conflict by using the non-transitive dependency:
12.0. It's literally impossible for Maven to use two different
versions of the same artifact at the same time.

If you're having problems with libraries which aren't
bytecode-compatible with Guava 12.0, I suggest upgrading those
libraries.
--
Coda Hale
http://codahale.com

"Ionuț G. Stan"

unread,
Jun 22, 2012, 5:55:30 PM6/22/12
to dropwiz...@googlegroups.com
On 22/Jun/2012 22:09, Coda Hale wrote:
> You do not have four versions of Guava on your classpath. Dropwizard
> depends on Guava 12.0, Jackson's Guava support depends on 11.0.2.
> Maven resolves this conflict by using the non-transitive dependency:
> 12.0. It's literally impossible for Maven to use two different
> versions of the same artifact at the same time.

Sorry, I didn't want to imply that I think there are multiple Guava
libraries at the same time. In the end just Guava 12.0 remains on the
classpath. And that would be fine if the version of jclouds we're using
wouldn't depend on some method in Guava that was removed in 12.0. I've
tried upgrading jclouds, and then I hit GSON problems. I upgraded that
and then my app broke. Not the API project, which ideally should be
totally isolated from the core business logic, but the core project itself.

What I'd like to achieve is isolation. I don't want to dig some other
code, totally unrelated to my problem. I want to focus my energies on
the API.

"Ionuț G. Stan"

unread,
Jun 22, 2012, 6:05:12 PM6/22/12
to dropwiz...@googlegroups.com
This is the dependency tree as reported by Eclipse:

http://dl.dropbox.com/u/21300018/classpath.png

On 22/Jun/2012 20:41, Christopher Elkins wrote:
> Do you have an explicit Guava dependency in your app? If not, it might be as simple as adding one.
>
>> I was thinking that maybe I can maintain a forked version of Dropwizard in which I would relocate "com.google.common" to some other package using the maven-shade-plugin. This is what elasticsearch is doing and where I got the idea from.
>>
>> As I don't have experience with the maven-shade-plugin, is it possible to do this for Dropwizard? If yes, how?
>>
>> I've tried adding this snippet[0] at the end of dropwizard-core/pom.xml but it dies with an error in dropwizard-db. I've added the same snippet in dropwizard-db/poml.xml too, but then it dies with some "invalid signature" error. Adding it to the parent POM won't work either.
>>
>> Any help, including an alternative solution to the classpath problem, would be greatly appreciated. I'm kind of losing my minds with this.
>>
>> [0]: https://gist.github.com/2974019
>
>
> I don't think there's any need to mess around with shading to solve this. It can probably be done by explicitly declaring transitive dependencies and excluding the unwanted version(s), but narrowing that down can be a lot of work for little gain. The brute-force way to solve it is by adding a dependency management[1] block to your POM:
>
> <dependencyManagement>
> <dependencies>
> <dependency>
> <groupId>com.google.guava</groupId>
> <artifactId>guava</artifactId>
> <version>12.0</version>
> </dependency>
> </dependencies>
> </dependencyManagement>
>
> That would effectively pin transitive dependencies to Guava 12.0, regardless of declared version.

Thanks for this. I didn't know that would override transitive
dependencies. Anyway, the problem persists because the jclouds version
we're using depends on a method that's been removed from Guava in recent
versions.

I would upgrade jclouds, and then something else that would then cause
problems with GSON, but... then I'll have to fix shit, and honestly, by
that point I would have totally forgotten why I started this project
altogether.
Reply all
Reply to author
Forward
0 new messages