Skip to content

Conversation

@hub-cap
Copy link
Contributor

@hub-cap hub-cap commented Jul 18, 2017

This commit removes all external dependencies from the rest client jar,
and shades them in an 'internal.' package within the jar, using
shadowJar gradle plugin. All projects that depended on the existing jar
have been converted to using the 'internal.' package prefixes to
interact with the rest client.

Closes #25208

@hub-cap hub-cap added :Java High Level REST Client :Clients/Java Low Level REST Client Minimal dependencies Java Client for Elasticsearch labels Jul 18, 2017
Copy link
Contributor Author

Choose a reason for hiding this comment

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

heh, will fix this comment

Copy link
Member

@javanna javanna left a comment

Choose a reason for hiding this comment

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

I left a couple of comments, I will leave the gradle part to @rjernst for review. Did I get it right that the plan is to have two artifacts, one with deps and the other one without?

Copy link
Member

Choose a reason for hiding this comment

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

why is httpcore replaced with the low-level rest client here?

Copy link
Member

Choose a reason for hiding this comment

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

I think I get it. either we use the ordinary httpcore classes, or the internal ones but they come from our own big jar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

well, we really cant use ordinary ones now. Since all of the dependencies in rest client are shaded to use internal.org.apache classes, if we leak anything like Header into an API, we need to use the internal.org.apache since those are in the method signatures. So, we have to use our internal ones always, which is why we removed the httpcore stuff, because client/test now uses internal.o.a.h.Header, for example.

Copy link
Member

Choose a reason for hiding this comment

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

thanks for the explanation!

Copy link
Member

Choose a reason for hiding this comment

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

don't we need to remove the existing jar entry without the suffix?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hopefully this will be explained better in the commit msg update

Copy link
Member

Choose a reason for hiding this comment

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

I also do not understand why both of these are necessary. The rest client used by the test framework for REST integ tests should be using the jar with no classifier. The deps version above should replace the 2 http grants below? I don't see where the nodeps version would come in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't, anymore :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I lied, it does, in an IDE /sadface

Copy link
Member

Choose a reason for hiding this comment

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

So we need the grant above for gradle and the grant below for the IDEs which don't use the fully shaded dependency. They use the -nodeps jar. I think they should be using the shadedDeps jar rather than the original dependencies. That way the packages line up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Id love for them to use the shaded jar itself, but we use project dependencies, and intellij is smarter than me when it comes to dealing w/ dependencies. here is what happens to the other projects, and they seem to (only in intellij) depend on the jar task w/ the funky classifier, even though I remove it from the runtime artifacts and remove the extendsFrom compile. So these stay, just for intellij purposes. And they are using the same packages anyway, since the -deps jar and the no classifier actual shaded jar have the same relocate bits.

image

@hub-cap
Copy link
Contributor Author

hub-cap commented Jul 19, 2017

@javanna Ill leave some better comments in the github commit on why the artifacts are split out like that. its somewhat confusing.

@hub-cap
Copy link
Contributor Author

hub-cap commented Jul 20, 2017

ok I decided to just add better docs to the build.gradle instead. Its saner there anyway.

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

I left a couple comments. I also think we should think of a better package name prefix, since these are part of the api (sorry I did not realize that when suggesting the name in the first place!).

Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't there be no need to use relocate here? If there is then unit tests ran with unshaded classes, which is exactly what we were trying to avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the duplicated shadowing task that actually shades the classes in src as well as the internal. things.

Copy link
Member

Choose a reason for hiding this comment

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

That is my point. We shade the dependency itself. Nothing in src should be referring to unshaded packages, so there should be no need to do t his relocation here.

Copy link
Member

Choose a reason for hiding this comment

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

I also do not understand why both of these are necessary. The rest client used by the test framework for REST integ tests should be using the jar with no classifier. The deps version above should replace the 2 http grants below? I don't see where the nodeps version would come in.

Copy link
Member

Choose a reason for hiding this comment

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

thanks for adding this comment!

@hub-cap
Copy link
Contributor Author

hub-cap commented Jul 20, 2017

@javanna @rjernst I have cleaned up the build so that it uses the actual shaded jar outside of the rest project, instead of relying on the transient project dependencies (which was the -deps.jar). I have also removed the -nodeps jar from existence outside of the build, so the shaded jar is the only thing that other projects know about / build to.

@rjernst
Copy link
Member

rjernst commented Jul 20, 2017

Just a note about this in general: I think as a followup (for rc/GA) we need to pull javadocs from the deps and add them to the generated client jar javadocs.

@hub-cap hub-cap force-pushed the issues/25208 branch 3 times, most recently from 54c9d76 to 8e5060b Compare July 21, 2017 20:15
hub-cap added 6 commits July 23, 2017 22:43
This commit removes all external dependencies from the rest client jar,
and shades them in an 'internal.' package within the jar, using
shadowJar gradle plugin. All projects that depended on the existing jar
have been converted to using the 'internal.' package prefixes to
interact with the rest client.

Closes elastic#25208
@nik9000
Copy link
Member

nik9000 commented Jul 24, 2017

also think we should think of a better package name prefix, since these are part of the api

We could, in the grand tradition of Java, go super verbose with something like org.elasticsearch.client.shaded.httpcomponents.

Copy link
Member

@tlrx tlrx left a comment

Choose a reason for hiding this comment

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

This looks promising. I have compilation errors in my IDE but maybe it's due to Intellij IDEA 2017.1.


/**
* The rest client is a shaded jar. It contains the source of the rest client, as well as all the dependencies,
* shaded to the `internal.` package. 3 artifacts come out of this build process.
Copy link
Member

Choose a reason for hiding this comment

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

nit: doc needs to be updated once the package name is defined

signature "org.codehaus.mojo.signature:java17:1.0@signature"
}

dependencyLicenses.dependencies = project.configurations.shade
Copy link
Member

Choose a reason for hiding this comment

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

I think we'll have to clean Apache license and notice files in the final Jar using a Shadow plugin Transformers or build our own one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ill chat w/ ryan about this, good call for bringing it up

Copy link
Member

Choose a reason for hiding this comment

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

Good idea


/**
* The rest client is a shaded jar. It contains the source of the rest client, as well as all the dependencies,
* shaded to the `internal.` package. 3 artifacts come out of this build process.
Copy link
Member

Choose a reason for hiding this comment

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

internal. is no longer accurate.

* 3) The *actual* jar that will be used by clients. This has no classifier, contains the rest client src and `internal.`.
* This jar is the only actual output artifact of this job.
*
* The IDE does not like removing artifacts and changing configurations on the fly, so the bits that make the build
Copy link
Member

Choose a reason for hiding this comment

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

s/The IDE/IDEs/ ? I expect you mean IntelliJ and Eclipse.

* The reason this jar was not overwritten was because gradle knows what its inputs and outputs are for a given task
* and we should not alter that by overwriting the original jar. What we do is add a `nodeps` classifier to it instead.
* This jar is removed from the output artifacts in cli, and retained in IDE builds.
* 2) A jar that contains *only* the `internal.` dependencies. This is a jar that is built before the src is compiled.
Copy link
Member

Choose a reason for hiding this comment

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

I like this comment but I'd rephrase it, maybe moving the number 2 jar to the number 1 jar and explaining that it is also there for IDEs. I think it'd be good also to explain that we use the shaded package names in the source so we still jar up the bits that come out of javac without any post processing.

allprojects {
if (project.path == ':test:framework') {
if (project.path == ':test:framework' || project.path == ':client:test') {
// :test:framework:test cannot run before and after :core:test
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a comment explaining why :core:test also cannot run before :core:test?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ill leave that for ryan to answer heh

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand your statement @nik9000. The task graph cannot have cycles, and a dependency on yourself is still a cycle.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, :client:test cannot run before :core:test. Basically, if we are going to leave a comment explaining why :test:framework needs this exemption we should probably explain the :client:test too.

Copy link
Member

Choose a reason for hiding this comment

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

Ok I see the confusion. The comment should be updated. It means that if the code below this were to run, a circular dependency would be added between :test:framework:test and :core:test. Likewise, the new check is added because :client:test would have a circular task dep with :client:rest:test.

shadowJar {
configurations = [project.configurations.shade]
classifier = null
relocate 'org.apache', 'org.elasticsearch.client'
Copy link
Member

Choose a reason for hiding this comment

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

I think it'd be clearer to do this with the regular jar task because you are just combining the two jar files into one, right? At least, I thought that is what we'd talked about doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, at this point I could combine the deps jar with the src/ in the project. I can follow up with this, as its a better idea than running another "very similar" shadow task. I can follow up with this

}

jar {
// rename the default jar because we are removing the classifier from the shadowJar, which is a null classifier
Copy link
Member

Choose a reason for hiding this comment

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

I'd say something like "move the default jar to another classifier so the jar with the dependencies can have the empty classifier".

Copy link
Member

Choose a reason for hiding this comment

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

So we need the grant above for gradle and the grant below for the IDEs which don't use the fully shaded dependency. They use the -nodeps jar. I think they should be using the shadedDeps jar rather than the original dependencies. That way the packages line up.

@rjernst
Copy link
Member

rjernst commented Jul 24, 2017

We could, in the grand tradition of Java, go super verbose with something like org.elasticsearch.client.shaded.httpcomponents

Please let's not do that. The package names have real costs (eg Windows file path limits).

@nik9000
Copy link
Member

nik9000 commented Jul 24, 2017

Please let's not do that. The package names have real costs (eg Windows file path limits).

Fine by me. I'd certainly prefer it if all the shaded things were grouped together in some obvious way but I'm not going to block anything over it.

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

This works great for me from the CLI. I at first had issues testing it with IntelliJ, in 2016.2. I upgraded to 2017.2, but still had issues. I then tried using the "module per source set" option and it "sort of" worked, but I needed to downgrade to 2017.1. So, I think we should add a note in CONTRIBUTING that using the module per source set option is now required, and probably also a note that 2017.1 is recommended (2017.2 was just recently released so I expect the issue should be fixed in a patch release).

@hub-cap
Copy link
Contributor Author

hub-cap commented Jul 24, 2017

👍 ill create a few issues off this initial one based on the feedback here

@hub-cap hub-cap merged commit e816ef8 into elastic:master Jul 24, 2017
@javanna
Copy link
Member

javanna commented Jul 24, 2017

thanks @hub-cap ! Was this supposed to go to 5.x too? I see it has the 5.6 label.

@hub-cap
Copy link
Contributor Author

hub-cap commented Jul 24, 2017

yes i have backported it, ty for keepin an eye out @javanna <3

@hub-cap hub-cap deleted the issues/25208 branch July 25, 2017 05:43
@javanna javanna added :Clients/Java Low Level REST Client Minimal dependencies Java Client for Elasticsearch and removed :Java High Level REST Client labels Aug 1, 2017
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.

Shade client jars and build uber jar

6 participants