Skip to content

Remove guava from transitive compile classpath#54309

Merged
rjernst merged 16 commits intoelastic:masterfrom
rjernst:guava_runtime
Apr 2, 2020
Merged

Remove guava from transitive compile classpath#54309
rjernst merged 16 commits intoelastic:masterfrom
rjernst:guava_runtime

Conversation

@rjernst
Copy link
Copy Markdown
Member

@rjernst rjernst commented Mar 26, 2020

Guava was removed from Elasticsearch many years ago, but remnants of it
remain due to transitive dependencies. When a dependency pulls guava
into the compile classpath, devs can inadvertently begin using methods
from guava without realizing it. This commit moves guava to a runtime
dependency in the modules that it is needed.

Note that one special case is the html sanitizer in watcher. The third
party dep uses guava in the PolicyFactory class signature. However, only
calling a method on the PolicyFactory actually causes the class to be
loaded, a reference alone does not trigger compilation to look at the
class implementation. There we utilize a MethodHandle for invoking the
relevant method at runtime, where guava will continue to exist.

Additionally, this commit adds a build time check that we do not add any compile dependency on guava.

Guava was removed from Elasticsearch many years ago, but remnants of it
remain due to transitive dependencies. When a dependency pulls guava
into the compile classpath, devs can inadvertently begin using methods
from guava without realizing it. This commit moves guava to a runtime
dependency in the modules that it is needed.

Note that one special case is the html sanitizer in watcher. The third
party dep uses guava in the PolicyFactory class signature. However, only
calling a method on the PolicyFactory actually causes the class to be
loaded, a reference alone does not trigger compilation to look at the
class implementation. There we utilize a MethodHandle for invoking the
relevant method at runtime, where guava will continue to exist.
@rjernst rjernst added :Core/Infra/Core Core issues without another label >refactoring v8.0.0 v7.8.0 labels Mar 26, 2020
@elasticmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-core-infra (:Core/Infra/Core)

@rjernst rjernst requested a review from mark-vieira March 26, 2020 23:13
@mark-vieira
Copy link
Copy Markdown
Contributor

When a dependency pulls guava into the compile classpath, devs can inadvertently begin using methods from guava without realizing it. This commit moves guava to a runtime dependency in the modules that it is needed.

And people thought Gradle was being dumb by introducing api vs implementation 😉 This is exactly the reason for making such a distinction.

Copy link
Copy Markdown
Contributor

@mark-vieira mark-vieira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple comments, otherwise LGTM.

configuration.resolutionStrategy.eachDependency {
String artifactName = it.target.name
if (FORBIDDEN_DEPENDENCIES.contains(artifactName)) {
throw new GradleException("Dependency '${artifactName}' on configuration '${configuration.name}' is not allowed. " +
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to include the full path to the configuration here as just saying "compileClasspath" isn't going to be particularly helpful.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the current failure output. It has the full path in the first part of the error.

> Could not resolve all files for configuration ':x-pack:plugin:identity-provider:compileClasspath'.
   > Could not resolve com.google.guava:guava:19.0.
     Required by:
         project :x-pack:plugin:identity-provider
      > Dependency 'guava' on configuration 'compileClasspath' is not allowed. If it is needed as a transitive depenency, try adding it to the runtime classpath

}

subprojects {
pluginManager.withPlugin('java') {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth nothing that standalone QA projects do no apply the java plugin but only java-base.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate that, but still think this is a good start.

@rjernst rjernst merged commit 9191c93 into elastic:master Apr 2, 2020
@rjernst rjernst deleted the guava_runtime branch April 2, 2020 19:54
@jasontedor
Copy link
Copy Markdown
Member

This pull request is a thing of beauty to bury the zombie that tried to come back.

rjernst added a commit to rjernst/elasticsearch that referenced this pull request Apr 2, 2020
Guava was removed from Elasticsearch many years ago, but remnants of it
remain due to transitive dependencies. When a dependency pulls guava
into the compile classpath, devs can inadvertently begin using methods
from guava without realizing it. This commit moves guava to a runtime
dependency in the modules that it is needed.

Note that one special case is the html sanitizer in watcher. The third
party dep uses guava in the PolicyFactory class signature. However, only
calling a method on the PolicyFactory actually causes the class to be
loaded, a reference alone does not trigger compilation to look at the
class implementation. There we utilize a MethodHandle for invoking the
relevant method at runtime, where guava will continue to exist.
rjernst added a commit that referenced this pull request Apr 8, 2020
Guava was removed from Elasticsearch many years ago, but remnants of it
remain due to transitive dependencies. When a dependency pulls guava
into the compile classpath, devs can inadvertently begin using methods
from guava without realizing it. This commit moves guava to a runtime
dependency in the modules that it is needed.

Note that one special case is the html sanitizer in watcher. The third
party dep uses guava in the PolicyFactory class signature. However, only
calling a method on the PolicyFactory actually causes the class to be
loaded, a reference alone does not trigger compilation to look at the
class implementation. There we utilize a MethodHandle for invoking the
relevant method at runtime, where guava will continue to exist.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants