2

All URL constructors are deprecated in Java 20. I replaced new URL(protocol, host, file) by new URI(protocol, host, file, null).toURL() as I have no query and no fragment but I don't know what to do with the others:

/home/gouessej/Documents/programmation/java/workspace/Ardor3D/ardor3d-core/src/main/java/com/ardor3d/util/UrlUtils.java:40: warning: [deprecation] URL(String) in URL has been deprecated
        return new URL(new URL(url), relativeLoc);
                       ^
/home/gouessej/Documents/programmation/java/workspace/Ardor3D/ardor3d-core/src/main/java/com/ardor3d/util/UrlUtils.java:40: warning: [deprecation] URL(URL,String) in URL has been deprecated
        return new URL(new URL(url), relativeLoc);
               ^
/home/gouessej/Documents/programmation/java/workspace/Ardor3D/ardor3d-core/src/main/java/com/ardor3d/util/resource/SimpleResourceLocator.java:94: warning: [deprecation] URL(URL,String) in URL has been deprecated
            final URL rVal = new URL(_baseDir.toURL(), spec);
                             ^
/home/gouessej/Documents/programmation/java/workspace/Ardor3D/ardor3d-audio/src/main/java/com/ardor3d/audio/FilenameURL.java:125: warning: [deprecation] URL(String) in URL has been deprecated
                    url = new URL( filename );

Would simply new URI(filename).toURL()do the job in the last case?

When I compare the wording in the Java documentation, I understand that an URI scheme means more or less a URL protocol, an URI host is an URL host and an URL file matches with a URI path and an optional URI query. What are the exact equivalent of new URL(spec) and new URL(context, spec)?

I prepared some suggested changes but it doesn't work, an IllegalArgumentException is thrown.

gouessej
  • 3,640
  • 3
  • 33
  • 67
  • 1
    *Would simply new URI(filename).toURL()do the job in the last case?* I would say so, from reading the URI doc. But it'll only take 5 minutes to try it and see, – Arfur Narf Apr 08 '23 at 15:57
  • 1
    If you want to construct a `file:` scheme URI, then File has a [toURI method](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/io/File.html#toURI()). – teapot418 Apr 08 '23 at 15:59
  • 1
    The `context,spec` thing can probably be done by `URI.resolve()`? – teapot418 Apr 08 '23 at 16:01
  • 1
    Indeed, that very same javadoc states: "The recommended way to manage the encoding and decoding of URLs is to use `URI`, and to convert between these two classes using `toURI()` and `URI.toURL()`." So the answer to your first question is yes. The answer to your second question, as teapot pointed out, is `new URI(context).resolve(spec).toURL()`. – VGR Apr 08 '23 at 22:49
  • @ArfurNarf It's not so trivial because I can't test all possible special cases depending on file systems. Imagine that it works on a simple case but it doesn't work in another case because a special character isn't escaped. I would like to understand formally how to replace those calls once for all. – gouessej Apr 09 '23 at 00:34
  • @VGR Actually, your comment clarifies teapot418's suggestion. Thanks. – gouessej Apr 09 '23 at 00:53
  • @VGR I obtain `java.lang.IllegalArgumentException: URI is not absolute` when I call `new URI(context).resolve(spec).toURL()`. – gouessej Apr 09 '23 at 13:30
  • Yes, and [the method's documentation](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/net/URI.html#toURL()) tells you that you will get that exception. Is there a reason you're using relative URIs? – VGR Apr 09 '23 at 14:04
  • @VGR It's a utility of the engine. At the beginning, it was used to work around some bugs or limitations of the URL class. I'll isolate the problem in a tiny unit test. – gouessej Apr 09 '23 at 17:17
  • If you are trying to make URLs out of relative filenames, I find myself wondering if you’re actually trying to access data built into your application. If that is the case, you should not be creating URLs yourself at all; you should use [Class.getResource](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/lang/Class.html#getResource(java.lang.String)) for that. You should never rely on relative filenames, since the current directory usually is not something you can control. – VGR Apr 10 '23 at 12:17
  • The method is in a utility, it's used both for files on the local filesystem and files from the Internet. – gouessej Apr 10 '23 at 22:38

1 Answers1

9

tl;dr

  • To construct a URL, use URI::toURL.
  • To construct a file: based URL, (1) call Path::toURI, (2) then URI::toURL.

Details

Understand that:

  • java.net.URL is an ancient class, dating from Java 1. That class does not encode or decode any URL components according to the RFC 2396 escaping mechanism.
  • java.net.URI class came later, in Java 4.

Read this note from the Java team, Oracle: Quality Outreach Heads-up - JDK 20: Deprecate URL Public Constructors. To quote:

JDK 20 will deprecate all public constructors of java.net.URL. … To construct a URL, the URI::toURL alternative should instead be preferred. To construct a file: based URL, Path::toURI should be used prior to URI::toURL.

And see the note on constructor deprecation within the Javadoc of URL class.

See also the issue-tracker page, JDK-8294241 Deprecate URL public constructors.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    Thank you for your elaborated answer. I'll carefully try your suggestions, especially Path.toURI().toURL(). – gouessej Apr 09 '23 at 00:48
  • @gouessej If this Answer solved your problem, please accept it by marking the big check mark. This Question can be used to strike other Questions as duplicates only if an Answer is accepted. – Basil Bourque May 01 '23 at 15:19
  • Sorry for the long delay. I still have to isolate a few corner cases. – gouessej May 04 '23 at 20:38