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

SOLR-17321: Remove Deprecated URL API in Preparation for Java 21 #2501

Merged
merged 12 commits into from
Jun 21, 2024

Conversation

iamsanjay
Copy link
Contributor

@iamsanjay iamsanjay commented Jun 6, 2024

https://issues.apache.org/jira/browse/SOLR-17321

As we started preparing (#2497 ) the move to change the Java version for the main branch, It has been decided to merge the deprecated API changes first, and thus reducing the change burden for #2497.

Here we are replacing the deprecated URL with new Syntax using URI.

//Deprecated
URL url = new URL(urlStr);

to

URL url = URI.create(urlStr).toURL();

Checklist

Please review the following and check all that apply:

  • I have reviewed the guidelines for How to Contribute and my code conforms to the standards described there to the best of my ability.
  • I have created a Jira issue and added the issue ID to my pull request title.
  • I have given Solr maintainers access to contribute to my PR branch. (optional but recommended)
  • I have developed this patch against the main branch.
  • I have run ./gradlew check.
  • I have added tests for my changes.
  • I have added documentation for the Reference Guide

@iamsanjay
Copy link
Contributor Author

Though new Locale is deprecated, however the newer syntax Locale.of is not available in Java 11. Therefore It can only be done after migrating to Java21 or along with it.

Should we use forbidden APIs to Suppress the API which is forbidden in Java 21? Thread#getID and some other stuff related to SecurityManager.

Copy link
Contributor

@epugh epugh left a comment

Choose a reason for hiding this comment

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

This does make sense as the right route! Lgtm!!!

@epugh
Copy link
Contributor

epugh commented Jun 6, 2024

Seems a shame to add a to. Of suppress for locale and then remove it... might be cleaner to do that one as part of the upgrade.

@epugh
Copy link
Contributor

epugh commented Jun 6, 2024

As far as security manager goes, don't we need to just tackle that and solve the issue? Versus suppress it and ignore the problem?

@iamsanjay
Copy link
Contributor Author

As far as security manager goes, don't we need to just tackle that and solve the issue? Versus suppress it and ignore the problem?

Removing a SecurityManager will not be a simple task as some of these settings, I believe, were put in place to fix Security issues. For now, using forbidden would clear the path to the upgradation, Lucene did the same thing. However, now that the JDK has marked it for removal, future JDK upgradation would only be possible after removing it So we should start looking into it right after upgrading to Java 21.

And that's why I suggested marking SecurityManager, and related stuff, forbidden which is a viable solution for now.

@epugh
Copy link
Contributor

epugh commented Jun 6, 2024

As far as security manager goes, don't we need to just tackle that and solve the issue? Versus suppress it and ignore the problem?

Removing a SecurityManager will not be a simple task as some of these settings, I believe, were put in place to fix Security issues. For now, using forbidden would clear the path to the upgradation, Lucene did the same thing. However, now that the JDK has marked it for removal, future JDK upgradation would only be possible after removing it So we should start looking into it right after upgrading to Java 21.

And that's why I suggested marking SecurityManager, and related stuff, forbidden which is a viable solution for now.

yeah.. It sort of feels like that is the opposite of "get the code ready for java 21 first" like you are doing here with Url. However I also understand that it may spiral into a bigger thing. The important thing is to keep moving forward! Thanks for this.

@iamsanjay
Copy link
Contributor Author

Actually I started looking into it, the first issue that I found was "XXE attack in SolrConfig.xml" and a proposed fix (https://issues.apache.org/jira/browse/SOLR-12316). Afterwards the more improved version of fix involved SecurityManager as in running Solr in sandbox via SecurityManager (https://issues.apache.org/jira/browse/SOLR-13984).

And this was the comment!

The correct way to fix all issues we have seen the last time is very simple: LET'S RUN SOLR INSIDE A SECURITY MANAGER IN PRODUCTION (like in tests). Elasticsearch is doing this, so please please let's do this instead. But this requires to finally get rid of the webapplication and start.jar and add our own bootstrapping (like in tests) that configure Jetty and Security Manager from our own org.apache.solr.bootstrap.Main.java (or similar). -- Uwe

But I will keep on investigating, How and where Solr using SecurityManager?

@dsmiley
Copy link
Contributor

dsmiley commented Jun 6, 2024

Can we please keep the commentary here focused on what this PR title says this is about -- URL API?

Copy link
Contributor

@dsmiley dsmiley left a comment

Choose a reason for hiding this comment

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

Nice focused PR; thanks.

So did you find IntelliJ "structural replace" helpful? It's been quite a while since I last used it. It was clunkier than I wished... I wish it could detect when I'm trying to look for in a smarter way without me having to know the feature well. Ideally there would be a resource of popular/useful patterns, as one might expect there to be for JDK and major framework upgrades. Alas.

@epugh
Copy link
Contributor

epugh commented Jun 8, 2024

I like the forbidden api addition!

@iamsanjay
Copy link
Contributor Author

All the usages of new URL (except one) has been replaced with URI.create(url).toURL(). The exception was one specific case which is testing the presence of caret in the URL as It was an old issues (https://issues.apache.org/jira/browse/SOLR-5971) that failed due to the caret. Now replacing it with new Syntax fails because caret is in the disallowed list for URI and thus failed. I do not want to encode the character, because the whole point of test is to test caret without encoding it, instead I used @SuppressForbidden.

Because #2497 is still in progress, So, meanwhile, I added "new URL" to the forbidden api to make sure no one would use it.

solr/CHANGES.txt Outdated Show resolved Hide resolved
@iamsanjay
Copy link
Contributor Author

I added the changes under 9.7, I did not discussed this. So Should we consider this change for 10 only or release it in 9.7 as well?

@HoustonPutman
Copy link
Contributor

Backport it to 9.7 IMO

@epugh
Copy link
Contributor

epugh commented Jun 11, 2024

Agreed. When I added basic auth to the solr cli I did NOT backport it, and now it's a constant source of pain.

@iamsanjay
Copy link
Contributor Author

Going to merge this and back port to 9x on Friday, around 7PM IST.

Copy link
Contributor

@dsmiley dsmiley left a comment

Choose a reason for hiding this comment

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

Why use ForbiddenAPI for a deprecated thing? The JDK (with IDE support too) and javac already handle it in its own way. ForbiddenAPI principally exists for non-deprecated things we insist on not using.
cc @uschindler

@iamsanjay
Copy link
Contributor Author

Why use ForbiddenAPI for a deprecated thing?

As we are still in migration phase, It will not be deprecated until we move onto Java 21. Meanwhile, If someone tries to use it , they will get the warning message with an alternative API recommendation.

@uschindler
Copy link
Contributor

Why use ForbiddenAPI for a deprecated thing? The JDK (with IDE support too) and javac already handle it in its own way. ForbiddenAPI principally exists for non-deprecated things we insist on not using. cc @uschindler

In Java 11 it is not yet deprecated. So this allows to forbid it now.

Actually once we are on Java 21, the forbiddenapis signatures will complain, too (as deprecated APIs are reported, too). If you ask why forbiddenapis reports deprecated stuff: It's because normally during compilation, JDK only reports a warning for all deprecations (not only in the JDK also in your own code or dependencies). Forbiddenapis allows to restrict only JDK-forbidden stuff and you can keep other deprecations supressed. This is especially important for API developers, because you deprecate your own stuff but still have tests for it.

Copy link
Contributor

@uschindler uschindler left a comment

Choose a reason for hiding this comment

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

Actually this is partly a bit strange. In general the move should be to go away from URL completely. Theres code changed here which at some point creates an URL but later passes it to Jetty as URI. So It would be better to replace all URL by URI from beginning.

There are also some roundtrip conversions, please remove them.

@dsmiley
Copy link
Contributor

dsmiley commented Jun 13, 2024

What I love about our community is that we have so much expertise to call upon; thanks Uwe :-)

Forbiddenapis allows to restrict only JDK-forbidden stuff

Then lets do that and not single out a specific thing (URL).

@iamsanjay iamsanjay requested a review from uschindler June 16, 2024 16:19
Copy link
Contributor

@uschindler uschindler left a comment

Choose a reason for hiding this comment

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

Small change regarding exception handling in the POST tool, otherwise looks fine to me.

@@ -389,7 +389,7 @@ private void doWebMode() {
numPagesPosted = postWebPages(args, 0, out);
info(numPagesPosted + " web pages indexed.");

} catch (MalformedURLException e) {
} catch (URISyntaxException e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

URISyntaxException is only thrown by new URI(), the create function does not. Not sure how we should handle this.

See documentation of URI#create(String): "This convenience factory method works as if by invoking the URI(String) constructor; any URISyntaxException thrown by the constructor is caught and wrapped in a new IllegalArgumentException object, which is then thrown."

Copy link
Contributor

Choose a reason for hiding this comment

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

I would make this consistent to other code and prefer a clear exception.

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 started using URI.create for the same reason that you just explained as it throws unchecked exception which allows us to avoid explicitly handling the URISyntaxException.

Should we switch to new URI wherever we can without changing too much? I am open to that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think both is fine. I just noticed that the "catch" here looks obsolete (I wonder why compiler did not complain).

Copy link
Contributor Author

@iamsanjay iamsanjay Jun 17, 2024

Choose a reason for hiding this comment

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

doWebMode() is calling appendUrlPath that, as per new changes, is throwing URISyntaxException.

protected static URI appendUrlPath(URI uri, String append) throws URISyntaxException {
    var newPath = uri.getPath() + append;
    return new URI(uri.getScheme(), uri.getAuthority(), newPath, uri.getQuery(), uri.getFragment());
  }

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 have replaced the URI.create with new URI in PostTool.java. Also replaced in few test classes as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks great!

Copy link
Contributor

Choose a reason for hiding this comment

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

I have replaced the URI.create with new URI in PostTool.java. Also replaced in few test classes as well.

Actually you did this everywhere, which I am not sure if its a good idea. In PostTool i recommend to change this to get a consistent error message in both cases: for original URI and for the appendUrlPath() method.

I am not a big fan of checked Exceptions, so I would have used new URI only to make it consistent with the code around it.

Copy link
Contributor Author

@iamsanjay iamsanjay Jun 17, 2024

Choose a reason for hiding this comment

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

I've reverted the changes and updated it only for PostTool.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

git diff f2841ac..0007bb082 --name-only
solr/CHANGES.txt
solr/core/src/java/org/apache/solr/cli/PostTool.java

@iamsanjay
Copy link
Contributor Author

Ran the failed test multiple times and it's passing. Flaky!

ERROR: The following test(s) have failed:
  - org.apache.solr.client.solrj.TestLBHttp2SolrClient.testTwoServers (:solr:solrj)
    Test history: https://ge.apache.org/scans/tests?search.rootProjectNames=solr-root&tests.container=org.apache.solr.client.solrj.TestLBHttp2SolrClient&tests.test=testTwoServers http://fucit.org/solr-jenkins-reports/history-trend-of-recent-failures.html#series/org.apache.solr.client.solrj.TestLBHttp2SolrClient.testTwoServers
    Test output: /tmp/src/solr/solr/solrj/build/test-results/test/outputs/OUTPUT-org.apache.solr.client.solrj.TestLBHttp2SolrClient.txt
    Reproduce with: ./gradlew :solr:solrj:test --tests "org.apache.solr.client.solrj.TestLBHttp2SolrClient.testTwoServers" -Ptests.jvms=96 "-Ptests.jvmargs=-XX:TieredStopAtLevel=1 -XX:+UseParallelGC -XX:ActiveProcessorCount=1 -XX:ReservedCodeCacheSize=120m" -Ptests.seed=BC6F7BFC1228CAE8 -Ptests.timeoutSuite=600000! -Ptests.file.encoding=ISO-8859-1
FAILURE: Build failed with an exception.

It recently started failing (I hope I am looking at it in a right way!)

Screenshot 2024-06-17 at 9 48 33 PM

PS :- Thank You @dsmiley. Test history URL in Action!

@iamsanjay iamsanjay requested a review from uschindler June 18, 2024 12:13
@iamsanjay
Copy link
Contributor Author

If there are no more comments/issues, I would like to merge this by Friday. Thanks!

@iamsanjay iamsanjay merged commit 2a56bfc into apache:main Jun 21, 2024
4 checks passed
iamsanjay added a commit to iamsanjay/solr that referenced this pull request Jun 21, 2024
…pache#2501)

* Switch to URI
* Added URL to the forbidden API

-------------

Co-authored-by:  Uwe Schindler <[email protected]>
Co-authored-by: David Smiley <[email protected]>
(cherry picked from commit 2a56bfc)
@@ -109,7 +110,7 @@ public static void runReplicationHandlerCommand(
}

static void executeHttpRequest(String requestUrl) throws IOException {
URL url = new URL(requestUrl);
URL url = URI.create(requestUrl).toURL();
Copy link
Contributor

Choose a reason for hiding this comment

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

This is causing TestSolrCoreSnapshots.testBackupRestore to fail on Windows machines.

java.lang.IllegalArgumentException: Illegal character in query at index 117: http://127.0.0.1:64027/solr/admin/cores?action=BACKUPCORE&core=SolrCoreSnapshots_shard1_replica_n1&name=u&location=C:\Users\jenkins\workspace\Solr-main-Windows\solr\core\build\tmp\tests-tmp\org.apache.solr.core.snapshots.TestSolrCoreSnapshots_9D4706448466E215-001\tempDir-002&incremental=false&commitName=ydfbp
	at __randomizedtesting.SeedInfo.seed([9D4706448466E215:2BFC06FAB6D52C5B]:0)
	at java.base/java.net.URI.create(URI.java:883)
	at org.apache.solr.handler.BackupRestoreUtils.executeHttpRequest(BackupRestoreUtils.java:113)

iamsanjay added a commit that referenced this pull request Aug 22, 2024
…r Java 21 (#2528)

* SOLR-17321:  Remove Deprecated URL ctors in Preparation for Java 21 (#2501)

* Switch to URI
* Added URL to the forbidden API

-------------

Co-authored-by:  Uwe Schindler <[email protected]>
Co-authored-by: David Smiley <[email protected]>
(cherry picked from commit 2a56bfc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants