Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary incompatibility between v2.1.11 and v2.2.x due to AhcWSClientConfig #845

Open
cptwunderlich opened this issue Feb 1, 2024 · 2 comments

Comments

@cptwunderlich
Copy link

I'm upgrading our services from Play 2.8 to 2.9 (and play-ws 2.2.5). A service has a dependency on another packages, which provides a client (which uses play-ws). That dependency is still on Play 2.8 / play-ws 2.1.11.

There are no eviction warnings or binary incompatibility errors, but I get an Exception at runtime:

java.lang.NoSuchMethodError 'int play.api.libs.ws.ahc.AhcWSClientConfig$.apply$default$6()'

We create an instance of AhcWSClientConfig directly, like so:

AhcWSClientConfig(
    WSClientConfig(connectionTimeout = settings.http.connectionTimeout, requestTimeout = settings.http.requestTimeout)
  )

Unfortunately, a new field was added to that case class a while ago. Even though there are default values provided, this is not binary compatible.
(AhcConfig in 2.1.11 vs AhcConfig in 2.2.5 )

It would be great to get a compiler error, instead of a runtime error. I am not sure how to achieve that though. Not sure if versionScheme could be used, since in this case, the minor version increase is a binary incompatible version.
Evolving case classes in a binary compatible way is an issue in general.

While I'd like a solution for my immediate problem (i.e., a build failure would be nice to catch this in CI), I also wonder how to avoid this in the future.

@mkurz
Copy link
Member

mkurz commented Feb 27, 2024

versionScheme might be an approach. However, in general I see that more as a "problem" of Scala and not play-ws. On our side we can just take more care to not break code (which we can not always avoid) or start working with versionScheme settings, which we do not do right now.
In general I would advice to always make sure your dependencies makes use of the same major/minor releases like you main lib/app does. Patch releases should not break in general.

@cptwunderlich
Copy link
Author

Yes, I agree, that this is a general Scala issue. Things like versionScheme are workarounds.
The problem is, that tools like scala-steward can upgrade your dependencies without you noticing if you didn't pin them and then your service fails at runtime.
An integration test would have to actually use the client to trigger this exception. Unfortunately, that makes things more complicated, so we just mock the client.

So, yes, keeping all versions the same is definitely the way to go, but difficult if you have many services, automatic dependency updates and start updating your services gradually. Bc. incompatible versions can sneak in and it's hard to find that before running them without something like versionScheme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants