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

Add Java 11 compatibility #2812

Closed

Conversation

leonardehrenfried
Copy link
Member

@leonardehrenfried leonardehrenfried commented Aug 24, 2019

To be completed by pull request submitter:

  • issue: Fixes Target Java 11 #2717
  • roadmap: Not on the roadmap, it appears
  • tests: n/a
  • formatting: n/a
  • documentation: If you are adding a new configuration option, have you added an explanation to the configuration documentation tables and sections?
  • changelog: add a bullet point to the changelog file with description and link to the linked issue

To be completed by @opentripplanner/plc:

  • reviews and approvals by 2 members, ideally from different organizations
  • after merging: update the relevant card on the roadmap

This PR adds is a first try of making OTP work with Java 11. I got very close but I'm stuck with a single problem right now.

I did the following:

  • Updated the relevant Maven plugins
  • Added a module-info.java that lists all the required modules (has to be maintained manually - gross but necessary)

This made the project compile and the tests run.

The last remaining problem is the ObjectDiffer usage in GraphInitializationTest, which relies heavily on reflection. Its extensive usage of reflection sd problematic under Java 11.

I tried to work around it by adding --add-opens command line arguments to the forked test JVM and made some progress. However, I also had to add 2 classes to ObjectDiffer's ignore list:

  • Method as it was part of a proxy object which could not be reflected on in Java 11
  • JarFile: the caused a stack overflow in the test but I'm not actually what exactly has changed since Java 8 to make this use a huge stack.

In the end, I made the test pass but I'm not sure if excluding quite a few of these classes defeats the purpose of the test.

Looking forward to hearing your opinion about this.

Open questions:

  • Is support for Java 8 still needed considering that it's EOL?

@leonardehrenfried leonardehrenfried requested a review from a team as a code owner August 24, 2019 20:52
@leonardehrenfried
Copy link
Member Author

Hmm, the tests don't pass on Travis which is weird because the pass on my local machine, also running Java 11 and Linux.

Perhaps more classes need to be excluded?

@leonardehrenfried
Copy link
Member Author

leonardehrenfried commented Aug 25, 2019

Ok ignoring SoftReference does the trick but now I see lots of Javadoc errors.

It appears that Java 11 is a lot more strict with regards to the actual Javadoc syntax.

Are you ok with me cleaning these up?

@abyrd
Copy link
Member

abyrd commented Aug 28, 2019

Great to have a PR for this. I hope to try it out in the coming days and hopefully help get everything working. @leonardehrenfried do feel free to clean up Javadoc to meet the new exacting standards.

@leonardehrenfried
Copy link
Member Author

leonardehrenfried commented Sep 5, 2019

I have cleaned up the Javadoc so that it doesn't throw any errors on Java 11 anymore.

Looking forward to your review.

I also successfully built a graph and ran it (including debug layers) on Java 11! Very pleased with this!

@abyrd
Copy link
Member

abyrd commented Sep 6, 2019

Hi @leonardehrenfried. Thanks for raising the issue of Java 11+ compatibility and putting in the effort to solve these Jigsaw module problems. I had tried to migrate a smaller but related project at one point and ran into the same final roadblock: the ObjectDiffer used in the tests inherently works by reflection. I think it will be much easier for OTP to explicitly permit the module containing ObjectDiffer (kryo-tools) to perform reflection if kryo-tools is itself migrated to the Jigsaw module system. Fortunately this is our own project, so I can make the changes. I'm working on migrating that module, which is good training for then reviewing this PR and suggesting a fix to allow kryo-tools to perform reflection in tests.

@abyrd
Copy link
Member

abyrd commented Sep 6, 2019

Oh nice, I see you've added arguments to exceptionally allow reflection just during the tests. Maybe that's even better than module directives that would open things to reflection during non-test execution.

@leonardehrenfried
Copy link
Member Author

Exactly. This allows us to run kryo-tools as is without adding module information to it.

I'm not sure if that would help anyway, since you would have to add the permission to the java.base module, don't you? Or am I seeing this wrong?

@leonardehrenfried
Copy link
Member Author

leonardehrenfried commented Sep 6, 2019

One thing we ought to think about is Java 8 compatibility. Is it desired considering that it's EOL?

I'm not sure if there have been Java bytecode changes from Java 8 to 11 but if there are, then Java 8 will not be able to run code compiled for 11.

@abyrd
Copy link
Member

abyrd commented Sep 11, 2019

I'm not too concerned about maintaining compatibility. Java 8 has started disappearing from various build and deployment environments anyway and it's very easy to get a copy of 11 or higher.

I think your approach, making exceptions only during tests, is probably a good one. I'm going to continue with that kryo-tools Java 11 migration just to make sure I understand well enough how the whole system works.

abyrd
abyrd previously approved these changes Sep 11, 2019
Copy link
Member

@abyrd abyrd left a comment

Choose a reason for hiding this comment

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

I have built this locally and it works, thanks so much for working though this process! Having studied the question a but I do think adding "opens" switches to the test runner is the right approach for targeted white-box testing, as it still prevents reflection during normal non-test execution.

Also, it's good to update all these Maven plugins to more recent versions.

Once this is merged we'll port it over to the OTP2 branch.

@@ -78,7 +78,7 @@
</scm>

<properties>
<geotools.version>20.1</geotools.version>
<geotools.version>21.2</geotools.version>
Copy link
Member

Choose a reason for hiding this comment

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

I see Geotools 21 was the first version with Java 11 compatibility. I assume we aren't jumping to an even newer Geotools because of the transitive dependency on JTS, which has changed its package name and will conflict with other OTP dependencies?

Copy link
Member Author

Choose a reason for hiding this comment

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

I tought that 21.2 is the newest stable version: https://github.com/geotools/geotools/tags

Or would you like to use 22-RC?

Copy link
Member

Choose a reason for hiding this comment

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

Oh I suppose it is. I saw 23-SNAPSHOT and must have assumed there was already a 22 release. But now I see 22 is also still in SNAPSHOT. In that case then there's no question, 21.2 is fine.

@@ -259,10 +258,25 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<version>2.19.1</version>
Copy link
Member

Choose a reason for hiding this comment

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

I see that in c42ca0c you downgraded this due to a corrupted stream error. I'd like to eventually find and fix the root problem. Can you provide a link to the ticket you referenced in your commit message?

Copy link
Member Author

Choose a reason for hiding this comment

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

Of course, I will try again and clarify the commit message.

@@ -64,7 +64,7 @@ else if (CRS.getAxisOrder(destCrs) == CRS.AxisOrder.EAST_NORTH)
if (!destCrs.equals(sourceCrs)) {
transform = true;

// find the transformation, being strict about datums &c.
Copy link
Member

Choose a reason for hiding this comment

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

Personally I like ampersand-c. as a way to write "et cetera", as the ampersand is a ligature of Latin "et". It's fine to remove it though if it might confuse some people.

Copy link
Member

Choose a reason for hiding this comment

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

Oh I see, Javadoc is interpreting this as in HTML. Now I see why it's removed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Correct, Java 11 is way more strict with these HTML entities.

A big problem where also the < and > characters. I got a little creative and converted to unicode characters where possible. If not I just spelled them out with words.

Copy link
Member

@abyrd abyrd Sep 11, 2019

Choose a reason for hiding this comment

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

In my commits on the 2.x port, I used &gt; to replace > in some places, but that makes it kind of unreadable in a text editor. Although I managed to eliminate all the error messages, the most complete "solution" was to just turn off the doclint in the config in the POM.

Copy link
Member

Choose a reason for hiding this comment

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

Tip: In Intellij Ctrl+J (at leas with mac shortcuts) displays the formated text - I find it easier to read. So ,I tend to favor good readable formated JavaDoc over it to be easy to read in plain text.

@abyrd
Copy link
Member

abyrd commented Sep 11, 2019

@t2gran could you also review this?

abyrd added a commit that referenced this pull request Sep 11, 2019
Ports PR #2812 over to 2.x as a single commit.
@abyrd
Copy link
Member

abyrd commented Sep 11, 2019

@leonardehrenfried I ported this over to dev-2.x in PR #2829. You might want to cherry-pick my additional commit b121b85 from over there.

@leonardehrenfried
Copy link
Member Author

leonardehrenfried commented Sep 11, 2019

I've clarified why I downgraded the surefire plugin in the message of the rebased commit: ca708cc

@t2gran t2gran added the OTP1 Fix or backport to the 1.x version of OTP label Sep 13, 2019
@leonardehrenfried
Copy link
Member Author

@abyrd If you're concerned about the surefire downgrade, I'm happy to do more research about upgrading it together with an upgrade to Junit 5. I'd suggest to do that in a separate PR in order to limit the scope of this one.

@abyrd
Copy link
Member

abyrd commented Sep 13, 2019

Thanks @leonardehrenfried. I'm not really concerned about it as long as it runs the tests within the build as expected. I was thinking of putting a brief comment in the POM XML itself (rather than in the commit message) because this is where a contributor would be most likely to see it if/when they decide to upgrade the surefire plugin. Otherwise they might just see an "outdated" version and not understand it was an intentional choice. But having the comment on the commit message is good enough.

The combination of Java 11, the junit version, the surefire plugin version and
the plugin config `forkCount` and `reuseForks` caused a variety of
failures when running the tests, most frequently a ClassNotFoundException like this:

ClassNotFoundException: org.apache.maven.plugin.surefire.StartupReportConfiguration

It is not entirely clear what the correct way to fix this but it occurs
even when you use version 3.0.0-M3 of the surefire plugin, which is the
newest released version as of writing this. Perhaps also upgrading to
junit 5 might resolve this, but that seemed a little beyond the scope of
the PR.

The least invasive choice was to downgrade the surefire plugin version.

junit-team/junit5#1367
https://jira.apache.org/jira/browse/SUREFIRE-1520
https://issues.apache.org/jira/browse/SUREFIRE-1534
https://stackoverflow.com/questions/53437819/maven-surefire-and-jdk-11
This eliminates Maven warnings.
Arguably we might want Javadoc linting on, but it was already switched
off using a different parameter for an older Javadoc plugin version.
@leonardehrenfried
Copy link
Member Author

I played around with it a bit and i can make the build pass by excluding the package that is causing the Javadoc error:
<excludePackageNames>org.opentripplanner.graph_builder.module.ned:*</excludePackageNames>

Is this an acceptable solution?

@abyrd
Copy link
Member

abyrd commented Sep 17, 2019

@leonardehrenfried absolutely, we can exclude some classes from the Javadoc to avoid the problem. I already wasted to much time trying to make this class visible to the Javadoc tools. Just be sure to include a comment alongside the setting explaining why we're excluding this one package.

After everything I've been reading about the module system, I'm also wondering whether this system will ever really be adopted or will just create a worldwide mess. It seems quite flawed and appears to have mostly negative impacts on the average project, and this view is shared by several knowledgeable sources.

@t2gran
Copy link
Member

t2gran commented Sep 17, 2019

In our case we probably want org.opentripplanner.otp. 👍

@t2gran
Copy link
Member

t2gran commented Sep 17, 2019

I think we only need JavaDoc on the interface classes - documenting the API. Developers read the JAvaDoc in an IDE or the source.The API classes is needed because that is the place for the most up to date doc on the API. (In OTP2 we could drop the JavaDoc entierly, the GraphQL enpoints will have schema witch document them)

@leonardehrenfried I approved the review, because all my comments were not that important or on stuff that existed from before - feel free to fix these things, but my point was to give some hints for next time to improve.

@leonardehrenfried
Copy link
Member Author

@abyrd I've added a comment about the exclusion and also about the surefire downgrade. Regarding surefire, would you welcome a separate PR where I upgraded Junit and Surefire to their newest versions? And whilst I am cleaning up the build, can I also get rid of the dependency on osmpbf 1.3.4-SNAPSHOT (as mentioned in #2638)?

@t2gran While I was there I also incorporated your Javadoc review feedback.

t2gran
t2gran previously approved these changes Sep 17, 2019
@leonardehrenfried
Copy link
Member Author

I would absolutely love to get this merged. Is there any other improvement you'd like me to do?

@abyrd
Copy link
Member

abyrd commented Oct 12, 2019

@leonardehrenfried we are now working on finalizing this transition to Java 11+, hoping to do it within a few days. To answer your last question, yes if you want to do the work to research how to move Junit and Surefire to their newest versions, it would be nice to have a pull request to that effect. But it's not necessarily high priority.

I think we already have a path to update the PBF dependency to a newer version, though it doesn't really solve #2638 in the sense that it's still a forked library. But it's a forked library with one tiny patch so it doesn't really bother me. We released crosby.binary:osmpbf version 1.3.3-entur with a dependency on com.google.protobuf:protobuf-java version 3.8.0, to the Conveyal Maven repo, which is already in the OTP POM:

<repository>
  <id>conveyal</id>
   <name>conveyal</name>
  <url>https://maven.conveyal.com</url>
</repository>

Before we move to merge this PR #2812, I am going to revise #2829 (the port of this PR to OTP2) to see how well it works with no module-info at all, only declaring the automatic module name. We may also disable Javadoc publication there. It's good to have the module-info file around for future reference, but I think we should do the simplest thing that works to allow building on JDK11+.

abyrd added a commit that referenced this pull request Oct 12, 2019
Migrate to Java 11 (porting PR #2812, plus a few small changes)
@abyrd
Copy link
Member

abyrd commented Oct 14, 2019

@leonardehrenfried we have revised #2829 and merged it into the OTP2 dev branch. It has no module-info at all, and only declares an automatic module name. This seems to be working well. We will not be disabling Javadoc publication because deploying to Maven Central requires a Javadoc JAR.

Therefore, in this branch I suggest removing module-info from this PR and making sure <doclint>none</doclint> is set on the Javadoc generation in both surefire-plugin sections of the POM. Then we can merge it.

We can then introduce a module-info on the theoretical future day when all our dependencies declare their own module names.

@leonardehrenfried
Copy link
Member Author

Thanks for heads up @abyrd, but this pull request already has no module-info.java and uses <doclint>none</doclint>.

I changed that when you suggested it in #2812 (comment)

@leonardehrenfried
Copy link
Member Author

Hi @abyrd,

I know that this has been merged into 2.x but is it also going to land in OTP 1.5?

@leonardehrenfried
Copy link
Member Author

Java 14 has been released and Java 8 has been EOL for quite some time.

Would there be any chance to merge this into dev-1.x?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OTP1 Fix or backport to the 1.x version of OTP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Target Java 11
3 participants