-
Notifications
You must be signed in to change notification settings - Fork 25k
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
Java 9: requiring elasticsearch from module-info.java fails with "module not found" #28984
Comments
Can you elaborate on this? I think Codec and DocValuesFormat are leftover from long ago when we had custom versions of these in ES. PostingsFormat contains Completion50PostingsFormat which is still used. Is the issue just that Codec and DocValuesFormat are empty (we can remove them)? |
I added a Gradle test module in the PR, but I couldn't reproduce my maven project behaviour. @rjernst,
This is really weird. |
I created https://github.com/Cosium/jigsaw-elasticsearch which allows to reproduce the issue. |
And a ticket in Maven compiler tracker https://issues.apache.org/jira/browse/MCOMPILER-328 |
https://issues.apache.org/jira/browse/MCOMPILER-328?focusedCommentId=16398365&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-16398365 confirms that Maven get the automodule name directly from the JDK. That would mean that Gradle computes the module name itself, which is more brittle. |
I created a Gradle equivalent: Therefore:
|
Pinging @elastic/es-core-infra |
After much debugging ! Classpath vs Modulepath in Java 9The modulepath should contain all modular jars. That includes jars containing well defined A jar in the module path can't access a jar in the classpath. Maven behaviourFor each jar:
With elasticsearch as unique dependency:
With commons-io as unique dependency:
Gradle behaviourGradle doesn't make any kind of jigsaw module autodetection. The experimental jigsaw plugin, seems to do the same thing: ConclusionThe jar built by my project being defined by a IMO, there is no point in trying to reproduce the current issue with a dedicated Gradle module, since it entirely depends on the way the end user will configure Gradle. Besides, it is unlikely that Gradle user is aware of the current issue since he will probably never use the JDK api allowing to select automodules. So the fix seems to be the good one to me. I think it would be easier to have a Maven module, since Maven has the correct behaviour. |
Ping @rjernst , @jasontedor |
Ping @rjernst, @jasontedor |
I don't understand how this is a |
@nicolaiparlog The label was a mislabeling and I have removed it. |
@jasontedor the label is still on the linked PR |
@jasontedor any idea on when this will be fixed/included in a release? thx! |
You can only fix this by making Elasticsearch a real module. Automodules don't work for Elasticsearch. There are several problems: Elasticsearch contains classes from a package it does not own (org.apache.lucene) and also defines SPIs for them. This needs to be exposed via module-info.java. But this won't still not work, as Lucene is not module conformant (for the same reasons). |
@uschindler as the discussion in this issue shows, there is a fix available, it only has to be merged and released. So converting to an explicit module is not needed yet. Putting an automatic module name in the manifest does no harm, on the contrary, it makes sure that elasticsearch reserves its module name. |
The problem is that it won't still not work at runtime, because the SPI won't load. The good thing is that Elasticsearch does no longer implement SPIs (Codecs). And if you just use the Elasticsearch client, you won't run into trouble, because Lucene is just a dependency, but it's actually not used (only for classloading). |
So in short there are multiple problems: The empty/missing META-INF/services are a bug in Elasticsearch. This violates the spec (also for older Java versions, but nothing cares). Once you have fixed this and added an automatic module name, it compiles. |
@uschindler thx for the clarification. I do think that if this gets fixed for elasticsearch it can be deployed as automatic module and we can keep lucene on the classpath for now. (automatic modules can read from the classpath) That way at least explicit modules can use the elasticsearch automatic module, and lucene remains on the classpath until a redesign has been done. |
@jasontedor can someone prioritise this issue so that the elasticsearch jar is at least compatible with jdk specs? i.e. including META-INF/services files for classes and packages that don't exist in the jar is just wrong. Then the community can start using elasticsearch on the module path of the jdk. Thx in advance. |
I did some tests on the current master. Since we don't support elasticsearch, I think that the us-case that triggers this is being able to write a modularized application that talks to ES via one of the clients.
And just a class to test the communication:
Note that this now requires to have more requires in
We have to tell Gradle to put these jars on the module path and make them automatic modules.
Like @uschindler mentions, elasticsearch has classes in lucene packages and lucene itself has packages spread across modules. Probably the best path to be able to use the high level rest client in a modular application is to remove elasticsearch(server) as a dependency, and reshuffle packages so it doesn't have any in common with the low level rest client. If the dependencies allow it we could potentially make it into a real module. I was not able to replicate the issues with the empty service files just by requiring elasticsearch from a modules-info. I haven't checked what changed, but the linked PR that adds a reproduction is old. I tried against latest master.
With this Gradle setup
I'm not saying we shouldn't remove the empty service files. I'll create a PR for that, no need to keep them around, but I don't see how this setup could be useful. To summarize I would like to move forward with the following:
@jasontedor @rjernst thoughts ? Right now the best bet for modular applications is to use the low level rest client, or keep all the elasticsearch jars on the classpath and have all ES specific code localized in an automated module in their application to be able to access them. This would allow the rest of the application to benefit from modularization without requiring elasticsearch to change. |
As mentionned in the previous messages, if you did that with Gradle it's normal. |
Closing in favor of #38299 |
Elasticsearch version (
bin/elasticsearch --version
): 6.2.2JVM version (
java -version
): 9.0.4OS version (
uname -a
if on a Unix-like system): Ubuntu 17.10Description of the problem including expected versus actual behavior:
We are migrating our Maven project to Java 9.
In each module of our project, we add a
module-info.java
.Everything works fine for every dependencies except elasticsearch.
Requiring it from module-info fails with:
Steps to reproduce:
Analysis:
I debugged
maven-compiler-plugin
and that lead me tojdk.internal.module.ModulePath
.It fails in
jdk.internal.module.ModulePath
at line 557:The issue comes from the fact that no elasticsearch packages match the following declared Java services:
Those service declarations either need to be moved to another project, or a fake class should be added to
org.apache.lucene.codecs
.The text was updated successfully, but these errors were encountered: