11

I have the following situation:

+ DentistApp
   L TreatsLibrary
     L IceCream 1.0
   L CavityCausesLib
     L IceCream 2.0

Now I get a VerifyError because TreatsLibrary is using IceCream.giveToKidAfterDrill() which was removed in version 2.0 because of legal reasons.

How do I import both versions and make sure that each uses its own?

gurghet
  • 7,591
  • 4
  • 36
  • 63
  • 2
    This cannot be done by just using one ClassLoader as in one ClassLoader, only one version of the class can exist. You may want to take a look at OSGi if you don't want to implement your own class loading mechanism. – dzhg Nov 11 '17 at 05:40
  • Yes it can be done, I just don't remember how, it had to do with renaming libraries – gurghet Nov 11 '17 at 13:32
  • You tagged this with sbt-assembly, which will only help you if you package your libraries using an uber JAR. – Yuval Itzchakov Nov 15 '17 at 12:29
  • I am using a Uber jar – gurghet Nov 15 '17 at 12:30
  • *"No they are not used in the project only in dependencies"* What does this have to do with what I've answered? Shading happens when you package your uber JAR, and at runtime these classes will have different package names – Yuval Itzchakov Nov 15 '17 at 12:31
  • Alright. I now get it that `sbt-assembly` has the ability to shading the classes. https://github.com/sbt/sbt-assembly#shading – dzhg Nov 17 '17 at 01:12

1 Answers1

7

This answer assumes you're talking about how to load these libraries from a packaged uber JAR at runtime.

You need to shade your dependencies using sbt-assembly. This can be done as follows:

assemblyShadeRules in assembly ++= Seq(
  ShadeRule.rename("IceCream.**" -> "my_icecream.@1")
    .inLibrary("com.library.treats" % "TreatsLibrary" % "1.0.0")
    .inProject
)

This will shade the IceCream dependency in your com.library.treats and change every package name to begin with my_icecream.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • No they are not used in the project only in dependencies – gurghet Nov 15 '17 at 12:28
  • @gurghet Not sure what that has to do with my answer. This will shade any dependency, regardless if it's written by you or packaged by a third party. – Yuval Itzchakov Nov 15 '17 at 12:33
  • What does inproject do? – gurghet Nov 15 '17 at 13:17
  • @gurghet Goes over all your library dependencies in your project. i.e. if it has a reference to `com.library.treats.TreatsLibrary` it now needs to change it to `my_icecream.TreatsLibrary`. – Yuval Itzchakov Nov 15 '17 at 13:27
  • from the README: `call .inProject to match your project source` so no it would be useless – gurghet Nov 16 '17 at 16:34
  • @gurghet If you change a librarys namespace, and your code references the old namespace, how will your code compile? Trust me, you need it. – Yuval Itzchakov Nov 16 '17 at 16:45
  • @YuvalItzchakov but you still have the nonshaded IceCream 2.0 on your classpath, don't you? or else how does CavityCausesLib work? – K. M Aug 15 '18 at 20:48
  • @K.M I do, but now they have different artifact ids, so they no longer clash. – Yuval Itzchakov Aug 16 '18 at 06:44
  • @YuvalItzchakov if the non-shaded one is still on the classpath, does that mean that the `.inProject` line is not necessary? if my code references the old namespace, the old namespace should still be there. however, i tried a setup similar to this, and it actually doesn't work without `.inProject` and I don't understand why. shouldn't my `IceCream.**` refs in my code still hit IceCream 2.0? – K. M Aug 16 '18 at 18:41